2015-12-03 4 views
0

Я написал код для практики использования трубы и встретил некоторые проблемы.Может ли текстовый файл использоваться как труба?

Для кода ниже я попытался сделать именованный канал для записи/чтения. Но если в моем текстовом файле есть несколько слов, мой код не работает. Я ожидал, что на выходе будут напечатаны слова внутри текстового файла и строка, в которую я написал. Не могу ли я использовать файл .txt в качестве канала? Как использовать трубку для изменения текстового файла? Спасибо за помощь!

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

#define MAX 100 

int main() 
{ 
    int fd; 
    char *myfifo = "pipe_tx2.txt"; 
    char buf[MAX]; 

    /* create the fifo */ 
    mkfifo(myfifo, 666); 

    /* write string to the pipe */ 
    fd = open(myfifo, O_WRONLY); 
    write(fd, "hello", sizeof("hello")); 
    close(fd); 

    /* read and display message from pipe */ 
    fd = open(myfifo, O_RDONLY); 
    read(fd, buf, MAX); 
    printf("we got: %s\n", buf); 
    close(fd); 

    /* remove the pipe */ 
    unlink(myfifo); 

    return 0; 
} 
+7

Вы не проверяете возвращаемое значение из 'mkfifo()', 'write()' или 'read()'. Поэтому вы не знаете, что работает, а что нет. Вы даже не знаете, успешно ли ваши вызовы 'open()' или нет. –

+0

хорошо, спасибо за помощь! – KennyYang

+2

Я не уверен, что понимаю, что вы подразумеваете под «если в моем текстовом файле есть несколько слов, мой код не работает». Вы говорите, что у вас есть обычный файл с тем же именем, что и FIFO, который вы пытаетесь создать? Если так, то нет, это абсолютно не сработает. FIFO - это особый * вид * файла, а не специальный * use * для файла. –

ответ

2

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

Но, в худшем случае, семантика открытого/чтения/записи на именованном канале отличается от того, что используется для обычного файла. open для записи именованного канала блокируется, пока кто-то не откроет его для чтения, а наоборот. Таким образом, один процесс не может использовать именованный канал таким образом (помните, что каналы обычно предназначены для взаимодействия между процессами). Вам нужно открыть для чтения сначала в неблокирующем режиме, затем немедленно установить режим блокировки на будущее, а затем открыть для записи, чтобы часть записи была доступна.

Другая проблема заключается в том, что вы не отправляете правильные данные. Вы должны использовать strlen, чтобы поймать длину C-строки и добавить ее для подсчета и включить конечный символ NUL, поэтому чтение полной C-строки будет корректно в другой части.

2

Ваша непосредственная проблема заключается в том, что вы используете 666 вместо 0666 для режима работы FIFO, а это значит, у вас нет разрешения на его чтение. Код с дополнительной проверкой ошибок продемонстрирует это:

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

#define MAX 100 

int main() 
{ 
    int pid; 
    char *myfifo = "pipe_tx2.txt"; 

    unlink(myfifo);    /* if it already exists */ 
    /* create the fifo */ 
    if (mkfifo(myfifo, 666)) { 
     perror(myfifo); 
     return 1; 
    } 

    pid = fork(); 
    if (pid < 0) { 
     perror("fork"); 
     return 1; 
    } 

    if (!pid) { 
     /* child process - read and display message from pipe */ 
     char buf[MAX]; 
     int fd = open(myfifo, O_RDONLY); 
     int bytes_read; 
     if (fd < 0) { 
      perror(myfifo); 
      return 1; 
     } 

     bytes_read = read(fd, buf, MAX); 
     if (bytes_read < 0) { 
      perror("read"); 
      return 1; 
     } 
     printf("We got: %*s\n", bytes_read, buf); 
     close(fd); 
     return 0; 
    } 

    { 
     /* parent process - write string to the pipe */ 
     static const char message[] = "hello"; 
     sleep(2);    /* just to show that the child blocks until we write */ 

     int fd = open(myfifo, O_WRONLY); 
     int bytes_written; 
     if (fd < 0) { 
      perror(myfifo); 
      return 1; 
     } 
     write(fd, message, sizeof message); 
     if (bytes_written <= 0) { 
      perror("write"); 
      return 1; 
     } 
     close(fd); 
    } 

    waitpid(pid, NULL, 0); 

    /* remove the pipe */ 
    unlink(myfifo); 

    return 0; 
} 

Измените режим 0666, и вы больше не получите pipe_tx2.txt: Permission denied от процесса чтения.

Смежные вопросы