守护(daemon)进程即在后台运行的进程,网上有很多介绍守护进程的文章,这里不再赘述,直接上代码。
static void _daemon_prep(int stderr_log)
{
/* Avoid keeping any directory in use. */
chdir("/");
/* Reset process session id. */
setsid();
/* If you want to log in console. */
if (stderr_log)
return;
/*
* Close inherited file descriptors to avoid
* keeping unnecessary references.
*/
close(0);
close(1);
close(2);
/*
* Redirect std{in,out,err}, just in case.
*/
open("/dev/null", O_RDWR);
dup(0);
dup(0);
}
static int _daemonize()
{
int pid = fork();
if (pid != 0) {
// parent, exit
if (pid == -1) {
//cerr << "daemonize failed!" << endl;
return -1;
}
exit(0);
} else {
// child, continue
//cout << "daemonnize success!" << endl;
_daemon_prep(0);
return 0;
}
}
在你的 main 函数中调用 _daemonize 方法即可使你的进程变成守护进程。如以下示例:
int main()
{
_daemonize();
while(1) {
cout << "hello, world" << endl;
sleep(1);
}
exit(0);
}
以上"hello, world"程序会在后台运行,因在_daemon_prep函数中将标准输入输出重定位到了/dev/null,故你在终端看不到任何输出。如你想在终端看到输出,可在调用_daemon_prep时传入参数1。如你想把标准输出、错误输出重定位到文件方便后续查看,可修改代码如下:
/*
* Redirect std{in,out,err}, just in case.
*/
open("/dev/null", O_RDWR); // stdin
if (open("/var/log/yourapp.log", O_RDWR | O_CREAT | O_TRUNC) < 0 ) {
cerr << "open error!" << endl;
dup(0); // stdout
dup(0); // stderr
} else {
dup(1); // redirect stderr to the file same as stdout
}
一般不建议这样保存程序日志,可采用这里介绍的专用日志工具记录日志信息。