守护进程也称精灵进程,是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。linux大多数服务器就是用守护进程实现的。
linux系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能直接和用户交互。其他进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行,这种进程有一个名称叫守护进程。
查看系统中的守护进程–指令:ps axj | grep -E ‘d$’
创建守护进程最关键的一步是调用setsid函数创建一个新的Session,并成为Session Leader.
成功调用该函数的结果是:
1、创建一个新的Session,当前进程成为Session Leader, 当前进程的id就是Session的id.
2、创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id.
3、如果当前进程原本有一个控制终端,则它失去一个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。
创建守护进程
1、调用umask将文件模式创建屏蔽字设置为0.
2、调用fork,父进程退出(exit)。原因:1)、如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止使得shell认为该命令已经执行完毕。2)、保证子进程不是一个进程组的组长进程。
3、调用setsid创建一个新会话。setsid会导致:1)、调用进程成为新会话的首进程。2)、调用进程成为一个进程组的组长进程。3)、调用进程没有控制终端(再次fork一次,保证daemon进程,之后不会打开tty设备)
4、将当前工作目录更改为根目录。
5、关闭不在需要的文件描述符。
6、其他:忽略SIGCHLD信号。
程序代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/stat.h>
#include<sys/types.h>
void mydamon()
{
umask(0);
if (fork() > 0)
{
exit(0);
}
setsid();
if (fork() > 0)
exit(0);
chdir("/");
close(0);
close(1);
close(2);
signal(SIGCHLD, SIG_IGN);
}
int main()
{
mydamon();
while (1){ }
return 0;
}
程序运行结果:
也可以调用函数创建守护进程
程序中第一次fork的作用:是让shell认为这条命令已经终止,不用挂在终端输入上,还有就是为了后面的setsid服务,因为调用setsid函数的进程不能是进程组组长,如果不fork出子进程,则此时的父进程是进程组组长,就无法调用setsid。当子进程调用完setsid函数之后.,子进程是会话组长也是进程组组长,并且脱离了控制终端,此时,不管控制终端如何操作,新的进程都不会收到一些信号使得进程退出。
第二次fork的作用:
虽然当前关闭了和终端的联系,但是后期可能会误操作打开了终端。只有会话首进程能打开终端设备,也就是再fork一次,再把父进程退出,再次fork的子进程作为守护进程继续运行,保证了该精灵进程不是对话期的首进程。当然第二次fork不是必须的。