在Linux中用C在后台启动进程
我想做点奇怪的事。我需要启动一个进程logcat,从一个deamon开始,它将在后台运行并打印到终端,而不需要控制stdin。它用于日志记录,因此理想情况下logcat将打印日志消息,同时仍然允许用户输入标准命令并从shell初始化程序。这是我到目前为止所拥有的守护进程的代码。logcat程序启动并显示日志消息,但我无法在stdin中输入任何命令,因为该程序似乎已经控制了stdin在Linux中用C在后台启动进程,c,linux,process,fork,C,Linux,Process,Fork,我想做点奇怪的事。我需要启动一个进程logcat,从一个deamon开始,它将在后台运行并打印到终端,而不需要控制stdin。它用于日志记录,因此理想情况下logcat将打印日志消息,同时仍然允许用户输入标准命令并从shell初始化程序。这是我到目前为止所拥有的守护进程的代码。logcat程序启动并显示日志消息,但我无法在stdin中输入任何命令,因为该程序似乎已经控制了stdin int main ( int argc, char** argv, char** env ) { int
int main ( int argc, char** argv, char** env )
{
int fd;
if ((fd = open("/dev/console", O_RDWR)) < 0) {
fd = open("/dev/null", O_RDWR);
}
printf("THIS IS A TEST\n");
dup2(1, fd);
dup2(2, fd);
pid_t childpid = fork();
if(childpid == -1) {
perror("Failed to fork, logcat not starting");
return 1;
}
if(childpid == 0) {
//this is the child, exec logcat
setsid();
int execReturn = execl("/system/bin/logcat", "logcat", (char *) 0);
} else {
//this is the parent do nothing
close(fd);
return 0;
}
close(fd);
return 0;
}
int main(int argc、char**argv、char**env)
{
int-fd;
如果((fd=open(“/dev/console”,O_RDWR))<0){
fd=打开(“/dev/null”,O_RDWR);
}
printf(“这是一个测试\n”);
dup2(1,fd);
dup2(2,fd);
pid_t childpid=fork();
if(childpid==-1){
perror(“未能分叉,logcat未启动”);
返回1;
}
if(childpid==0){
//这是孩子,exec logcat
setsid();
int execReturn=execl(“/system/bin/logcat”,“logcat”,“char*)0);
}否则{
//这是父母什么都不做的
关闭(fd);
返回0;
}
关闭(fd);
返回0;
}
谢谢[死链接]
[上述回程机器档案]
--代码取自上面的链接
执行摘要:
我经常遇到的一件事是Linux守护进程不能正确地对自己进行守护。要正确地进行后台监控,必须遵循以下步骤
- fork()调用用于创建单独的进程
- setsid()调用用于将进程与父进程(通常是shell)分离
- 应该重置文件掩码
- 当前目录应更改为良性目录
- 需要重新打开标准文件(stdin、stdout和stderr)
- 启动守护进程然后注销将导致终端挂起。这对于ssh来说尤其令人讨厌
- 从中启动守护程序的目录仍处于锁定状态
- 在启动守护进程的shell中出现虚假输出
/dev/null/
:
close(0);
if ((fd = open("/dev/null", O_RDONLY)) != 0)
...error - failed to open /dev/null!
这意味着您的守护子进程将不会从终端读取任何内容
我想你要做的是:
/dev/null
logcat
写入当前标准输出/dev/console
;如果是这样,那么修改代码以打开/dev/console
是合理的。但是,如果您无法打开/dev/console
,那么使用/dev/null
是不合理的;您的程序应该报告错误并失败(因为让logcat写入/dev/null
!)没有意义。确保使用O_NOCTTY
标志打开控制台,使其不会成为守护进程的控制终端
我最后要说的是:
- 当终端或控制台用于其他用途时,是否确实希望随机文本出现在终端或控制台上
另请参见:glibc中有专门用于此的功能:
#include <unistd.h>
...
/* We are in the parent, yet */
daemon(0,0);
/* Now we are in the child */
...
#包括
...
/*我们在父母家,还没有*/
守护进程(0,0);
/*现在我们是孩子了*/
...
这里有更多详细信息非常感谢您的深入回答。正如你所提到的,问题是stdin。我不得不从logcat重定向到stdin,还有一些其他的东西,比如进程的后台监控。这帮我省去了很多压力和烦恼。再次感谢。我真的很感激。这帮了大忙。谢谢你。@Mike-你可能会弄错很多东西。。。我以前漏掉了一些片段,这篇文章是记住所有片段的一个很好的起点。链接似乎已经死了。