使用C在Linux后台启动进程

Mik*_*ike 8 c linux fork process

我想在这里做一些有点奇怪的事情.我需要从一个将在后台运行的deamon启动一个进程logcat,并在不控制stdin的情况下打印到终端.它用于日志记录,因此理想情况下logcat将打印日志消息,同时仍允许用户输入标准命令并从shell初始化程序.这是我到目前为止守护进程的代码.程序logcat启动并显示日志消息但我无法输入任何命令到stdin,因为程序似乎控制了stdin.

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;
}
Run Code Online (Sandbox Code Playgroud)

谢谢

Jon*_*ler 4

“logcat”命令似乎用于 Android 开发 - 这可能解释了该命令的奇怪位置。

您必须修复的关键操作是确保关闭当前的标准输入(终端)并打开/dev/null/输入设备:

close(0);
if ((fd = open("/dev/null", O_RDONLY)) != 0)
    ...error - failed to open /dev/null!
Run Code Online (Sandbox Code Playgroud)

这意味着您的守护进程子进程不会从终端读取任何内容。


我认为你想做的是:

  1. 从命令行运行启动程序,该程序将标准输入、标准输出和标准错误连接到“终端”。
  2. 在您的程序中,您想要替换标准输入,使其来自/dev/null.
  3. 您想保留标准输出 - 您想logcat写入当前的标准输出。
  4. 您可能也想保留标准错误。

在程序中的某个时刻,您正确执行守护进程(借用@bstpierre答案中的链接),确保您连接到的终端不是您的控制终端,以便发送到终端的中断和挂断不会影响你的守护进程。管道比您设置的更简单 - 您应该处理标准输入并保持标准输出和标准错误不变(而不是更改输出并保持输入不变)。

现在,您可能希望输出转到/dev/console;如果是这样,那么修改代码来打开/dev/console. /dev/null但是,如果打不开就依靠,那就不太合理了/dev/console;你的程序应该报告错误并失败(因为让 logcat 写入没有意义/dev/null!)。确保使用该O_NOCTTY标志打开控制台,这样它就不会成为守护程序的控制终端。

我最后的评论是:

  • 您确定要在终端或控制台用于其他用途时出现随机文本吗?

我不太喜欢这种事发生。


另请参阅:SO 958249