(一)、基本概念
1、守护进程是脱离于终端并且在后台运行的进程 。 守护进程脱离于终端是为了避免进
程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息
所打断 。
2、守护进程是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或
等待处理某些发生的事件。 守护进程常常在系统引导装入时启动,在系统关闭时终止
2、大多数服务是通过守护进程实现的
3、守护进程能够突破终端限制,终端关闭,但是守护进程还在
创建守护进程的步骤
(一)、创建子进程,父进程退出
在 Shell 终端里造成一程序已经运行完毕的假象。 之后的所有工作都在子进程中完成,而用
户在 Shell 终端里则可以执行其他命令,从而在形式上做到了与控制终端的脱离 。
(二)、在子进程中创建新会话
概念:
1)、会话:当用户在某个终端上登录时,一个新的会话就开始了
2)、进程组:是一个或多个进程的集合,其组长进程的进程号等于进程组 ID ,且该进程组 ID
不会因组长进程的退出而受到影响
3)、会话周期:会话期是一个或多个进程组的集合 。 通常, 一个会话开始与用户登录,
终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期
setsid 函数用于创建一个新的会话,并担任该会话组的组长。 调用 setsid 有 3 个作用 :
①让进程摆脱原会话的控制;
②让进程摆脱原进程组的控制;
③让进程摆脱原控制终端的控制 。
由于在调用了 fork 函数时,子进程全盘拷贝了父进程的会话期 、 进程组 、 控制终端等,虽然
父进程退出了,但会话期、进程组 、 控制终端等并没有改变,因此,还不是真正意义上的独立 。
而 setsid 函数能够使进程完全独立出来,从而摆脱其他进程的控制 。
(三)、改变当前目录为根目录
使用 fork 创建的子进程继承了父进程的当前工作目录。 由于在
进程运行中,当前目录所在的文件系统(如/mnt/usb )是不能卸载的,这对以后的使用会造
成诸多的麻烦
因此,通常的做法是让 ”/”作为守护进程的当前工作目录,这样就可以避免上述的问题。 当然,
如有特殊需要,也可以把当前工作目录换成其他的路径 。
(四)、重设文件权限掩码 。
文件权限掩码是指屏蔽掉文件权限中的对应位 。 比如,有个文件权限掩码是 050 ,它就
屏蔽了文件组拥有者的可读与可执行权限
把文件权限掩码设置为0 ,可以大大增强该守护进程的灵活性 。 设置文件权限掩码的函数是 umask ,通常的使用方法
为 umask(0)。
(五)、关闭文件描述符
同文件权限码一样,用 fork 函数新建的子进程会从父进程那里继承一些已经打开了的文
件。 这些被打开的文件可能永远不会被守护进程读写,但它们一样消耗系统资源,而且可能
导致所在的文件系统无法结束 。
所以,文件描述符为 0 、 l 和 2 的 3 个文件(常说的输入、输出和报错)已经失去
了存在的价值,也应被关闭 。 通常按如下方式关闭文件描述符 :
for(i=O ; i<MAXFILE;i ++)
close(i) ;
示例代码
/**
* 守护进程
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h> // 提供open等函数
#include<unistd.h>//包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数。
#include<sys/wait.h>
#include<sys/types.h>//是Unix/Linux系统的基本系统数据类型的头文件,含有size_t,time_t,pid_t等类型。
#include<sys/stat.h>//是unix/linux系统定义文件状态所在的伪标准头文件。
#define MAXFILE 65535
int main()
{
pid_t pc;
int i,fd,len;
char *buf = (char*)("this is a Dameon\n");
pc = fork(); /*第一步*/
if(pc < 0)
{
printf("error fork\n");
exit(1);
}
else if(pc > 0)
{
exit(0);
}
setsid();/*第二步*/
chdir("/");/*第三步*/
umask(0); /*第四步*/
for(int i = 0;i < MAXFILE;i++)
{
close(i);
}
while(1)
{
fd = open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND,0600);
if(fd < 0)
{
perror("open");
exit(1);
}
write(fd,buf,len+1);
close(fd);
sleep(10);
}
return 0;
}
g++ -o fork fork.cpp
./fork
执行编译完的目标文件,好像程序执行一下就退出了
然后执行ps -ef |grep frok 命令,发现守护进程在运行
tail /tmp/dameon.log 文件,发现"this is a Dameon"还在正常打印
如果想结束这进程
kill -9 跟进程号
如kill -9 3434