(一)守护进程是什么?
守护进程即使运行在后台他,不依赖于终端的一种服务型进程。该进程是一种很有用的进程, Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任务。 比如,作业规划进程crond,打印进程lpd等。
(二)为什么需要守护进程
(1)脱离终端,一般的进程是依赖于终端的,当终端关闭时,该终端史所依赖的进程会关闭。
(2)守护进程可以很大程度的节约系统资源。
(三)守护进程如何创建?
步骤:
(1)脱离父进程,实现在后台运行。
(2)脱离会话终端,登录会话和进程组。由于会话组对终端的独占性,每个会话组只能有一个终端,所以,使用setsid()函数重新创建一个会话组,使得该会话组的会话组长为该进程,这就使得该进程可以脱离了原来的会话组,即脱离终端。
(3)禁止进程重新打开控制终端。由于该会话组的会话组长依然有创建终端的能力,所以需要重新创建子进程来避免创建终端 。这里需要强调的是,在调用setsid之前必须保证调用函数进程不是组长进程,上面的fork确定保证了这一步。
(4)关闭打开的文件描述符。进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。
(5)改变进程工作路径。当该进程工作时,该进程所在的文件系统不能卸载,所以为了保险起见,一般把该进程的工作路径改为根目录。
(6)重设文件创建掩模。进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0)。
(7)处理SIGCHLD信号。处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结 束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下 可以简单地将 SIGCHLD信号的操作设为SIG_IGN。signal(SIGCHLD,SIG_IGN);这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。
(四)代码实现
(1)系统自带的daemon()函数直接创建守护进程(推荐使用)
(2)C代码实现:
static int daemon_instance()
{
pid_t pid;
int i = 3;
if ((pid = fork()) < 0)
{
exit(0);
}
else if (pid > 0)
{
exit(0);
}
if (setsid() < 0)
{
exit(-1);
}
if ((pid = fork()))
{
exit(0);
}
if (chdir("/") < 0)
{
exit(0);
}
umask(0);
for(i = 0; i < getdtablesize(); i++)
{
close(i);
}
return 0;
}