Использование нескольких каналов в c - PullRequest
1 голос
/ 04 мая 2019

Я не хочу писать программу, которая использует 2 канала для передачи значений между родительским и дочерним процессами. Код:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>

int mkfifo(const char *path, mode_t mode);

int main(int argc, char **argv)
{
  int fd,df,val;
  char * myfifo = "/tmp/myfifo";
  mkfifo(myfifo, 0666);

  char * myfifo2 = "/tmp/myfifo2";
  mkfifo(myfifo2, 0666);

  pid_t c=fork();

  if(c==0){
    df = open(myfifo2, O_RDONLY);
    read(df, &val, sizeof(val));
    close(df);
    val= val+10;
    df = open(myfifo2, O_WRONLY);
    write(df, &val, sizeof(val));
    fd = open(myfifo, O_WRONLY); //if i put this write first print works and program finishes
    write(fd, &val, sizeof(val));

      }
  if(c>0)
   {
    val=1;
    df = open(myfifo2, O_WRONLY); 
    write(df, &val, sizeof(val)); 
    fd = open(myfifo, O_RDONLY);
    read(fd, &val, sizeof(val));
    printf("val is %d \n",val);

        }
}

При первом чтении потомка родитель ожидает записи val в файле fifo. После этого он записывает новый val в этот файл fifo, а затем записывает значение во второй текстовый файл. Чтение в коде родителя ожидает этого так что все, что я хочу, это чтобы родительский процесс выполнил печать только после того, как дочерний процесс записал val в файл myfifo2. Такова цель второго именованного канала, который я использовал. Однако этот код получает застрял и ничего не печатает. Я заметил, что если я изменяю порядок записи двух в дочернем процессе, он работает, но он не удовлетворяет вышеуказанной вещи, в которой я нуждаюсь. Почему это происходит и как мне решить эту проблему?

1 Ответ

2 голосов
/ 04 мая 2019

Что происходит

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

Более того, он поставляется с некоторыми оговорками:

  • Чтобы получить эффект "буферизации", необходимо открыть оба конца трубы (man 7 fifo)

    FIFO должен быть открыт с обоих концов (чтение и запись), прежде чем данные могут быть переданы. Как правило, открытие блоков FIFO до открытия другого конца.

  • Операции записи в конечном итоге блокируются, когда труба достигает своей емкости. Этот размер зависит от системы, но может быть установлен с помощью F_SETPIPE_SZ fcntl. Но также:

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

Итак, у вас есть такая ситуация:

  • Родитель (возможно, может даже не быть там) ждет в read в /tmp/myfifo.

  • /tmp/myfifo2 открывается WR_ONLY родителем.

  • ребенок звонит df = open(myfifo2, O_WRONLY);, открывая /tmp/myfifo2 также как WR_ONLY. Таким образом, конец чтения канала не открыт, поэтому вызов open блоков.

  • Тупик .

Чтобы решить эту проблему, достаточно открыть myfifo2 в дочернем элементе как чтение-запись , должно быть .

df = open(myfifo2, O_RDWR); // instead of df = open(myfifo2, O_WRONLY);

ИМО, однако, этот шаблон общения выглядит немного странно (и трудно понять).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...