Chinaunix首页 | 论坛 | 博客
  • 博客访问: 152366
  • 博文数量: 69
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 595
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-16 00:00
个人简介

宁可逆流而上与众不同,也不顺风顺水随波逐流

文章分类

全部博文(69)

文章存档

2020年(1)

2018年(9)

2017年(43)

2016年(16)

我的朋友

分类: C/C++

2017-03-27 00:07:48

1:创建子进程并且父进程退出
2:调用setsid()创建一个新会话
3:再次fork()一个子进程,我们称为孙子进程,此时我们确定孙子进程没有控制终端。为什么再fork一次看我另一篇关于会话进程组的博文http://blog.chinaunix.net/uid-31374636-id-5760998.html
4:当前工作目录更改为根目录chdir("/")
5:   设置文件模式创建屏蔽字umask(0)
6: 关闭打开的文件描述符
7:将标准输入输出,错误输出都定向到/dev/null,这样不会在终端产生任何输出
8:因为stdin,stdout,stderr都定向到/dev/null,所以不能在终端输出,关于出错消息我们只能通过日志记录到文件中
9:使用记录锁保证守护进程只有一个副本在后台运行

只要保证进程的父进程为init,没有控制终端,工作目录最好是根目录,文件描述符都被关闭,文件模式创建屏蔽字为0。最重要的是一直运行,那么它就是守护进程
  1. //write a program which change the process to be a daemon
  2. #include<unistd.h>
  3. #include<fcntl.h>
  4. #include<stdio.h>
  5. #include<syslog.h>
  6. #include<sys/resource.h>
  7. #include<sys/stat.h>
  8. #include<stdlib.h>

  9. void daemonize(char*cmd)
  10. {
  11.   pid_t pid;
  12.   if((pid=fork())<0){
  13.     perror("fork a child process failed");
  14.     exit(0);
  15.   }
  16.   if(pid!=0)
  17.     exit(0);
  18.   //father process have exited,now only the child process
  19.   //create a session
  20.   setsid();
  21.   //maybe this child process has a tty,so i fork again to sure the daemon process have not tty.
  22.   if((pid=fork())<0){
  23.     perror("fork a grandchild failed");
  24.     exit(0);
  25.   }
  26.   if(pid!=0)
  27.     exit(0);
  28.   //the child process have exited,now only the grandchild process
  29.   umask(0);
  30.   if(chdir("/")<0){
  31.     perror("set work directory to / failed");
  32.     exit(0);
  33.   }
  34.   //now,i will turn off all file discription
  35.   struct rlimit fd_lim;
  36.   if(getrlimit(RLIMIT_NOFILE,&fd_lim)<0){
  37.     perror("can't get file limit");
  38.     exit(0);
  39.   }
  40.   if(fd_lim.rlim_max==RLIM_INFINITY)
  41.     fd_lim.rlim_max=1024;
  42.   for(int i=0;i<fd_lim.rlim_max;++i){
  43.     close(i);
  44.   }
  45.   //the last work is redirect the stdin,stdout,stderr to /dev/null and process the error message to log file
  46.   int fd0,fd1,fd2;
  47.   fd0=open("/dev/null",O_RDWR);
  48.   fd1=dup(fd0);
  49.   fd2=dup(fd0);
  50.   //initialize the log file
  51.   openlog(cmd,LOG_CONS,LOG_USER);
  52.   if(fd0!=0||fd1!=1||fd2!=2){
  53.     syslog(LOG_ERR,"unexpected file discriptors %d %d %d",fd0,fd1,fd2);
  54.     exit(0);
  55.   }
  56. }
上述代码中一开始我用的return代替的exit,但是后来发现程序居然在前台,后来才意识到return只是返回到调用函数,而不是退出进程。
阅读(531) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~