fifo linux - write() 函数突然终止程序
fifo linux - write() function terminates the program abruptly
我正在用 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 传递给每个执行。例如:./producer 0, ./producer 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()
数据(即在 write()
-系统调用中被阻止)的所有其他写入器现在收到 SIGPIPE
,这将导致程序终止(如果未指定其他信号处理)。
您的消费者程序可能不会在生产者写入时关闭文件描述符。不关闭直接读取下一个数据
问题已解决:
问题是我在每条消息处打开和关闭 FIFO,在一些写入尝试中生成了一个 Broken pipe。在代码开始而不是在循环内为生产者和消费者删除 close() 并插入 open() 函数解决了问题。
修复错误的生产者代码如下:
#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 my_fd;
void send(unsigned int * msg){
int fd, msg_size;
int r;
char buffer [5];
char myfifo[50] = "/tmp/myfifo"
if(fd == -1){
perror("error open SEND to fifo");
}
r = write(my_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;
my_fd = open("/tmp/myfifo", O_WRONLY);
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 my_fd;
int receive(unsigned int * received_msg){
int fd, msg_size;
int ret_code;
char buffer [5];
char myfifo[50] = "/tmp/myfifo";
if(fd == -1)
perror("error open RECV to fifo");
ret_code = read(my_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);
my_fd = open("/tmp/myfifo", O_RDONLY);
unsigned int msg[1];
while(1){
receive(msg);
printf("receive msg from id %d\n", msg[0]);
}
}
谢谢大家!!
我正在用 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 传递给每个执行。例如:./producer 0, ./producer 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()
数据(即在 write()
-系统调用中被阻止)的所有其他写入器现在收到 SIGPIPE
,这将导致程序终止(如果未指定其他信号处理)。
您的消费者程序可能不会在生产者写入时关闭文件描述符。不关闭直接读取下一个数据
问题已解决:
问题是我在每条消息处打开和关闭 FIFO,在一些写入尝试中生成了一个 Broken pipe。在代码开始而不是在循环内为生产者和消费者删除 close() 并插入 open() 函数解决了问题。
修复错误的生产者代码如下:
#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 my_fd;
void send(unsigned int * msg){
int fd, msg_size;
int r;
char buffer [5];
char myfifo[50] = "/tmp/myfifo"
if(fd == -1){
perror("error open SEND to fifo");
}
r = write(my_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;
my_fd = open("/tmp/myfifo", O_WRONLY);
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 my_fd;
int receive(unsigned int * received_msg){
int fd, msg_size;
int ret_code;
char buffer [5];
char myfifo[50] = "/tmp/myfifo";
if(fd == -1)
perror("error open RECV to fifo");
ret_code = read(my_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);
my_fd = open("/tmp/myfifo", O_RDONLY);
unsigned int msg[1];
while(1){
receive(msg);
printf("receive msg from id %d\n", msg[0]);
}
}
谢谢大家!!