介绍并实现简单的守护进程

   今天来分享一下Linux下,由守护进程实现的大多数服务器,并能够完成许多系统任务。

   守护进程是一种运行在后台的进程,又称精灵进程。它独立于控制终端并且周期的实现执行某种任务或等待处理某些发生的事件,且不受用户登陆和注销的影响(它们不与任何终端关联),它们每天24小时不停的运行。一般情况下,Linux系统的守护进程以.d结尾。

   可用ps axj查看系统中的进程,今天我就不演示了,TPGID这一行为-1的都是没有控制终端的守护进程。

   要想自己实现一个简单的守护进程,创建守护进程最关键的一步是调用setsid函数创建一个新的session,并成为session leader。只要调用setsid函数的进程不是当前进程组的leader,一般情况下都会调用成功。

setsid函数成功调用的结果:

   1.调用setsid函数成功会创建一个新的session,并成为session leader。

   2.创建一个新的进程组,并当前进程成为该进程组的 leader,当前进程的id成为该进程组的id。

   3. 使得这个开始有控制终端的进程成为一个没有控制终端的进程。(与原来的终端去关联。)

所以自己实现守护进程的一般步骤如下

   1.调用umask函数将文件模式创建屏蔽字设置为0,让守护进程设置文件权限不受约束。

   2.由主线程fork一个子进程,并让父进程退出。

   3.由子进程去调用setsid函数,为该子进程成为精灵进程提供了基础。

   4.将当前工作目录更改根目录,避免误删产生当前工作目录导致守护进程出错,把守护进程的工作目录更改到更目录,能够减小被误删的可能性。(另外,一般情况下,根目录是不会被删掉,即使你使用rm -R /命令,只会把根目录可以删除的文件全部删除,可能会导致系统down掉,友情提示:不要轻易去尝试。)

   5.关闭不需要的文件描述符(或者重定向不需要文件描述符),例如标准读写和报错。

    注:重定向不需要的文件描述符,避免守护进程在输出输入或报错时,因为标准输入输出被关闭而导致守护进程程序崩掉。

   6.用signal函数,去忽略SIGCHLD信号。

有些朋友,写自己的守护程序是会fork两次:

   目的是:为了保持子进程不是话首进程,保证后续不在和其他终端有关联。所以,这样的写法没有任何问题的,同样,我写的这么简单也是没有错的。

实现守护进程:

关闭不需要的文件描述符,运行和分析结果如下:

注:为了简单,我直接将守护进程的id打印出来方便在/proc/(Linux系统中基于内存的文件系统,可以看到守护进程的相关参照信息)中查找守护进程的相应信息,虽然运行的是前台程序,但是的那个父进程退出后,子进程(守护进程)会去后台运行,所以也没差。

 

运行并查看守护进程相关信息

 

删除守护进程

重定向不需要的文件描述符,运行和分析结果如下:

 

运行并查看守护进程相关信息

系统实现守护进程函数——daemon函数:

 

运行和分析结果如下: 

当参数为默认值时,生成的守护进程会更改工作目录,并重定向不需要的文件描述符。

 

当参数不是默认值时,生成的守护进程不会更改工作目录,也不会重定向不需要的文件描述符。

 

守护进程的源代码如下:

daemon.c

 1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<signal.h>
  4 #include<unistd.h>
  5 #include<sys/types.h>
  6 #include<sys/stat.h>
  7 #include<fcntl.h>
  8
  9 void fun(){
 10     umask(0);
 11     pid_t id = fork();
 12
 13     if(id > 0){
 14         printf("id: %d\n", id);
 15         return ;
 16     }
 17
 18     setsid();
 19     chdir("/");//更改工作目录
 20
 21 //  close(0);//关闭多余的文件描述符
 22 //  close(1);
 23 //  close(2);
 24     
 25     int fd = open("/dev/null", O_RDWR);
 26     dup2(fd,0);//重定向多余的文件描述符,避免守护进程在输出输入或报错时,因为标准输入输出被关闭而导致守护进程程序崩掉
 27     dup2(fd,1);
 28     dup2(fd,2);
 29     close(fd);
 30     
 31     signal(SIGCHLD, SIG_IGN);//ignore
 32 }
 33
 34 int main(){
 35  //  fun();
 36     daemon(1,1);
 37
 38     while(1){}
 39     return 0;
 40 }

Makefile

 

 1 mydaemon:mydaemon.c

  2     gcc -o $@ $^

  3 .PHONY:clean

  4 clean:

  5     rm -f mydaemon


   分享如上!望互相交流,共同学习进步!如有不正确的地方,望斧正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值