守护进程(精灵进程daemon):是运行在后台的一种特殊进程,它一直运行在后台,不受用户登录和注销的影响。所以它是独立于终端的并且周期性地执行某种任务或等待处理某些发生的事件。不能直接和用户交互。因此不允许往终端打印消息。

crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程,crond进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。


生命周期:通常在系统装入时启动,关闭时终止


特点:

1)脱离终端  为了避免进程在执行过程中的信息在任何终端上显示并且保证进程也不会被任何终端所产生的终端信息所打断。

2)自成进程组,PID = PGID

3)自成会话  PID = SID

4)父进程为1号进程。

注意:创建守护进程时,需保证该进程不是组长进程。否则出错返回-1.


pid_t setsid(void)

该函数的功能:

1)创建一个新会话,并且使该进程成为组长进程。

2)脱离原会话、进程组、终端的控制


创建守护进程一些必要操作:

将掩码权限设置为0(umask(0)):大大增强守护进程的灵活性

将工作目录更改为根目录:继承了父进程的工作目录,而此目录下的一些文件可能无法卸载,会造成一些麻烦。

关闭不需要的流:因为该进程继承了父进程的一些打开的文件,而守护进程可能一直不需要这些文件,但它们一样消耗系统资源,并且还有可能导致所在的文件系统无法卸下。

将信号SIGCHLD设置为忽略:此时父进程已经退出,所以不需要发送SIGCHLD信号

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<signal.h>
  5 void my_daemon()
  6 {
  7     umask(0);  //设置权限
  8     pid_t id = fork();  //保证当前进程不是组长进程。
  9     if(id<0)
 10     {
 11         perror("fork");
 12         exit(1);
 13     }
 14     else if(id>0)
 15     {
 16         exit(0);
 17     }
 18     pid_t sid = setsid();  //创建新会话
 19     if(sid<0)
 20     {
 21         perror("setsid");
 22         exit(1);
 23     }
 24     if(chdir("/")<0)  //更改当前工作目录为根目录
 25     {
 26         perror("chdir");
 27         exit(1);
 28     }
 29     close(0);  //关闭不需要的流
 30     close(1);
 31     close(2);
 32     signal(SIGCHLD,SIG_IGN);  //忽略SIGCHLD信号
 33 }
 34 int main()
 35 {
 36     my_daemon();
 37     while(1);
 38     return 0;
 39 }
 
 [fbl@localhost daemon]$ ./my_daemon 
[fbl@localhost daemon]$ 
[fbl@localhost daemon]$ ps axj |grep -E 'my_daemon'
    1  2655  2655  2655 ?           -1 Rs     500   5:46 ./my_daemon
    1  2694  2694  2694 ?           -1 Rs     500   0:02 ./my_daemon
 2449  2697  2696  2449 pts/0     2696 S+     500   0:00 grep -E my_daemon