守护进程
Posted Alex
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了守护进程相关的知识,希望对你有一定的参考价值。
1. 守护进程:
守护进程也成精灵进程,是生成期较长的一种进程。他们常常在系统自举时启动,仅在系统关闭时才终止。因为他们没有控制终端,所以他们在后头运行。
2. ps查看守护进程的特征:
大多数守护进程以超级用户(用户ID=0)特权运行,守护进程均没有控制终端,其终端名设置为?,终端前台进程组ID设置为-1;内核守护进程以无终端的方式启动。用户层守护进程缺少控制终端可能是守护进程调用了setsid的结果。所有用户层紧都是进程组的组长进程以及会话的首进程,而且是这些进程组和会话中的唯一进程。最后,应当引起注意的是大多数守护进程的父进程都是init进程;
3. 函数原型:
#include <unistd.h> int daemon(int nochdir, int noclose); ret=成功返回0,失败返回-1
nochdir- =0,切换工作目录到 /
noclose- =0,标准输入输出错误输出重定向到/dev/null
4. 常用编程模型:
1 #include <unistd.h> 2 #include <stdio.h> 3 4 int do_sth() 5 { 6 //Add what u want 7 return 0; 8 } 9 int main() 10 { 11 daemon(0,0); 12 while ( 1 ) 13 { 14 do_sth(); 15 sleep(1); 16 } 17 }
5. 守护进程惯例:
(1) 若守护进程使用锁文件,那么该文件通常存放在/var/run目录中。注意,守护进程可能需具有超级用户权限才能在此目录下创建文件。锁文件的名字通常是name.pid,其中,name是该守护进程或者服务的名字。例如:cron守护进程的锁文件名字是/var/run/crond.pid
(2) 若守护进程支持配置选项,那么配置文件通常存放在/etc目录中。配置文件的名字通常是name.conf,其中,name是该守护进程或服务的名字。例如syslogd的配置文件是/etc/syslog.conf
(3) 守护进程可用命令行启动,但通常他们是由系统初始化脚本之一(/etc/rc*或者/etc/init.d/*)启动的。如果在守护进程终止时,应当自动的重新启动他,则我们可以在/etc/inittab中为 该守护进程包括_respawn记录锁,这样,init就将重启该守护进程;
(4) 若一守护进程有一配置文件,那么当守护进程启动时,它读该文件,但是在此后一般就不会再查看它。若以管理员更改了配置文件,那么该守护进程可能需要被停止,然后再启动,以使配置文件更改生效。为避免这种麻烦,某些守护进程将捕捉SIGHUP信号,当他们接收到该信号的时候,重读配置文件。因为守护进程并不与终端相结合,它们或者是无控制终端的会话首进程,或者是孤儿进程组成员,所以守护进程并不期望接收SIGHUP,于是可以安全的使用它;
6. daemon()实现规则:
(1) 调用umask将文件的模式创建屏蔽字设置为0;由继承得来的文件模式创建屏蔽字可能会拒绝设置某些权限。例如,若守护进程需要创建一个组可读、写的文件,而集成的文件模式创建屏蔽字可能屏蔽了这两种权限,于是所要求的组可读、写就不能起作用;
(2) 调用fork,然后父进程退出(exit);这样做实现了以下几点:第一,如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止使得shell认为这条命令已经执行完毕;第二,子进程继承了父进程的进程组ID,但具有一个新的进程ID,这就保证了子进程不是一个进程组的组长进程。这是下面调用setsid的必要前提条件;
(3) 调用setsid以创建一个新会话。这样使进程(a)成为新会话的首进程(b)成为一个新进程组的组长进程(c)没有控制终端;
(4) 将当期工作目录更改为根目录;从父进程继承过来的当期工作目录可能在一个装配文件系统中。因为守护进程通常实在系统再引导之前是一直存在的,所以如果守护进程的当期工作目录在一个装配文件系统中,那么该文件系统就不能被拆卸;这与装配文件系统的原意不符;
(5) 关闭不再需要的文件描述符。这使守护进程不再持有从父进程继承而来的某些文件描述符。
(6) 某些守护进程打开/dev/null使其具有文件描述符0,1,2,这样,任何一个试图读标注输入,写标准输出或者标准错误输出的库例程都不会产生任何效果。
以上是关于守护进程的主要内容,如果未能解决你的问题,请参考以下文章
20. Gradle编译其他应用代码流程(七) - 守护进程编译