我试图在while-true
循环中等待waitpid()
和read()
。具体来说,我正在等待这两个事件中的任何一个,然后在循环的每次迭代中对其进行处理。目前,我有以下实现(我不希望这)。
while (true) {
pid_t pid = waitpid(...);
process_waitpid_event(...);
ssize_t sz = read(socket, ....);
process_read_event(...);
}
此实现的问题是第二事件的处理取决于第一个事件的完成。我希望不再处理这两个事件,而是希望处理循环的每次迭代中首先发生的任何事件。我应该怎么做?
如果您不想触摸线程,则可以将其包含在waitpid
的调用选项中:
pid_t pid = waitpid(pid, &status, WNOHANG);
从 waitpid
的manpage中:
wnohang-如果没有孩子退出,请立即返回。
因此,如果waitpid
还没有准备好,它将不会阻止,并且该程序将继续进入下一行。
至于read
,如果它阻止了您,您可能想看看poll(2)
。您可以从本质上检查一下您的套接字是否准备就绪,例如250ms,然后在当时致电read
。这将允许它不阻止。
您的代码看起来有点像这样:
// Creating the struct for file descriptors to be polled.
struct pollfd poll_list[1];
poll_list[0].fd = socket_fd;
poll_list[0].events = POLLIN|POLLPRI;
// POLLIN There is data to be read
// POLLPRI There is urgent data to be read
/* poll_res > 0: Something ready to be read on the target fd/socket.
** poll_res == 0: Nothing ready to be read on the target fd/socket.
** poll_res < 0: An error occurred. */
poll_res = poll(poll_list, 1, POLL_INTERVAL);
这只是假设您是从套接字中的read
,从代码中的变量名来判断。正如其他人所说的那样,您的问题可能需要一些更重的重型。
,如果您不想在程序中使用线程,@DanielPorteous的答案也应起作用。
这个想法很简单,除非他们花了一些时间来执行操作,否则不让waitpid
和read
功能等待。这个想法是保持超时机制,以便,如果waitpid
对整个操作没有影响,它将立即返回,并且读取操作也会发生同样的事情。
如果read
功能需要很长时间才能读取整个缓冲区,则可以从read
函数手动限制读数,以免一次读取整体,而是读取2毫秒,然后传递周期到执行waitpid
函数。
但是可以安全地用于您的目的,并且非常易于实现。这是关于如何实现线程的好指南。
在您的情况下,您需要声明两个线程。
pthread_t readThread;
pthread_t waitpidThread;
现在您需要创建线程并将特定函数作为其参数传递。
pthread_create(&(waitpidThread), NULL, &waitpidFunc, NULL);
pthread_create(&(readThread), NULL, &readFunc, NULL);
现在,您可能必须编写waitpidFunc
和readFunc
功能。他们看起来像这样。
void* waitpidFunc(void *arg)
{
while(true) {
pid_t pid = waitpid(...);
// This is to put an exit condition somewhere.
// So that you can finish the thread
int exit = process_waitpid_event(...);
if(exit == 0) break;
}
return NULL;
}
我认为在这种情况下的正确工具是select
或poll
。两者都在做同样的工作。他们允许选择可用输入的那些描述符。因此,例如,您可以在两个插座上同时等待。但是,在您的情况下,它不能直接使用,因为您想等待流程和套接字。解决方案将是创建一个管道,该管道将在等待夹完成时会收到一些东西。
您可以启动一个新线程,并将其与原始螺纹一起使用管道连接。新线程将调用waitpid
,完成后,它将将其结果写入管道。主线程将使用select
等待插座或管道。