守护进程 setsid(转)

摘要:
守护进程是一个在后台运行的特殊进程。同时,守护进程执行许多系统任务。这些环境通常由守护进程从执行它们的父进程继承。最后,守护进程的启动方式有其自身的特点。这一原则是为了满足守护程序的特性。方法是在第1点的基础上调用setsid(),使进程成为会话领导者:setsid);注意:当进程是会话领导者时,setsid()调用失败。它可以修改守护进程创建的文件的访问位。3、 守护程序实例由两部分组成:主程序测试。c和初始化程序init。c
守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进 程。 Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任务。 比如,作业规划进程crond,打印进程lpd等。 

守护进程的编程本身并不复杂,复杂的是各种版本的Unix的实现机制不尽相同,造成不同 Unix环境下守护进程的编程规则并不一致。需要注意,照搬某些书上的规则(特别是BSD4.3和低版本的System V)到Linux会出现错误的。下面将给出Linux下守护进程的编程要点和详细实例。 

一. 守护进程及其特性 

守护进程最重要的特性是后台运行。在这一点上DOS下的常驻内存程序TSR与之相似。其次,守护进程必须与其运行前的环境隔离开来。这些环 境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下 来的。最后,守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc*.d中启动,可以由作业规划进程crond启动,还 可以由用户终端(通常是 shell)执行。 

总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。如果对进程有比较深入的认识就更容易理解和编程了。 

二. 守护进程的编程要点 

前面讲过,不同Unix环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则其实都一样,区别在于具体的实现细节不同。这个原则 就是要满足守护进程的特性。同时,Linux是基于Syetem V的SVR4并遵循Posix标准,实现起来与BSD4相比更方便。编程要点如下; 

1. 在后台运行。 

为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。 

if(pid=fork())exit(0); //是父进程,结束父进程,子进程继续 
2. 脱离控制终端,登录会话和进程组 

有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: 

setsid(); 

说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。 

3. 禁止进程重新打开控制终端 

现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端: 

if(pid=fork()) exit(0); //结束第一子进程,第二子进程继续(第二子进程不再是会话组长) 

4. 关闭打开的文件描述符 

进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们: 

for(i=0;i<;++1) //关闭打开的文件描述符 
close(i); 

5. 改变当前工作目录 

进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如 /tmpchdir("/") 

6. 重设文件创建掩模 

进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0); 

7. 处理SIGCHLD信号 

处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结 束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下 可以简单地将 SIGCHLD信号的操作设为SIG_IGN。 

signal(SIGCHLD,SIG_IGN); 

这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。 

三. 守护进程实例 

守护进程实例包括两部分:主程序test.c和初始化程序init.c。主程序每隔一分钟向/tmp目录中的日志test.log报告运行状态。初始化程序中的init_daemon函数负责生成守护进程。读者可以利用init_daemon函数生成自己的守护进程。 

1. init.c清单 

C代码  收藏代码
  1. #include < unistd.h >  
  2. #include < signal.h >  
  3. #include < sys/param.h >  
  4. #include < sys/types.h >  
  5. #include < sys/stat.h >  
  6.   
  7. void init_daemon(void){  
  8.     int pid;  
  9.     int i;  
  10.     if(pid=fork())exit(0);//是父进程,结束父进程  
  11.      else if(pid< 0)exit(1);//fork失败,退出  
  12.   
  13.     //是第一子进程,后台继续执行  
  14.     setsid();//第一子进程成为新的会话组长和进程组长  
  15.                //并与控制终端分离  
  16.     if(pid=fork())exit(0);//是第一子进程,结束第一子进程  
  17.     else if(pid< 0)exit(1);//fork失败,退出  
  18.   
  19.     //是第二子进程,继续  
  20.     //第二子进程不再是会话组长  
  21.   
  22.      for(i=0;i< NOFILE;++i)//关闭打开的文件描述符  
  23.      close(i);  
  24.     chdir("/tmp");//改变工作目录到/tmp  
  25.     umask(0);//重设文件创建掩模  
  26.      return:  
  27. }  

2. test.c清单 

C代码  收藏代码
  1. #include < stdio.h >  
  2. #include < time.h >  
  3. #include < stdio.h >  
  4.   
  5. void init_daemon(void);//守护进程初始化函数  
  6. main(){  
  7.     FILE *fp;  
  8.     time_t t;  
  9.     init_daemon();//初始化为Daemon  
  10.     while(1)//每隔一分钟向test.log报告运行状态  
  11.     {  
  12.         sleep(60);//睡眠一分钟  
  13.          if((fp=fopen("test.log","a")) >=0){  
  14.         t=time(0);  
  15.         fprintf(fp,"Im here at %sn",asctime(localtime(&t)) );  
  16.         fclose(fp);  
  17.         }  
  18.     }  
  19. }  


以上程序在Ubuntu Linux8.04下编译通过。步骤如下: 

编译:gcc -g -o test init.c test.c 

执行:./test 

查看进程:ps -ef 

从输出可以发现test守护进程的各种特性满足上面的要求。  

免责声明:文章转载自《守护进程 setsid(转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇iOS开发中WiFi相关功能总结linux设置上网代理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

针对防止自己的Linux进程被杀死的解决办法

这里后三种方法 在/etc/inittab文件加一条语句( :id:rstate:action:process),运行动作为 respawn,这样在每次系统检测到process进程不存在时,就会重启它。 创建一个守护进程,该守护进程的功能就是检测主进程是否在运行,若不在运行,那么守护进程就启动它。(这里存在一个问题,守护进程也可能会被杀死,那么更狠的一点...

[linux]进程(六)——守护进程

15,守护进程 概念:守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程的特点:守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。守护进程...

Python并发编程 —— 在Python程序中的进程操作

运行中的程序就是一个进程。所有的进程都是通过它的父进程来创建的。因此,运行起来的python程序也是一个进程,那么我们也可以在程序中再创建进程。多个进程可以实现并发效果,也就是说,当我们的程序中存在多个进程的时候,在某些时候,就会让程序的执行速度变快。我们可以借助python中强大的模块。来实现创建进程这个功能。 1、multiprocessing模块 把...

ubuntu守护进程rsyslog.conf_栈_百度空间

ubuntu守护进程rsyslog.conf_栈_百度空间 ubuntu守护进程rsyslog.conf 2010年04月18日 星期日 11:11 今天在学习守护进程时,看到一个实验,却无法得到结果。发现可能是Linux版本不同,结果配置文件也不同首先,ubuntu的配置文件为/etc/rsyslog.conf,不再是/etc/syslog.conf。...

Linux C/C++编程之(十九)进程组守护进程

文章目录 一、概述 二、进程组与守护进程 1. 进程组 2. 进程组操作函数 3. 会话 4. 守护进程 一、概述 二、进程组与守护进程 1. 进程组 进程组,也称之为作业。BSD于1980年前后向Unix中增加的一个新特性,代表一个或多个进程的集合,每个进程都属于一个进程组。在waitpid函数和kill函数的参数中都曾使用到。操作系...

linux日志守护进程 syslog

  https://www.cnblogs.com/linuxws/p/9017404.html   几乎所有的网络设备都可以通过syslog协议,将日志信息以UDP的形式传送给远端服务器,远端接收日志服务器必须通过syslogd监听UDP端口514,并根据 syslog.conf 配置文件张的配置处理。配置文件 /etc/rsyslog.conf 中...