守护进程(daemon)
了解守护进程必须要先了解进程组、作业、会话,这三个概念已经在上一篇blog中介绍过了。
1.定义
守护进程独立于控制端并周期性地执行某种任务或等待处理发生的某些事件 ;
2.特点:
①守护进程的命名都是以d结尾;
②守护进程不受用户登录和注销的影响,当会话终止时,后台登录和注销受到影响,但不影响守护进程;
③守护进程的PPID即父进程都为1,大部分守护进程的PID,PGID,SID都相同;
④所有的守护进程自成进程组,自成会话,所以它们的PID,PGID,SID相同;
⑤大部分的守护进程都是孤儿进程;
⑥守护进程完成许多系统任务,Linux的大多数服务器都是用守护进程实现的;
如图所示:
3 . 创建守护进程的函数:
pid_t setsid(void);
函数返回值:调用成功时,返回当前进程的ID,出错时返回-1;
使用函数的条件:当前进程不能为进程组长,所以可以先fork( )一个子进程,再调用这个函数,该子进程不可能为进程组的首进程,即不可能为进程组长;
4.为什么守护进程的父进程都为一号进程?
由setsid()的使用条件可知,必须要先fork( )一个子进程,fork()完后将父进程退出,子进程被一号进程回收,它的PPID就为1,所以所有守护进程的父进程都为一号进程。
5.创建守护进程的步骤:
①调用umask将文件模式创建屏蔽字设置为0;
②调用fork( ),并退出父进程;
③调用setsid( )创建一个新的会话;
④将当前工作目录更改为根目录;
⑤关闭终端描述符,因为守护进程与终端无关;
⑥忽略SIGCHLD信号;
6.自己创建守护进程:
#include<unistd.h>
#include<stdio.h>
#include<signal.h>
void mydaemon()
{
umask(0);//①文件模式创建屏蔽字设置为0;
if(fork()>0)//②调用fork( ),并退出父进程;
{
exit(0);
}
setsid();//③调用setsid( )创建一个新的会话;
chdir("/");//④将当前工作目录更改为根目录;
close(0);//⑤关闭终端描述符;
close(1);
close(2);
signal(SIGCHLD,SIG_IGN);//⑥忽略SIGCHLD信号;
}
int main()
{
mydaemon();
//还可以直接调用系统的deamon(0,0);
while(1);
}
7.为何有时会fork( )两次?
(1) 第一次fork( )的作用:
①保证子进程不是组长进程,就可以调用setsid()创建会话;
②父进程退出后,让shell认为该命令已经执行完毕;(2)第二次fork( )的作用:
防止进程打开了新的控制终端。
** 因为打开一个新的终端的前台条件是该进程是会话首进程,第二次fork( )后,产生子进程,父进程退出,不会是会话首进程,也就无法打开控制终端。
** 第二次的fork( )是可选的,不是必要的。
8.
所以,守护进程也叫作精灵进程,是运行在后台的一个特殊进程,是一个很有用的进程,和以前学习的僵尸进程完全不同,它能够完成许多系统任务,可以继续了解它。