Intereting Posts
Почему для передачи 2-мерного массива в функцию требуется размер? Как эффективно получить первую десятичную цифру числа Каков эффективный способ получить diff из двух массивов в C? Более безопасные альтернативы стандартной библиотеке C Почему _mm_stream_ps производит пропуски кэша L1 / LL? Есть ли случай, когда целое число теряет свою точность при двойном литье? Создайте среду сборки для проекта «C» для динамического выбора папок во время компиляции почему этот код работает в C Разница между нулевым завершающим символом char (\ 0) и `^ @` getchar () и кондиционирование цикла для разрыва с определенным символом присваивание делает указатель из целого без cast Что происходит с возвращаемым значением main ()? Настройка для компилятора, отличного от значения по умолчанию при запуске configure C – переход от ncurses ui к внешней программе и обратно как избежать блокировки функции чтения?

Как подождать, пока данные будут записаны на другом конце трубы

Я разрабатываю приложение в C. Родительский и дочерний процесс обмениваются данными через канал. Перед записью в pipe родительский процесс выполняет другие инструкции. В примере кода я использовал sleep (10) для задержки. В дочернем процессе он должен читать данные из трубы. Но данные не читаются на считываемом конце канала в дочернем процессе.

int main() { int pid; FILE *fp; fp = fopen("test.txt","w"); char *buff; int fd[2]; int count = 0 ; pipe(fd); pid = fork(); if(pid == 0) { close(fd[1]); ioctl(fd[0], FIONREAD, &count); fprintf(fp,"Value of count: %d ",count); buff = malloc(count); fprintf(fp,"\n TIME before read: %s",__TIME__); read(fd[0], buff, count); fprintf(fp,"\nbuffer: %s\n TIME after read %s", buff, __TIME__); } else{ close(fd[0]); sleep(10); //delay caused by application specific code replaced with sleep write(fd[1],"THIS is it",10); } fclose(fp); return 0; } 

Как заставить дочерний процесс ждать, пока данные не будут записаны на другом конце?

Ваша труба открывается в режиме блокировки, и вы ничего не измените, что, вероятно, то, что вы намеревались.

Тем не менее, поскольку первое, что вы делаете, это запрос размера данных, ожидающих на трубе, затем слепо перепрыгнуть в чтение, что многие байты (которые, по всей вероятности, будут равны нулю во время выполнения кода, поскольку родитель еще ничего не написал ) вы не блокируете, а вместо этого просто уходите, потому что вы ничего не просили.

Существует несколько способов сделать это, включая цикл выбора. Если вы предпочтете блокировать чтение до тех пор, пока не будут доступны данные, сделайте это в одном байте и затем заполните оставшиеся данные.

Это ни в коем случае не пример того, как это сделать правильно , но это короткий пример того, как вы можете подождать по одному байту, запросить размер файла для чтения, чтобы получить остальную часть данных, прочитать его и продолжайте это до тех пор, пока в трубе не останется никаких данных, а родитель завершает их конец:

Надеюсь, вы сочтете это полезным.

 #include  #include  #include  int main() { int pid = 0; // create pipe pair int fd[2]; pipe(fd); pid = fork(); if (pid == 0) { // child side char *buff = NULL; char byte = 0; int count = 0; // close write side. don't need it. close(fd[1]); // read at least one byte from the pipe. while (read(fd[0], &byte, 1) == 1) { if (ioctl(fd[0], FIONREAD, &count) != -1) { fprintf(stdout,"Child: count = %d\n",count); // allocate space for the byte we just read + the rest // of whatever is on the pipe. buff = malloc(count+1); buff[0] = byte; if (read(fd[0], buff+1, count) == count) fprintf(stdout,"Child: received \"%s\"\n", buff); free(buff); } else { // could not read in-size perror("Failed to read input size."); } } // close our side close(fd[0]); fprintf(stdout,"Child: Shutting down.\n"); } else { // close read size. don't need it. const char msg1[] = "Message From Parent"; const char msg2[] = "Another Message From Parent"; close(fd[0]); sleep(5); // simulate process wait fprintf(stdout, "Parent: sending \"%s\"\n", msg1); write(fd[1], msg1, sizeof(msg1)); sleep(5); // simulate process wait fprintf(stdout, "Parent: sending \"%s\"\n", msg2); write(fd[1], msg2, sizeof(msg2)); close(fd[1]); fprintf(stdout,"Parent: Shutting down.\n"); } return 0; } 

Выход

 Parent: sending "Message From Parent" Child: count = 19 Child: received "Message From Parent" Parent: sending "Another Message From Parent" Parent: Shutting down. Child: count = 27 Child: received "Another Message From Parent" Child: Shutting down. 

Я думаю, после

 ioctl(fd[0], FIONREAD, &count); the count is 0. read(fd[0], buff, count) will get no data. try read(fd[0], buff, 10) 

Проблема заключается в получении количества байтов, записанных в трубу. Вы получаете это сразу после fork (). Если процесс чтения выполняется первым, он не будет содержать данных (и счетчик будет равен нулю). Если сначала выполняется процесс записи, он будет содержать некоторые данные.

Как заставить дочерний процесс ждать, пока данные не будут записаны на другом конце?

Так как вы открыли канал в режиме блокировки, вы должны прочитать как можно больше данных, а не пытаться получить размер письменных данных.


Вот ваш модифицированный пример, ожидающий полного сообщения:

 #include  #include  int main() { int pid; FILE *fp; fp = fopen("test.txt","w"); char *buff = malloc(1024); int fd[2]; int count = 0 ; pipe(fd); pid = fork(); if(pid == 0) { close(fd[1]); int i = 0; while ( i < 10 ) { fprintf(fp,"\n TIME before read: %s \n",__TIME__); read(fd[0], buff+i, 1); ++ i; } fprintf(fp,"Full message received!\nbuffer: %s\n TIME after read %s\n", buff, __TIME__); } else{ close(fd[0]); sleep(10); //delay caused by application specific code replaced with sleep write(fd[1],"THIS is it",10); } fclose(fp); return 0; }