繁体   English   中英

C IPC等待孩子

[英]C IPC waiting for child

所以我有一个程序,它创建一个子进程并执行一个命令(例如,ls)。 然后,父母将使用管道发送给孩子并从孩子那里取得。 当我从命令行输入命令时,这很好用。

但是,当输入来自文件时,似乎孩子没有足够的时间来运行,并且从管道读取时我得到NULL - 即使会有来自它的信息。

没有使用sleep(),有没有更好的方法来确保孩子在尝试阅读之前已经运行了?

非常感谢!

如果您没有将管道文件描述符设置为非阻塞,那么应该没有问题。 管道上的任何读数都会阻塞,直到孩子产生输出; 如果您需要响应多个文件描述符(例如,来自用户的标准输入和来自子进程的管道),请使用select()poll()

我假设fgets()返回NULL。 这表示文件结束(意味着孩子已关闭管道的末尾)或错误。 你可以使用feof()ferror()来检查其中哪一个是真的。 在错误情况下使用perror()来查看错误实际是什么。

问题是你对孩子有多少控制? 如果您自己编写孩子,那么您可以让孩子在已启动的共享内存中设置一个标志(或触摸文件或您想要的任何痒痒),然后只有在您知道孩子在线运行它之后。

如果您无法控制子进程,那么仍然可以通过使用您自己的脚本包装子进程来实现上述解决方案,该脚本首先启动子进程然后设置共享内存。这可以是shell脚本的形式,如如下

#!/bin/sh

$CHILD
my_app_that_set_the_flag

最后另一个选择是继续等待从管道中获取NULL,显然这会导致无限循环,但如果你不能指望你总会在管道上得到一些东西

您的父线程需要等到子项准备好后再尝试从管道读取。 有几种方法可以做到这一点。

首先,您可以使用条件变量。 声明两个线程都可以访问的变量并将其设置为0 当父级已准备好阅读时,您的子线程将其设置为1 父将等到变量变为1 (使用while(!condvar) sleep(1); ),然后它将从管道中读取并将变量重置为0以便子项知道父项已完成。

另一种选择是使用一种进程间通信形式,例如信号 与条件变量方法类似,子线程将执行其工作,然后在完成时向父线程发送信号。 父线程将一直等到它从管道读取之前接收到信号,然后它可以向子节点发送一个信号,指示它已完成。

编辑:由于您使用fork而不是使用线程生成子进程,因此您不能在此处使用条件变量(父级和子级将具有单独的副本)。

相反,您可以使用signal()kill()函数在进程之间发送信号。 在分叉之前,使用getpid存储父pid的副本(用于子进程)。 还存储fork的返回值,因为它将包含子的pid。

要向其他进程发送信号,请使用以下内容:

kill(parent_pid, SIGUSR1);

接收过程需要设置信号处理程序。 例如:

int signal_received = 0;
void signal_handler(int signal_num) {
    if (signal_num == SIGUSR1)
        signal_received = 1;
}

signal(SIGUSR1, signal_handler);

现在,只要进程收到信号编号SIGUSR1就会自动调用signal_handler函数。 你的线程会在一个循环中等待,看着这个变量改变使用类似的东西:

while (1) { // Signal processing loop
    // Wait here for a signal to come in
    while (!signal_received) { sleep(1); }

    // Wake up and do something
    read_from_pipe();
    ...
    signal_received = 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM