守护进程&创建守护进程&fork一次和fork两次的区别

3/3/2017来源:C/C++教程人气:941

 我们先来了解一下什么是守护进程? 守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是生存期长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。 疑问守护进程的特点: (1)linux系统启动时会启动很多系统服务进程,守护进程没有控制终端,不能直接和用户交互 (2)其他进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但守护进程不受用户登录注销的影响,只受开机或者关机的影响。 疑问守护进程存在的原因: daemon函数存在的原因是因为控制终端由于某些原因(如断开终端链接)会发送一些信号的原因。而接收处理这些信号的缺省动作会让进程退出。这些信号会由于终端上敲一些特殊按键而产生。 疑问守护进程和后台进程的区别: (1)守护进程是后台进程,后台进程不一定是守护进程 (2)守护进程运行是与终端无关的,是不能往终端上打消息的 (3)守护进程的会话组和当前目录,文件描述符都是独立的。后台运行只是终端进行了一次fork,让程序在后台执行 疑问创建守护进程: 创建守护进程最关键的一步是调用setsid函数创建一个新的session,并成为Session Leader。 #include<unistd.h> pid_t setsid(void); 该函数调用成功时返回新创建的Session的id(其实也就是当前进程的id),出错返回-1。注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进程组的Leader也很容易,只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进 程组中,进程组的Leader必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,在子进程中调用setsid就不会有问题了。 成功调用该函数的结果是: (1)创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。 (2)创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。 (3)如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。 创建守护进程的步骤: (1)调用umask将文件模式创建屏蔽字设置为0 (2)父进程fork出子进程,然后子进程调用setsid,父进程直接退出(保证了子进程不是一个进程组的组长), (3)调用setsid创建一个新的会话(调用成功会使调用进程成为新会话的首进程,并且成为一个进程组的组长进程,调用进程没有控制终端) (4)将当前工作目录更改为根目录 (5)关闭不在需要的文件描述符 (6)忽略SIGCHLD信号 下面是我写的创建守护进程的代码(fork两次): 疑问大笑要知道在创建守护进程的时候fork一次和fork两次两者有什么区别,就要先知道第一次fork和第二次fork都起到了什么作用: (1)调用一次fork的作用:     第一次fork的作用是让shell认为这条命令已经终止,不用挂在终端输入上,还有就是为了后面的setsid服务,因为调用setsid函数的进程不能是进程组组长,如果不fork出子进程,则此时的父进程是进程组组长,就无法调用setsid。当子进程调用完setsid函数之后,子进程是会话组长也是进程组组长,并且脱离了控制终端,此时,不管控制终端如何操作,新的进程都不会收到一些信号使得进程退出。 (2)第二次fork的作用: 虽然当前关闭了和终端的联系,但是后期可能会误操作打开了终端。 只有会话首进程能打开终端设备,也就是再fork一次,再把父进程退出,再次fork的子进程作为守护进程继续运行,保证了该精灵进程不是对话期的首进程, 第二次不是必须的,是可选的,市面上有些开源项目也是fork一次