Я реализую канал в 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
Выполнить производителя во всех терминалах одновременно, передавая каждому выполнению связанный идентификатор, передаваемый командной строкой. Пример: ./producer 0, ./producer 1.
После того, как производитель отправит сообщения несколько раз (в среднем по 10), один произвольный производитель внезапно остановит его выполнение, показывая проблему.
На следующем рисунке изображено исполнение:
Терминалы готовы к выполнению
На следующем рисунке изображена ошибка идентификатора производителя 3
Ошибка производителя 3
Заранее спасибо