找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 4686|回复: 0

Linux后台进程挂起通用做法

[复制链接]
发表于 2013-9-24 09:20:51 | 显示全部楼层 |阅读模式
最近看了一些Twitter的一些开源项目,吸收到了很多好的想法。
其实老外似乎不是很喜欢C++,C的底层比较多。不过我觉得倒是无所谓,所谓的C坑少,大多数是因为以对象的方法设计了过程式代码。毕竟,这个世界,并不是只有对象存在的方式,合理的搭配,才是能发挥最强的开发方式,还是那句话,代码不重要,重要的是想法。
比如,抠出一个很通用的进程后台挂起方法,一个函数搞定,一般情况下不需要改动这里的代码,只要调用一下即可。
  1. static int daemonize()
  2. {
  3.         pid_t pid, sid;
  4.         int fd;
  5.         pid = fork();
  6.         switch (pid) {
  7.         case -1:
  8.                 printf("[daemonize]fork() failed: %s", strerror(errno));
  9.                 return -1;
  10.         case 0:
  11.                 break;
  12.         default:
  13.                 _exit(0);
  14.         }
  15.         sid = setsid();
  16.         if (sid < 0) {
  17.                 printf("[daemonize]setsid() failed: %s", strerror(errno));
  18.                 return -1;
  19.         }
  20.         if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
  21.                 printf("[daemonize]signal(SIGHUP, SIG_IGN) failed: %s", strerror(errno));
  22.                 return -1;
  23.         }
  24.         int status = chdir("/");
  25.         if (status < 0) {
  26.                 printf("chdir("/") failed: %s", strerror(errno));
  27.                 return -1;
  28.         }
  29.         umask(0);
  30.         fd = open("/dev/null", O_RDWR);
  31.         if (fd < 0) {
  32.                 printf("[daemonize]open("/dev/null") failed: %s", strerror(errno));
  33.                 return -1;
  34.         }
  35.         status = dup2(fd, STDIN_FILENO);
  36.         if (status < 0) {
  37.                 printf("[daemonize]dup2(%d, STDIN) failed: %s", fd, strerror(errno));
  38.                 close(fd);
  39.                 return -1;
  40.         }
  41.         status = dup2(fd, STDOUT_FILENO);
  42.         if (status < 0) {
  43.                 printf("[daemonize]dup2(%d, STDOUT) failed: %s", fd, strerror(errno));
  44.                 close(fd);
  45.                 return -1;
  46.         }
  47.         status = dup2(fd, STDERR_FILENO);
  48.         if (status < 0) {
  49.                 printf("[daemonize]dup2(%d, STDERR) failed: %s", fd, strerror(errno));
  50.                 close(fd);
  51.                 return -1;
  52.         }
  53.         if (fd > STDERR_FILENO) {
  54.                 status = close(fd);
  55.                 if (status < 0) {
  56.                         printf("[daemonize]close(%d) failed: %s", fd, strerror(errno));
  57.                         return -1;
  58.                 }
  59.         }
  60.         return 0;   
  61. }
复制代码
看,非常漂亮吧,很实用。
在这里记录一下。
这里要说一下ACE的daemonize,至今比这个过程少了几步,最重要的是/dev/null没有被设置。
如果在程序有大量输出的时候(比如printf),CPU占用率会被吃掉不少,起不到提高效率的作用。所以我都用这个函数替换了ace的daemonize。
希望ACE在以后的版本中改进。
看看ACE 在6.0.0里面干了什么。。
以下是ACE源代码:
  1. int
  2. ACE::daemonize (const ACE_TCHAR pathname[],
  3.                 bool close_all_handles,
  4.                 const ACE_TCHAR program_name[])
  5. {
  6.   ACE_TRACE ("ACE::daemonize");
  7. #if !defined (ACE_LACKS_FORK)
  8.   pid_t pid = ACE_OS::fork ();
  9.   if (pid == -1)
  10.     return -1;
  11.   else if (pid != 0)
  12.     ACE_OS::exit (0); // Parent exits.
  13.   // 1st child continues.
  14.   ACE_OS::setsid (); // Become session leader.
  15.   ACE_OS::signal (SIGHUP, SIG_IGN);
  16.   pid = ACE_OS::fork (program_name);
  17.   if (pid != 0)
  18.     ACE_OS::exit (0); // First child terminates.
  19.   // Second child continues.
  20.   if (pathname != 0)
  21.     // change working directory.
  22.     ACE_OS::chdir (pathname);
  23.   ACE_OS::umask (0); // clear our file mode creation mask.
  24.   return 0;
  25. #else
  26.   ACE_UNUSED_ARG (pathname);
  27.   ACE_UNUSED_ARG (close_all_handles);
  28.   ACE_UNUSED_ARG (program_name);
  29.   ACE_NOTSUP_RETURN (-1);
  30. #endif /* ACE_LACKS_FORK */
  31. }
复制代码
少了STDIN_FILENO STDOUT_FILENO STDERR_FILENO 和 dev/null
这几个参数都是很关键的参数,不过我个人觉得未必是ACE的疏忽,只是我个人觉得应该补上。更好的提供效能,毕竟,后台输出不重定向是无意义的,别人也看不见。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-22 16:28 , Processed in 0.094048 second(s), 7 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表