您的位置:首页 > 运维架构 > Linux

Linux后台进程挂起通用做法

2014-11-04 09:09 190 查看
最近看了一些Twitter的一些开源项目,吸收到了很多好的想法。

其实老外似乎不是很喜欢C++,C的底层比较多。不过我觉得倒是无所谓,所谓的C坑少,大多数是因为以对象的方法设计了过程式代码。毕竟,这个世界,并不是只有对象存在的方式,合理的搭配,才是能发挥最强的开发方式,还是那句话,代码不重要,重要的是想法。

比如,抠出一个很通用的进程后台挂起方法,一个函数搞定,一般情况下不需要改动这里的代码,只要调用一下即可。

static int daemonize()

{

pid_t pid, sid;

int fd;

pid = fork();

switch (pid) {

case -1:

printf("[daemonize]fork() failed: %s", strerror(errno));

return -1;

case 0:

break;

default:

_exit(0);

}

sid = setsid();

if (sid < 0) {

printf("[daemonize]setsid() failed: %s", strerror(errno));

return -1;

}

if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {

printf("[daemonize]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("[daemonize]open(\"/dev/null\") failed: %s", strerror(errno));

return -1;

}

status = dup2(fd, STDIN_FILENO);

if (status < 0) {

printf("[daemonize]dup2(%d, STDIN) failed: %s", fd, strerror(errno));

close(fd);

return -1;

}

status = dup2(fd, STDOUT_FILENO);

if (status < 0) {

printf("[daemonize]dup2(%d, STDOUT) failed: %s", fd, strerror(errno));

close(fd);

return -1;

}

status = dup2(fd, STDERR_FILENO);

if (status < 0) {

printf("[daemonize]dup2(%d, STDERR) failed: %s", fd, strerror(errno));

close(fd);

return -1;

}

if (fd > STDERR_FILENO) {

status = close(fd);

if (status < 0) {

printf("[daemonize]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的疏忽,只是我个人觉得应该补上。更好的提供效能,毕竟,后台输出不重定向是无意义的,别人也看不见。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: