Чтение и запись в один и тот же файл с использованием именованного канала на C

#c #linux #bash

#c #linux #bash

Вопрос:

Более конкретно, предполагается, что программа эмулирует команду bash cat file| grep $keyword > file . Что я сделал: в родительском я считываю каждый символ из файла и форматирую их в строки, которые затем отправляю в именованный канал, затем в дочернем записываю строки, содержащие ключевое слово, в исходный файл.

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

Любая помощь с реализацией / объяснением того, почему именно возникает ошибка, была бы отличной.

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

char key[20], *c,line[40];
int fd,fd_r,fd_w,fd_fr,fd_fw,counter=0;

int main(){

pid_t pid;
mkfifo("fifo1",0777);
fgets(key,10,stdin);

int k=0;

if ((pid=fork()) < 0)
        perror("err_fork");

if(pid){ //PARENT

        printf("%dn",fd_r=open("prog.c",O_RDONLY));
        printf("%dn",fd_fw=open("fifo1",O_WRONLY));
        while(read(fd_r,c,1)){
                line[k  ]=(*c);
                while(read(fd_r,c,1) amp;amp; ((*c)!='n'))
                        line[k  ]=(*c);
                line[k]=0;
                write(fd_fw,line,strlen(line) 1);
                memset(line,0,sizeof(line));
        }
        close(fd_r);
        close(fd_fw);
}
else{   //CHILD
        printf("%dn",fd_w=open("prog.c",O_WRONLY));
        printf("%dn",fd_fr=open("fifo1",O_RDONLY));
        while(read(fd_fr,line,sizeof(line))){
                c=strstr(line,key);
                if(c)
                        write(fd_w,line,strlen(line) 1);
        }
        close(fd_w);
        close(fd_fr);
}

unlink("fifo1");
}
  

Комментарии:

1. Вы знаете, что команда bash cat file| grep $keyword > file принципиально не будет работать? Обычно это просто усекает файл. Я полагаю, вы можете эмулировать его прерывистость, если действительно хотите, но какой в этом смысл?

2. Кроме того, while(read(...)) это не очень хороший способ решения проблем, потому что в случае ошибки read() возвращает -1 значение, отличное от нуля, и, следовательно, приведет к продолжению цикла, даже если c он не содержит новых данных.

3. Если вам не нужно различать error и EOF, вы можете использовать while (read(...) > 0)

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

5. @NateEldredge Это не эмулирует эту прерывистость, потому что она не используется O_TRUNC при открытии выходного файла.

Ответ №1:

Вы нарушаете сегментацию, потому что пытаетесь прочитать байт c . Однако, c является неинициализированным глобальным указателем и, следовательно, равен NULL . Поэтому попытка считывания данных в этом месте является недопустимым использованием памяти.

Вместо этого вы объявляете

 char c;
  

и затем

 read(fd_r,amp;c,1)
  

Комментарии:

1. Ну, он глобальный, поэтому инициализируется значением NULL. Но на самом деле, вы не можете читать в нем.