У меня есть две программы, взаимодействующие через именованные каналы (на Mac), но размер буфера именованных каналов слишком мал.Программа 1 записывает 50 Кбайт в канал 1 перед чтением канала 2. Именованные каналы имеют размер 8 КБ (в моей системе), поэтому программа 1 блокируется, пока данные не будут использованы.Программа 2 считывает 20 Кбайт из канала 1, а затем записывает 20 Кбайт в канал 2.Pipe2 не может держать 20K, поэтому программа 2 теперь блокирует.Он будет выпущен только тогда, когда программа 1 выполнит чтение.Но программа 1 заблокирована в ожидании программы 2. deadlock
Я думал, что смогу решить эту проблему, создав программу-прокладку, которая читает stdin неблокирующую и записывает stdout неблокирующую, временно сохраняя данные в большом буфере,Я протестировал программу, используя данные кошки |./Gasket 0 |./gasket 1> out, ожидая, что будет копия данных.Однако, хотя первый вызов прокладки работает, как и ожидалось, чтение во второй программе возвращает 0 до того, как все данные будут использованы, и никогда не возвращает ничего, кроме 0 в последующих вызовах.
Я пробовал код ниже, обана MAC и Linux.Оба ведут себя одинаково.Я добавил ведение журнала, чтобы видеть, что при перезапуске второго вызова набивки не происходит никаких данных, даже если он не прочитал все данные, записанные первым вызовом.
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 100000
char buffer[BUFFER_SIZE];
int elements=0;
int main(int argc, char **argv)
{
int total_read=0, total_write=0;
FILE *logfile=fopen(argv[1],"w");
int flags = fcntl(fileno(stdin), F_GETFL, 0);
fcntl(fileno(stdin), F_SETFL, flags | O_NONBLOCK);
flags = fcntl(fileno(stdout), F_GETFL, 0);
fcntl(fileno(stdout), F_SETFL, flags | O_NONBLOCK);
while (1) {
int num_read=0;
if (elements < (BUFFER_SIZE-1024)) { // space in buffer
num_read = fread(&buffer[elements], sizeof(char), 1024, stdin);
elements += num_read;
total_read += num_read;
fprintf(logfile,"read %d (%d) elements \n",num_read, total_read); fflush(logfile);
}
if (elements > 0) { // something in buffer that we can write
int num_written = fwrite(&buffer[0],sizeof(char),elements, stdout); fflush(stdout);
total_write += num_written;
fprintf(logfile,"wrote %d (%d) elements \n",num_written, total_write); fflush(logfile);
if (num_written > 0) { // copy data to top of buffer
for (int i=0; i<(elements-num_written); i++) {
buffer[i] = buffer[i+num_written];
}
elements -= num_written;
}
}
}
}
Я полагаю,мог бы сделать прокладку многопоточным и использовать блокировку чтения в одном потоке и блокировку записи в другом, но я хотел бы понять, почему неблокирующая операция ввода-вывода кажется мне сломанной.
Спасибо!