Chinaunix首页 | 论坛 | 博客
  • 博客访问: 149137
  • 博文数量: 26
  • 博客积分: 645
  • 博客等级: 上士
  • 技术积分: 340
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-05 15:00
文章分类

全部博文(26)

文章存档

2014年(1)

2013年(1)

2011年(22)

2010年(1)

2009年(1)

我的朋友

分类: LINUX

2011-07-03 09:57:49

守护进程的特点:
UID = 0   以超级用户启动
TTY = ? 没有控制终端
TPGID=-1 没有任何相关的前台进程组
PPID = 1  父进程都为Init

创建守护进程的方法:
1、让Init成为它的父进程
用fork产生新进程后,杀死父进程,使Init收养它。
2、使用setsid创建新会话
使其失去原父进程的控制终端和前台进程组
3、用chdir修改当前工作目录
4、关闭文件描述符,重定向输入输出,避免出现打印
5、为守护进程的文件权限创建掩码
可以使用umask,避免其他用户查看。

代码举例:
createdaemon.c:
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>

  6. int main(int argc, char *argv[])
  7. {
  8.     pid_t pid;
  9.     int nochdir;
  10.     int noclosefp;
  11.     int fd;
  12.     int mode;

  13.     /* 入参检查:命令行参数不得少于三个(进程名、模式、守护进程路径) */
  14.     if(argc < 3)
  15.     {
  16.         printf("not enough argument!\n");
  17.         printf("arg[1]=1|2|3. 1-->nochdir;2-->noclosefp;3-->1+2.\n");
  18.         printf("arg[2..]=daemon program file and command line args...\n");
  19.         return -1;
  20.     }

  21.     /* 模式判断:mode+1:重置当前工作目录. mode+2:关闭输入输出 */
  22.     mode = atoi(argv[1]);
  23.     switch (mode)
  24.     {
  25.         case 1:
  26.         {
  27.             nochdir = 1;
  28.             noclosefp = 0;
  29.             break;
  30.         }
  31.         case 2:
  32.         {
  33.             noclosefp = 1;
  34.             nochdir = 0;
  35.             break;
  36.         }
  37.         case 3:
  38.         {
  39.             nochdir = 1;
  40.             noclosefp = 1;
  41.             break;
  42.         }
  43.         default:
  44.         {
  45.             printf("invalid args! exit.\n");
  46.             return -1;
  47.         }
  48.     }

  49.     /* 判断守护进程程序是否存在 */
  50.     if (access(argv[2], 0) < 0)
  51.     {
  52.         perror("access");
  53.         return -1;
  54.     }
  55.     /* 创建守护进程 */
  56.     pid = fork();
  57.     if(pid < 0)
  58.     {
  59.         perror("fork");
  60.         return -1;
  61.     }
  62.     else if(pid != 0)
  63.     {
  64.         _exit(0); /* 父进程直接退出,由init收养子进程 */
  65.     }

  66.     /* 成为会话头进程 */
  67.     pid = setsid();
  68.     if(pid < 0)
  69.     {
  70.         perror("setsid");
  71.         return -1;
  72.     }

  73.     printf("starting daemon process:%s, mode %d....\n", argv[2], mode);

  74.     /* 重置工作目录 */
  75.     if(!nochdir)
  76.     {
  77.         chdir("/");
  78.     }

  79.     /* 关闭输入输出 */
  80.     if(!noclosefp)
  81.     {
  82.         fd = open("/dev/null", O_RDWR, 0);
  83.         if(fd != -1)
  84.         {
  85.             dup2(fd, STDIN_FILENO);
  86.             dup2(fd, STDOUT_FILENO);
  87.             dup2(fd, STDERR_FILENO);
  88.             if(fd > 2)
  89.             {
  90.                 close(fd);
  91.             }
  92.         }
  93.     }

  94.     umask(0027);

  95.     if(execvp(argv[2], &(argv[2])) < 0)
  96.     {
  97.         perror("execvp");
  98.         return -1;
  99.     }

  100.     return 0;
  101. }

testdaemon.c:
  1. #include <stdio.h>
  2. #include <unistd.h>

  3. int main(int argc, char *argv[])
  4. {
  5.     while(1)
  6.     {
  7.         sleep(5);
  8.         printf("\ndaemon test is running.\n");
  9.     }
  10.     return 0;
  11. }

运行测试,不改变工作目录,不关闭输入输出:
lisong@lisong:~/code/experiment/proc/daemon$ ./createdaemon 3 ./testdaemon
starting daemon process:./testdaemon, mode 3....
lisong@lisong:~/code/experiment/proc/daemon$
daemon test is running.

daemon test is running.

改变工作目录,不关闭输入输出:
lisong@lisong:~/code/experiment/proc/daemon$ ./createdaemon 2 ./testdaemon
starting daemon process:./testdaemon, mode 2....
execvp: No such file or directory
改变目录之后,找不到testdaemon,因此无法执行。但“execvp: No such file or directory”可以打印。

不改变工作目录,关闭输入输出:
lisong@lisong:~/code/experiment/proc/daemon$ ./createdaemon 1 ./testdaemon
starting daemon process:./testdaemon, mode 1....
lisong@lisong:~/code/experiment/proc/daemon$ ps -axj|grep testdaemon
Warning: bad ps syntax, perhaps a bogus '-'? See
    1  3980  3980  3980 ?           -1 Ss    1000   0:00 ./testdaemon
 2392  3982  3981  2392 pts/1     3981 S+    1000   0:00 grep --color=auto testdaemon
lisong@lisong:~/code/experiment/proc/daemon$

关闭输入输出后,“daemon test is running.”无法打印,但可以看到守护进程已经开启了。

遗留问题:
1、找不到 程序时,access() 似乎没有返回异常状态。
2、待测umask

阅读(1439) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~