gpt4 book ai didi

当写入器速度快于读取器时,C FIFO 崩溃

转载 作者:行者123 更新时间:2023-11-30 18:44:39 28 4
gpt4 key购买 nike

我有一个使用 fork 的父进程和子进程,它们使用 FIFO 管道进行通信。当写入进程(父进程)比读取进程(子进程)运行得更快时,程序有时会工作,有时会崩溃。

以下代码是我目前拥有的代码。

void writeprocess(char* text);
void readprocess(void);

#define FIFO_NAME "MYTESTFIFO"
#define MAX 200

int main(int argc, const char * argv[]) {
pid_t pid;
pid = fork();

if(pid==0){
printf("Started child process.\n");
mkfifo(FIFO_NAME, 0666);
readprocess();
printf("Child process finished.\n");
exit(EXIT_SUCCESS);
}
else{
printf("Started parent process.\n");
mkfifo(FIFO_NAME, 0666);

writeprocess("Message 1");
writeprocess("Message 2");
writeprocess("Message 3");
writeprocess("Message 4");
writeprocess("terminate");

printf("Waiting for child process to finish.\n");
int returnStatus;
waitpid(pid, &returnStatus, 0);
printf("Parent process also finished.\n");
exit(EXIT_SUCCESS);
}
}

void writeprocess(char* text){
FILE *fp;
char *send_buf;

fp = fopen(FIFO_NAME, "w");
asprintf( &send_buf, "%s\n", text);
if ( fputs( send_buf, fp ) == EOF )
{
fprintf( stderr, "Error writing data to fifo\n");
exit( EXIT_FAILURE );
}
printf("Message send: %s", send_buf);
free( send_buf );

fclose(fp);
}

void readprocess(){
sleep(1);
FILE *fp;
char *str_result = NULL;
char recv_buf[MAX];

int stringdifference = 1;

while (stringdifference)
{
fp = fopen(FIFO_NAME, "r");
str_result = fgets(recv_buf, MAX, fp);
if ( str_result != NULL )
{
printf("Message received: %s", recv_buf);
}
fclose( fp );

stringdifference = strncmp(str_result, "terminate", 9);
}
}

当写入器写入 FIFO 管道的速度比读取器读取的速度快时,我会收到退出错误,并显示以下消息:“由于信号 13 而终止”。如何避免这种情况发生,同时保持程序以最佳性能运行?

我确实希望父进程能够结束该进程,并且我必须继续使用 FIFO 管道工作。

最佳答案

When the writer writes faster to the FIFO pipe than the reader can read, I get an exit error with the following message: "Terminated due to signal 13".

您错误地描述了问题的性质。正如您的其他答案已经观察到的那样,信号 13 是 SIGPIPE,如果您尝试写入没有读取器的管道,则会传递该信号。

通常有一些(有限的)保护措施来防止 FIFO 进入这种情况,即打开 FIFO 的一端会阻塞,直到另一端也打开为止。因此,如果一个进程成功打开 FIFO,它就知道最初有另一个进程的另一端打开。写入端打开的一方可以预期写入成功的可能性很高(但不一定不会阻塞)。然而,一旦最后一个读取器关闭 FIFO,进一步尝试写入它就会导致将 SIGPIPE 传递给写入器。当然,如果同一个或新的读取器打开 FIFO,则允许恢复写入——这对于 FIFO 来说是可能的,但对于普通管道来说是不可能的。

所以问题不在于读取器没有跟上,而在于它不断地打开和关闭 FIFO。这会产生竞争条件,因为写入器在尝试写入时会在多个时间间隔内引发 SIGPIPE。由于写入器重复打开和关闭 FIFO,因此要接收 SIGPIPE,写入器必须在读取器在收到上一条消息后关闭 FIFO 之前重新打开 FIFO,但是这并不意味着作者超越了读者。读者无法在作者写完之前读完给定的消息,因此他们的行为是交错的。在关闭 FIFO 和重新打开它之间,写入器没有执行任何其他操作,因此有时在读取器关闭之前重新打开它也就不足为奇了。

解决方案很简单:让每个进程保持管道持续打开,直到完成与其他进程的通信。每条消息的打开和关闭没有任何好处,但有很多缺点。但是,对于您的特定用途,将编写器的流置于行缓冲模式( setvbuf() ;默认情况下将是完全缓冲的)可能会有所帮助。

关于当写入器速度快于读取器时,C FIFO 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57294675/

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