一、守护进程
守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任务。比如,作业规划进程crond等。
其他进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直运行着,这种进程有一个名称叫守护进程。
命令查看系统中的进程: ps axj(a表示不仅列出当前用户的进程,也列出所有其他用户的进程,x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,j表示列出与作业控制相关的信息)
TPGID的-1表示没有终端控制的进程,就是守护进程。COMMAND用[]括起来的表示内核线程,没有用户空间代码,因此没有程序文件名和命令行,通常采用以k开头名字,表示Kernel。守护进程通常以d结尾的名字,表示Daemon。
二、创建守护进程
1.调用setsid函数
创建守护进程最关键的一步是调用setsid函数创建一个Session,并成为Session Leader。
该函数成功调用时返回新创建的Session的id(当前进程的id),出错返回-1。
注意:调用这个函数之前,当前进程不允许是进程的Leader,否则该函数返回-1。(先fork再调用setsid)
2.成功调用该函数的结果
1)创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
2)创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
3)如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。(原控制终端仍然是打开的,可以读写,但只是一个普通的打开文件文件)
3.创建守护进程的步骤
1)调用fork()创建子进程,然后exit退出父进程,保证所有任务都是在子进程下工作;
2)调用setsid在子进程中创建一个新会话;
3)将当前工作目录更改为根目录;(防止受到上层目录的影响)
4)将umask的值设置为0,这样就可以创建想要权限的文件,防止受到umask的影响;
5)关闭不需要的文件描述符,一般来说就是关闭默认的0,1,2三个文件描述符
6)忽略掉SIGCHLD信号
编写代码如下:
查看守护进程,将./mydaemon变成了守护进程。
创建守护进程还可以运用库函数daemon()
#include<unistd.h>
int daemon(int unchdir,int unclose)
三、为什么要fork两次?
第一次fork:这里第一次fork的作用就是让shell认为这条命令已经终止,不用挂在终端输入上;再一个是为了后面的setsid服务,因为调用setsid函数的进程不能是进程组组长,如果不fork子进程,那么此时的父进程是进程组组长,无法调用setsid。所以到这里子进程便成为了一个新会话组的组长。
第二次fork: 第2次fork不是必须的。也看到很多开源服务没有fork第二次。fork第二次主要目的是。防止进程再次打开一个控制终端。因为打开一个控制终端的前台条件是该进程必须是会话组长。再fork一次,子进程ID != sid(sid是进程父进程的sid)。所以也无法打开新的控制终端。