对于操作系统中的守护进程,它是运行在后台的一种特殊的进程。它独立于控制终端,并且周期性的执行某种任务或等待处理某些发生的事件。守护进程是一种很用用的进程,大多数服务器就是用守护进程实现的。
守护进程又名精灵进程,它与其他进程不同,其他进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止。而它们系统服务进程不受那些因素影响。
* 守护进程是后台进程,运行与终端无关。不能往前台输出数据。
一、命令:
通常我们使用 ps axj 命令来查看系统中的进程。
参数a表⽰示不仅列当前⽤用户的进程,也列出所有其他⽤用 户的进程,参数x表⽰示不仅列有控制终端的进 程,也列出所有⽆无控制终端的进程,参数j表⽰示列出与 作业控制相关的信息。
以d结尾的都是守护进程
ps axj |grep -E 'd$' 查找以d结尾的进程
二、守护进程的创建
创建守护进程最关键的一步是调用setsid函数创建一个新的session,并成为session Leader;
在调用setsid时,进程必须是非组长进程;对于setsid调用成功时返回新创建的Session的id,如果出错就回-1;要保证当前进程不是进程组的Leader也很容易,只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进 程组中,进程组的Leader必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,在子 进程中调setsid就不会有问题了。
屏蔽字设置为0;
2、调用fork,父进程退出(exit);
* shell分前后台控制的是作业 作业内部创建进程属于进程组 不属于作业。
b:保证子进程不是组长进程;
3、调用setsid创建一个新的会话。
setsid会导致:a:调用进程成为新会话的首进程;
b:调用进程成为一个进程组的组长进程;
c:调用进程没有控制终端。
在此有些在创建守护进程时fork两次 (再次fork一次,保证daemon进程,之后不会打开tty设备);
4、将当前工作目录更改为根目录。
5、关闭不再需要的文件描述符。
6、其他:忽略SIGCHLD信号。
自己创建守护进程:
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/stat.h>
void creat_daemon()
{
int i;
int fd0;
pid_t pid;
struct sigaction sa;
umask(0);//设置文件掩码位0;
if(pid=fork()<0)
{}
else if(pid!=0)
{
exit(0);
}
setsid(); //设置新会话
sa.sa_handler=SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
if(sigaction(SIGCHLD,&sa,NULL)<0)
{
return;
}
if((pid=fork())<0)
{
printf("fork error!\n");
return;
}
else if(pid!=0)
exit(0);
if(chdir("/")<0)
{
printf("child dir error\n");
return;
}
close(0);
fd0=open("/dev/null",O_RDWR);//关闭标准输入,重定向所有标准到/dev/null
dup2(fd0,1);
dup2(fd0,2);
}
int main()
{
creat_daemon();
while(1)
{
sleep(1);
}
}