читать не блокируя на именованном канале - PullRequest
11 голосов
/ 12 августа 2010

у меня есть следующий бит кода C, который читает из канала и затем должен блокировать, но никогда не блокирует

int pipe_fd;
int res;
int open_mode = O_RDONLY;
char buf[100];
int bytes_read = 0;

memset (buf, '\0', sizeof(buf));
pipe_fd = open(FIFO_NAME, open_mode);

if (access(FIFO_NAME, F_OK) == -1)
{
    res = mkfifo(FIFO_NAME, 0777);
    if (res != 0)
    {
            fprintf (stderr, "Could not create fifo %s\n", FIFO_NAME);  
            exit (EXIT_FAILURE);
    }
}

for(;;)
{        
    do     
    {     
        res = read(pipe_fd, buf, sizeof(buf));
        bytes_read += res;
    }while (res > 0);

    // process data then go back and block
    ............
}

Он посылается простым буфером с помощью некоторого кода в bash-скрипте, подобном следующему: './test 1'

#!/bin/bash

pipe=/tmp/pipe

if [[ ! -p $pipe ]]; then
    echo "Reader not running"
    exit 1
fi

if [[ "$1" ]]; then
     echo "some string" >$pipe
else
     echo "q" >$pipe
fi

Я запускаю программу C code в gdb, и первоначально она блокирует чтение, но как только я вызываю скрипт bash, код C больше не блокируется, он успешно считывает данные из буфер, а затем каждый раз, когда он читает, читается 0 байтов, поэтому не уверен, почему он больше не блокируется. Данные «некоторой строки» правильно получены на другой стороне.

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

Ответы [ 3 ]

16 голосов
/ 12 августа 2010

Я запускаю программу кода C в gdb, и первоначально она блокирует чтение, но как только я вызываю скрипт bash, код C больше не блокируется, он успешно считывает данные из буфера, а затем каждыйкогда он читает, читается 0 байт, поэтому не уверен, почему он больше не блокируется.Данные «некоторой строки» правильно получены на другой стороне.

0 означает EOF.FIFO может быть прочитан или записан только тогда, когда к нему подключены процессы как для чтения, так и для записи.Когда больше нет писателей (ваши сценарии оболочки прекращены), читатели получают уведомление об этом через read(), возвращая EOF.

FIFO ведут себя таким образом, чтобы быть совместимыми с логикой оболочки, например:

$ mkfifo ./tmp1
$ cat < input > ./tmp1 &
$ cat < ./tmp1 > /dev/null

Если read() не вернет EOF, второй cat будет заблокирован навсегда.

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

В вашей C-программе вы должны повторно open() FIFO после того, как read() вернул EOF в первый раз.

PS Найдено довольно хорошее резюме FIFO для тебя.Проверьте таблицу на второй странице.

0 голосов
/ 26 апреля 2014

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

Итак, сценарий записи должен открыть канал и многократно использовать открытый дескриптор, чтобы что-то написать и, наконец, закрыть открытый дескриптор.

0 голосов
/ 12 августа 2010

ваш bash-скрипт закрывает канал, поэтому C получает условие "eof"

...