Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31100
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 131
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-14 19:23
个人简介

a person

文章分类

全部博文(11)

文章存档

2015年(11)

我的朋友

分类: C/C++

2015-04-26 22:39:42

Linux下守护进程的创建一般遵守以下规则:
1. 设置umask为一个已知的值,通常为0;
        因为要确保守护进程对创建的进程具有正确的权限,避免默认的umask造成影响;
2. 调用fork( ),之后使父进程退出;
         首先,守护进程是由shell进程启动的,调用fork,使父进程退出,让shell进程认为该程序已经结束;其次,子进程继承了父进程的组ID,但是获得了一个新的进程ID,所以保证了子进程不是一个进程组的leader,这也是接下来要调用setsid的先决条件;
3.  调用setsid创建一个新的会话;
        当调用setsid后,该子进程创建了一个新的会话;并且成为了进程组的leader;而且和控制终端脱离了;
4. 将目录改为root;
        当前工作目录是由父进程继承而来,有可能会被unmount掉,不好说,所以为了保证文件系统的有效性,将目录切换为root更目录更加保险;
5. 关闭所有不需要的文件描述符;
        该步骤阻止了守护进程持有父进程的一些打开的文件描述符,可以使用getrlimit函数去确定最大的文件描述符的值并关闭所有的文件描述符;
6. 将文件描述符 0,1,2指向/dev/null;

下面创建一个守护进程,每隔5秒向日志文件中写入一条记录:

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <fcntl.h>
  5. #include <sys/resource.h>
  6. #include <sys/types.h>
  7. #include <syslog.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <signal.h>
  11. #include <time.h>

  12. #define error_handle(en,msg) \
  13.     do{errno=en;perror(msg);exit(EXIT_FAILURE);}while(0)

  14. void daemonize(const char *cmd){
  15.     int i,fd0,fd1,fd2;
  16.     pid_t pid;
  17.     struct rlimit rl;
  18.     struct sigaction sa;

  19.     /* Clear file creation mask */
  20.     umask(0);

  21.     /* Get maximum number of file descriptors */
  22.     if(getrlimit(RLIMIT_NOFILE,&rl)<0)
  23.         error_handle(1,"getrlimit error");

  24.     /* Become a session leader to lose controlling TTY. */
  25.     if((pid=fork())<0)
  26.         error_handle(1,"fork error");
  27.     else if(pid!=0) /* parent */
  28.         exit(0);
  29.     setsid();

  30.     /* Ensure future opens won't allocate controlling TTYs. */
  31.     sa.sa_handler=SIG_IGN;
  32.     sigemptyset(&sa.sa_mask);
  33.     sa.sa_flags=0;
  34.     // SIGHUP is a signal sent to a process when its controlling terminal is closed
  35.     if(sigaction(SIGHUP,&sa,NULL)<0)
  36.         error_handle(1,"SIGHUP error");
  37.     if((pid=fork())<0)
  38.         error_handle(1,"fork error");
  39.     else if(pid!=0) /* parent */
  40.     exit(0);

  41.     /* Change the current working directory to the root so
  42.        we won't prevent file system from being unmounted. */
  43.     if(chdir("/")<0)
  44.         error_handle(1,"chdir root error");

  45.     /* Close all open file descriptors */
  46.     if(rl.rlim_max==RLIM_INFINITY)
  47.         rl.rlim_max=1024;
  48.     for(i=0;i<rl.rlim_max;i++)
  49.         close(i);

  50.     /* Attach file descriptos 0,1,2 to /dev/null */
  51.     fd0=open("/dev/null",O_RDWR);
  52.     fd1=dup(0);
  53.     fd2=dup(0);
  54.     
  55.     /* Initialize the log file */
  56.     openlog(cmd,LOG_CONS|LOG_PID,LOG_DAEMON|LOG_USER);
  57.     if(fd0!=0||fd1!=1||fd2!=2){
  58.         syslog(LOG_ERR,"unexpected file descriptors %d %d %d\n",fd0,fd1,fd2);
  59.         exit(EXIT_FAILURE);
  60.     }

  61.     time_t cur_t;

  62.     while(1){
  63.         time(&cur_t);
  64.         syslog(LOG_INFO,"current time is %s\n",ctime(&cur_t));
  65.         sleep(3);    
  66.     }

  67.     exit(EXIT_SUCCESS);
  68. }

  69. int main(void){
  70.     daemonize("mydeamon");
  71.     exit(0);
  72. }
在Ubuntu下可以查看 /var/log/syslog 文件变化;
tail -n 50 /var/log/syslog 查看最后50行 为该daemon进程输出的时间


阅读(839) | 评论(0) | 转发(0) |
0

上一篇:fcntl

下一篇:writen and readn

给主人留下些什么吧!~~