gpt4 book ai didi

c - 如何检查流是否在此进程间通信案例中完成(在 C 中)?

转载 作者:太空宇宙 更新时间:2023-11-04 04:22:42 25 4
gpt4 key购买 nike

我正在编写与另一个程序交互的代码。

    FILE* streamout = fdopen(fdout[0],"r");

我已经使用 fdopen 之前所示的那样来处理读取,就像从文件中读取一样。问题是我不知道在以下循环中尝试从 streamout 中读取时使用什么停止条件。

while(fgets(endbuffer,sizeof(endbuffer),streamout) != NULL)
{
strcat(buffer,endbuffer);
}

程序永远不会退出 while 循环,即使流式传输结束也是如此。

编辑

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>

//this function returns when it receives a particular response ie: imready
void wait_until_ready(FILE *,FILE *);

int main(){

int fdin[2];
int fdout[2];

pid_t pid;

if ((pipe(fdin)<0)||(pipe(fdout)<0))
{
perror("pipe error");
exit(1);
}

if ((pid = fork())<0)
{
perror("fork error");
exit(2);
}

if (pid == 0)
{
close(fdin[1]);
close(fdout[0]);
dup2(fdin[0],0);
dup2(fdout[1],1);
execlp("stockfish","stockfish",0);
}
else
{
close(fdin[0]);
close(fdout[1]);
FILE* streamin = fdopen(fdin[1],"w");
FILE* streamout = fdopen(fdout[0],"r");
char buffer[1024];
wait_until_ready(streamin,streamout);
fprintf(streamin,"position startpos\n");
fprintf(streamin,"go\n");
fflush(streamin);

while (fgets(endbuffer,sizeof(endbuffer),streamout) != NULL)
{
strcat(buffer,endbuffer);
}
}

return 0;
}

最佳答案

我引用了一个经验法则(引用我自己,AFAIK):

  • 如果您使用 dup()dup2() — 或 fcntl()如果您是受虐狂 — 要将管道的一端复制到标准输入或标准输出,您应该关闭原始管道的两端(1 × pipe (), 1 × dup2() ⇒ 2 × close()).

子代码

你声称你这样做了。您的代码显示您没有。你有:

if (pid == 0)
{
close(fdin[1]);
close(fdout[0]);
dup2(fdin[0],0);
dup2(fdout[1],1);
execlp("stockfish","stockfish",0);
}

你需要:

if (pid == 0)
{
dup2(fdin[0],0);
dup2(fdout[1],1);
close(fdin[0]);
close(fdin[1]);
close(fdout[0]);
close(fdout[1]);
execlp("stockfish","stockfish",0);
fprintf(stderr, "Failed to execute 'stockfish'\n");
exit(EXIT_FAILURE);
}

如果不这样做,您可能会遇到问题。如果你小心的话,你可以在 dup2() 调用之前做一些关闭(你原来的两个 close() 调用很好,但我将所有四个组合在一起修改后的版本)。如果您在 dup2() 调用之后同时执行这两个操作,您可以对操作进行相当数量的重新排序,以判断每对中哪个 close() 先出现,哪个第二。您可以先在一个管道上执行所有操作,然后再在另一个管道上执行任何操作。等等

请注意,如果 execlp() 失败,您应该确保退出——或采取其他适当的规避措施。它迟早会发生,而且通常会导致麻烦。有些人主张 _exit() 而不是 exit()。如果您在 fork() 之前刷新了挂起的 I/O,应该没有问题。

父代码

父代码乍一看还不错。您没有将 dup2() 用于标准输入或标准输出,因此只需关闭管道的两个未使用的末端即可。

您给 child 写了一条信息。你……哦,你没有关闭到 child 的管道 (fclose(streamin);) ……所以你把消息写给 child ,你得到了回应,但是 child 现在等待来自 parent 的下一个命令,而 parent 正在等待来自 child 的更多数据。所以他们陷入了僵局 — 两个进程都在等待对方做某事,但都不会做对方需要的事情,所以他们陷入了僵局。

如果您打算将单个消息写入stockfish,那么您需要在进入读取循环之前调用fclose(streamin);。如果您需要发送更多消息,您必须知道如何判断 stockfish 已完成当前消息,以便您可以打破循环并返回以发送下一条命令。这可能是另一行说 imready 就像 wait_until_ready() 函数寻找的那样。所以你可能需要:

buffer[0] = '\0';   // Make sure that strcat() works sanely

while (fgets(endbuffer, sizeof(endbuffer), streamout) != NULL)
{
if (strcmp(endbuffer, "imready\n") == 0)
break;
// check for buffer overflow, etc before blithely appending!
// this is not efficient; it is sufficient, though.
if (strlen(buffer) + strlen(endbuffer) + 1 >= sizeof(buffer))
break;
strcat(buffer, endbuffer);
}

关于c - 如何检查流是否在此进程间通信案例中完成(在 C 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44873379/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com