Linux后台进程挂起通用做法
最近看了一些Twitter的一些开源项目,吸收到了很多好的想法。其实老外似乎不是很喜欢C++,C的底层比较多。不过我觉得倒是无所谓,所谓的C坑少,大多数是因为以对象的方法设计了过程式代码。毕竟,这个世界,并不是只有对象存在的方式,合理的搭配,才是能发挥最强的开发方式,还是那句话,代码不重要,重要的是想法。
比如,抠出一个很通用的进程后台挂起方法,一个函数搞定,一般情况下不需要改动这里的代码,只要调用一下即可。
static int daemonize()
{
pid_t pid, sid;
int fd;
pid = fork();
switch (pid) {
case -1:
printf("fork() failed: %s", strerror(errno));
return -1;
case 0:
break;
default:
_exit(0);
}
sid = setsid();
if (sid < 0) {
printf("setsid() failed: %s", strerror(errno));
return -1;
}
if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
printf("signal(SIGHUP, SIG_IGN) failed: %s", strerror(errno));
return -1;
}
int status = chdir("/");
if (status < 0) {
printf("chdir(\"/\") failed: %s", strerror(errno));
return -1;
}
umask(0);
fd = open("/dev/null", O_RDWR);
if (fd < 0) {
printf("open(\"/dev/null\") failed: %s", strerror(errno));
return -1;
}
status = dup2(fd, STDIN_FILENO);
if (status < 0) {
printf("dup2(%d, STDIN) failed: %s", fd, strerror(errno));
close(fd);
return -1;
}
status = dup2(fd, STDOUT_FILENO);
if (status < 0) {
printf("dup2(%d, STDOUT) failed: %s", fd, strerror(errno));
close(fd);
return -1;
}
status = dup2(fd, STDERR_FILENO);
if (status < 0) {
printf("dup2(%d, STDERR) failed: %s", fd, strerror(errno));
close(fd);
return -1;
}
if (fd > STDERR_FILENO) {
status = close(fd);
if (status < 0) {
printf("close(%d) failed: %s", fd, strerror(errno));
return -1;
}
}
return 0;
}
看,非常漂亮吧,很实用。
在这里记录一下。
这里要说一下ACE的daemonize,至今比这个过程少了几步,最重要的是/dev/null没有被设置。
如果在程序有大量输出的时候(比如printf),CPU占用率会被吃掉不少,起不到提高效率的作用。所以我都用这个函数替换了ace的daemonize。
希望ACE在以后的版本中改进。
看看ACE 在6.0.0里面干了什么。。
以下是ACE源代码:
int
ACE::daemonize (const ACE_TCHAR pathname[],
bool close_all_handles,
const ACE_TCHAR program_name[])
{
ACE_TRACE ("ACE::daemonize");
#if !defined (ACE_LACKS_FORK)
pid_t pid = ACE_OS::fork ();
if (pid == -1)
return -1;
else if (pid != 0)
ACE_OS::exit (0); // Parent exits.
// 1st child continues.
ACE_OS::setsid (); // Become session leader.
ACE_OS::signal (SIGHUP, SIG_IGN);
pid = ACE_OS::fork (program_name);
if (pid != 0)
ACE_OS::exit (0); // First child terminates.
// Second child continues.
if (pathname != 0)
// change working directory.
ACE_OS::chdir (pathname);
ACE_OS::umask (0); // clear our file mode creation mask.
return 0;
#else
ACE_UNUSED_ARG (pathname);
ACE_UNUSED_ARG (close_all_handles);
ACE_UNUSED_ARG (program_name);
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_LACKS_FORK */
}
少了STDIN_FILENO STDOUT_FILENO STDERR_FILENO 和 dev/null
这几个参数都是很关键的参数,不过我个人觉得未必是ACE的疏忽,只是我个人觉得应该补上。更好的提供效能,毕竟,后台输出不重定向是无意义的,别人也看不见。
页:
[1]