Прочитать все символы, записанные в FIFO, используя системный вызов open()

У меня есть канал FIFO, который открывается с обоих концов с помощью open() в режиме O_RDWR. В конце чтения read() читает не все символы, а меньше, чем указано в вызове. Есть ли способ убедиться, что все символы читаются с помощью open()?

заранее спасибо

if (p != NULL){

        printf("Inside p not null!\n");

        if((fd = open(p, O_RDWR)) < 0){
            perror("File could not be opened!");
            exit(EXIT_FAILURE);
        }

        //FILE *rdptr = fopen(p,"r");

        memset(buf,0,file_len);
        rc = read(fd, buf, file_len);
        printf("Number of bytes read: %d\n", rc);

        printf("Data detected on FIFO\n");
                buf[rc] = '\0';
                char base[20] = "output.txt";
                char name[20];
                sprintf(name, "%d%s", suffix, base);
        FILE *fptr = fopen(name,"ab+");
        fd_wr = open(name,O_WRONLY);
        charnum = write(fd_wr,buf,rc);
        kill(id_A, SIGKILL);
        //printf("No. of characters written: %d\n",charnum);
                //FD_CLR(fd, &rdfs);
    }

person user3033194    schedule 28.11.2014    source источник
comment
Вы пытались снова вызвать read() для чтения оставшихся символов?   -  person saeedn    schedule 28.11.2014
comment
Нет, я просто читаю это один раз. Код добавлен в отредактированный пост. Я не уверен, как это сделать.   -  person user3033194    schedule 28.11.2014
comment
Если вы записываете фиксированный объем данных, а затем убиваете записывающего, почему бы вам просто не использовать вместо этого файл? Кажется, вам не нужен FIFO здесь.   -  person nneonneo    schedule 28.11.2014
comment
Нет, на самом деле каждый пишущий должен записывать в отдельный FIFO, который считывается описанным выше процессом, а затем убивает пишущего. FIFO является частью требования. Я не могу это изменить.   -  person user3033194    schedule 28.11.2014


Ответы (1)


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

Вторая проблема: если file_len очень велико, возможно, модуль записи заблокировал попытку записать весь фрагмент данных (поскольку FIFO может содержать только определенное количество непрочитанных данных). Если это так, то read будет читать только те данные, которые были сохранены в FIFO, и немедленно вернется с тем, что может прочитать. Это позволит писателю записать больше байтов, которые затем будут прочитаны в следующем read.

Вы должны зацикливать чтение, регулируя смещение в буфере, пока не будут прочитаны все file_len байт. Что-то вроде этого:

size_t offset = 0;
while(offset < file_len) {
    rc = read(fd, buf+offset, file_len-offset);
    if(rc < 0) {
        /* handle I/O error or something... */
    } else {
        offset += rc;
    }
}
person nneonneo    schedule 28.11.2014
comment
извините, я не смог правильно отформатировать, но это то, что вы имеете в виду? - person user3033194; 28.11.2014
comment
read выдаст некоторый частичный вывод, и вам нужно увеличить смещение, чтобы прочитать больше. (Это как чтение книги: вы начинаете с того места, на котором остановились, а не с самого начала). - person nneonneo; 28.11.2014
comment
С помощью этого кода я пытаюсь напечатать rc после выхода из цикла while, но этого не происходит. Кажется, цикл не выходит, может быть, потому что чтение заблокировано или что-то в этом роде. - person user3033194; 28.11.2014
comment
может есть способ сбросить FIFO? Не знаю, правильный ли это термин. - person user3033194; 28.11.2014