- 是什么?
守护进程又称精灵进程,是运行在后台的一种特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件,守护进程是一种很有用的进程。Linux的大多数服务器就是用守护进程实现的。比如ftp服务器,ssh服务器,web服务器httpd等。同时,守护进程完程许多系统任务,比如企业规划进程crond等。 - 如何创建?
创建守护进程最关键的一步是调用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)如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。
3. 代码如何编写,关键步骤是哪些?
代码如下:
#include<stdio.h>
2
3 #include<unistd.h>
4 #include<signal.h>
5 #include<stdlib.h>
6 #include<fcntl.h>
7 #include<sys/stat.h>
8 void mydaemon()
9 {
10 int i;
11 int fd0;
12 pid_t pid;
13 struct sigaction sa;
14 umask(0);
15 if((pid = fork())<0)
16 perror("fork\n");
17 else if(pid>0)
18 {
19 exit(0);
20 }
21 setsid();
22 sa.sa_handler = SIG_IGN;
23 sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
25 if(sigaction(SIGCHLD,&sa,NULL)<0)
26 {
27 return;
28 }
29 if((pid=fork())<0)
30 {
31 printf("fork error");
32 return;
33 }
34 else if(pid !=0)
35 {
36 exit(0);
37 }
38 if(chdir("/")<0)
39 {
40
41 printf("child dir error\n");
42 return;
43
44
}
45 close(0);
46 fd0=open("/dev/null",O_RDWR);
47 dup2(fd0,1);
48 dup2(fd0,2);
49 }
50 int main()
51 {
52 mydaemon();
53 while(1)
54 {
55 sleep(1);
56 }
57
58 }
58,1 底端
44,1 60%
运行结果:
由图可知守护进程创建完成。
关键步骤:
1、调用umask将文件模式创建屏蔽字设置成0,
2、调用fork父进程退出,如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止使得shell认为该命令已经执行完毕,保证子进程不是进程组的组长进程。
3、使用setsid创建一个新会话
4、忽略SIGCHLD信号,
5、注册子进程退出忽略信号
6、再次fork终止父进程,保证子进程不是话首进程,从而保证后续不会在和其他中端关联
7、将当前目录改为根目录,
8、关闭不再需要的文件描述符,或者重定向到/dev/null
4. 为什么创建守护进程时有人fork两次?
为了保证创建的子进程不是话首进程,从而·保证后续不会再与其他终端产生关联,从而达到守护进程的概念,独立于控制终端而独立运行。