系统相关
首页 > 系统相关> > fifo linux-write()函数突然终止程序

fifo linux-write()函数突然终止程序

作者:互联网

我正在用C实现一个管道,其中多个生产者程序(在我的情况下为9)将数据写入一个单一的消费者程序.

问题在于,某些生产者(有时是一两个)有时会在调用write()函数时突然退出程序.

代码很简单,这是生产者代码:

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>

#define MSG_SIZE_BYTES 4

void send(unsigned int * msg){

    int fd, msg_size;
    int r;
    char buffer [5];
    char myfifo[50] = "/tmp/myfifo";

    fd = open(myfifo, O_WRONLY);

    if(fd == -1){
        perror("error open SEND to fifo");
    }

    r = write(fd, msg, MSG_SIZE_BYTES);

    if(r == -1){
        perror("error writing to fifo");
     }

    close(fd);
    printf("Message send\n");
}

int main(int argc, char *argv[]){
    int cluster_id = atoi(argv[1]);
    unsigned int msg[1];
    msg[0] = cluster_id;

    while(1){
        printf("Press a key to continue...\n");
        getchar();
        send(msg);
    }
}

这是消费者代码

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>

#define MSG_SIZE_BYTES 4

int receive(unsigned int * received_msg){
    int fd, msg_size;
    int ret_code;
    char buffer [5];
    char myfifo[50] = "/tmp/myfifo";

    fd = open(myfifo, O_RDONLY);

    if(fd == -1) 
       perror("error open RECV to fifo");

    ret_code = read(fd, received_msg, MSG_SIZE_BYTES);

    close(fd);

    if (ret_code == -1){
        printf("\nERROR\n");    
        return 0;
    }

    return 1;
}

void main(){

    mkfifo("/tmp/myfifo", 0666);

    unsigned int msg[1];
    while(1){
       receive(msg);
       printf("receive msg from id %d\n", msg[0]);

    }
}

我正在使用以下命令编译生产者和消费者:gcc -o my_progam my_program.c

要重现该问题,您需要打开9个终端以运行每个生产者,并打开1个终端以运行使用者.
执行使用者:./consumer

同时在所有终端中执行生产者,并将每次通过命令行传递的关联ID传递给每次执行.例如:./生产者0,./生产者1.

生产者发送消息几次(平均10次)后,一个任意的生产者将突然停止执行,从而显示问题.

下图描述了执行:
Terminals ready to execute

下图描述了生产者ID 3上的错误
Error on producer 3

提前致谢

解决方法:

消费者程序在读取数据后似乎关闭了管道的读取端:

fd = open(myfifo, O_RDONLY);

if(fd == -1){
     perror("error open RECV to fifo");
}
ret_code = read(fd, received_msg, MSG_SIZE_BYTES);

close(fd);

当前正在尝试写入()数据(即在write()-syscall中被阻止)的所有其他写入器现在都收到SIGPIPE,这导致程序终止(如果未指定其他信号处理).

生产者编写时,您的使用者程序可能无法关闭文件描述符.只需阅读下一个基准而不关闭.

标签:fifo,named-pipes,c-3,linux
来源: https://codeday.me/bug/20191211/2106940.html