Linux守候进程

在一个远程监控系统中,我们使用了守候进程。结合《Linux高级程序设计》的相关内容,对守候进程做个整理。

守候进程,又称守护进程(Daemon),是在后台运行的一种特殊的进程,脱离于终端。类似于Windows服务程序。守候进程适用于像我们项目中的数据采集类的程序,因为客户的误操作等原因,造成服务器的重启,这时要保证数据的接收是正常的,那么,很有必要将采集程序运行在后台,不被显示的终端界面所影响。

我们使用在系统启动时,随启动脚本来启动守候进程, 在/etc/rc.local里加上一句 /usr/local/haven/Daemon(即你的程序所在路径)。

 

守候进程的编程步骤一般比较死,都是规定好的,是一个套路:

1、屏蔽一些有关控制终端操作的信号;防止在守护进程没有正常运行起来前,控制终端收到干扰退出或挂起。

2、在后台运行,为了避免挂起控制终端将其放入后台执行。

3、脱离控制终端和进程,控制终端和进程组是从父进程继承下来的,要摆脱他们,使子进程成为新的会话组长。

4.、禁止进程重新打开控制终端,因为可以重新申请打开一个控制终端,那么再创建一个子进程。

5.、关闭打开的文件描述符,若不关闭会浪费系统资源。

6、改变当前工作目录,进程工作时,其工作目录在文件系统不能写下的。因此放在根目录,写运行日志的进程将工作目录改变到特定目录。

7、重设文件创建掩码。

8、处理SIGCHLD信号(子进程退出信号)。对于某些,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程从而占用了资源,如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。从而使用此步骤来解决这一问题。

下面是一个简单实现:Daemon.c

 

  1. #include<unistd.h>  
  2. #include<signal.h>  
  3. #include<fcntl.h>  
  4. #include<sys/syslog.h>  
  5. #include<sys/param.h>  
  6. #include<sys/stat.h>  
  7. #include<stdio.h>  
  8. #include<stdlib.h>  
  9.  
  10. int init_daemon(const char *pname,int facility)  
  11. {  
  12.     int pid;  
  13.     int i;  
  14.     signal(SIGTTOU,SIG_IGN);   //处理可能的终端信号  
  15.     signal(SIGTTIN,SIG_IGN);  
  16.     signal(SIGTSTP,SIG_IGN);  
  17.     signal(SIGHUP ,SIG_IGN);  
  18.  
  19.     if(pid=fork())                       //创建子进程,父亲进程退出  
  20.     {  
  21.        exit(EXIT_SUCCESS);  
  22.     }  
  23.     else if(pid<0)  
  24.     {  
  25.        perror("fork");  
  26.        exit(EXIT_FAILURE);  
  27.     }  
  28.     setsid();                           //设置新会话组长,新进程组长,脱离终端  
  29.     if(pid=fork())                    //创建新进程,子进程不能再申请终端  
  30.     {  
  31.        exit(EXIT_SUCCESS);  
  32.     }  
  33.     else if(pid<0)  
  34.     {  
  35.        perror("fork");  
  36.     }  
  37.     for(i=0;i<NOFILE;++i) //关闭父进程打开的文件描述符  
  38.        close(i);  
  39.     open("/dev/null",O_RDONLY); //对标准输入全部重新定向到文件中  
  40.     open("/dev/null",O_RDWR);  
  41.     open("/dev/null",O_RDWR);  
  42.  
  43.     chdir("/tmp");                    //修改主目录  
  44.     umask(0);                        // 重建设置文件掩码  
  45.     signal(SIGCHLD,SIG_IGN);   //处理子进程退出  
  46.     openlog(pname,LOG_PID,facility); //与守护进程建立联系,加上进程号,文件名  
  47.     return ;  
  48. }  
  49.  
  50. int main(int argc ,char *argv[])  
  51. {  
  52.     FILE *fp;  
  53.     time_t ticks;  
  54.     init_daemon(argv[0],LOG_KERN);//执行守候进程  
  55.     while(1)  
  56.     {  
  57.        sleep(1);  
  58.        ticks=time(NULL);  
  59.        syslog(LOG_INFO, "%s", asctime(localtime(&ticks))); //写日志信息  
  60.     }  

编译运行:

[root@localhost haven]# gcc -o Daemon Daemon.c
[root@localhost haven]# ./Daemon

查看:
[root@localhost haven]# ps aux|grep Daemon
root     13021  0.0  0.0   1648   420 ?        S    14:26   0:00 ./Daemon
root     13092  0.0  0.0   3916   660 pts/1    R+   14:28   0:00 grep Daemon

查看日志:
[root@localhost haven]# tail /var/log/messages
Feb 29 14:28:53 localhost ./Daemon[13021]: Wed Feb 29 14:28:53 2012
Feb 29 14:28:54 localhost ./Daemon[13021]: Wed Feb 29 14:28:54 2012
Feb 29 14:28:55 localhost ./Daemon[13021]: Wed Feb 29 14:28:55 2012
Feb 29 14:28:56 localhost ./Daemon[13021]: Wed Feb 29 14:28:56 2012
Feb 29 14:28:57 localhost ./Daemon[13021]: Wed Feb 29 14:28:57 2012
Feb 29 14:28:58 localhost ./Daemon[13021]: Wed Feb 29 14:28:58 2012
Feb 29 14:28:59 localhost ./Daemon[13021]: Wed Feb 29 14:28:59 2012
Feb 29 14:29:00 localhost ./Daemon[13021]: Wed Feb 29 14:29:00 2012
Feb 29 14:29:01 localhost ./Daemon[13021]: Wed Feb 29 14:29:01 2012
Feb 29 14:29:02 localhost ./Daemon[13021]: Wed Feb 29 14:29:02 2012

 

by HavenZhao    http://vcsky.net

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章