#c #linux #named-pipes #fifo #systems-programming
#c #linux #именованные каналы #fifo #системы-программирование
Вопрос:
У меня есть очень простая базовая программа, в которой есть два процесса: первый — это parent
и второй — это child
.
Дочерний процесс должен записать некоторые данные в FIFO
. После завершения всех заданий на запись (после завершения дочернего процесса). Затем родительский процесс должен прочитать весь FIFO
файл и распечатать в stdout
.
Итак, я думаю, мне нужен wait(NULL);
for parent
. Таким образом, parent
будет ждать, пока child
завершится. Но child
также блокируется из-за записи и блокируется для чтения этих записей. Итак, оба процесса ожидают друг друга, и я думаю, возникает взаимоблокировка.
Моя программа такова:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
int writeSomeStuffToFifo ();
void printAllFifo ();
char * myfifo = "myfifo";
int main(int argc, char **argv) {
int pid=0;
int childPid=-1;
int status;
pid=fork();
if ((pid = fork()) < 0){
perror("fork() error");
}
else if (pid == 0) {
writeSomeStuffToFifo ();
exit(1);
}
else do {
if ((pid = waitpid(pid, amp;status, WNOHANG)) == -1)
perror("wait() error");
else if (pid == 0) {
//child running
printf("child runningn");
}
else {
if (WIFEXITED(status)){
printf("child is terminatedn");
printAllFifo();
}
else{
printf("child did not exit successfullyn");
}
}
} while (pid == 0);
return 0;
}
int writeSomeStuffToFifo (){ //child process will run this function
int fd;
mkfifo(myfifo, 0666);
fd = open(myfifo, O_WRONLY);
write(fd,"foo1n",strlen("foo1n"));
close(fd);
fd = open(myfifo, O_WRONLY);
write(fd,"foo2n",strlen("foo2n"));
close(fd);
fd = open(myfifo, O_WRONLY);
write(fd,"foo3n",strlen("foo3n"));
close(fd);
}
void printAllFifo (){ //parent process will run this function
int fd=open(myfifo, O_RDONLY);
char* readBuffer=(char*)malloc((strlen("foo1n") strlen("foo2n") strlen("foo3n"))*sizeof(char));
read(fd, readBuffer, strlen("foo1n") strlen("foo2n") strlen("foo3n"));
printf("%sn",readBuffer );
close(fd);
}
Ответ №1:
mkfifo()
создает канал ограниченного размера. Вы не должны ждать в родительском процессе, пока дочерний процесс не завершит чтение, чтобы начать чтение, вы должны постоянно читать в родительском процессе, проверяя, завершился ли уже дочерний процесс.
Вы можете использовать ulimit -p
для чтения размера каналов по умолчанию в вашей системе Linux. Число умножается на 512, поэтому значение 8 означает 4096 байт.
Использование pipe()
больше подходит для этой задачи, чем mkfifo()
потому что вам на самом деле не нужен именованный канал. это предоставит вам 2 fds, один для чтения и один для записи. В родительском коде вы закрываете поле записи, в дочернем коде вы закрываете поле чтения, затем вы можете начать чтение из канала в родительском коде, пока он не вернет значение <= 0. Это означало бы, что дочерний процесс завершился (и канал был закрыт для записи). тогда вам нужно только вызвать waitpid()
из родительского кода, чтобы собрать завершенный дочерний процесс.
Комментарии:
1. Я все еще не понял, как я могу решить проблему tihs. Как я могу увеличить размер канала? Не могли бы вы объяснить с помощью кодов?
2. Вы не увеличиваете размер. Вы просто читаете из него перед завершением дочернего процесса.
3. Во-первых, я должен использовать
fifo
beacuse, я буду использовать его в своей домашней работе. Кроме того, если я прочитаю из него до завершения дочернего процесса, дочерний процесс не сможет записать все содержимое, и родительский файл не будет прочитан.4. Родительскому процессу необходимо выполнять чтение в цикле, пока он не обнаружит, что канал был закрыт для записи.
5. Хорошо, тогда как я могу контролировать, чтобы канал был закрыт для записи?