2017-11-15 3 views
1

두 개의 서로 다른 프로세스에서 두 개의 파일이 열려 있습니다. 두 개를 연결하는 파이프가 있습니다. 한 파일에서 다른 파일로 직접 쓸 수 있습니까? 특히 프로세스 읽기가 파일의 크기를 모르는 경우에는 읽으려고합니다.파이프를 통해 FILE * 쓰기

나는이

#define length 100 
int main(){ 
    int frk = fork(); 
    int pip[2]; 
    pipe(pip); 
    if (frk==0){ //child 
    FILE* fp fopen("file1", "r"); 
    write(pip[1],fp,length); 
    } 
    else { 
    FILE* fp fopen("file2", "w"); 
    read(pip[0],fp,length); 
} 
+2

'파이프 (핍)'은'포크()하기 전에해야한다;'. – mch

+0

분기 후에 파이프를 만드는 것이 불가능합니까? –

+2

'pipe' 함수를 사용하면 yes입니다. 또한'write'와'read'를 잘못 사용하고 있고, 두번째 매개 변수는 버퍼이며,'FILE'에 대한 포인터가 아닙니다. 'FILE * fp' 다음에'='를 잊어 버렸습니다. – mch

답변

3

같은 뭔가를 기대했다가 다른 하나 개의 파일에서 직접 쓸 수 있습니까?

C는 어떤 메커니즘도 제공하지 않으며 특수한 하드웨어 지원이 필요한 것 같습니다. 표준 I/O 패러다임은 데이터가 소스에서 메모리로 읽히거나 메모리에서 대상으로 쓰여지는 것입니다. 그 중간에 성가신 "기억"은 한 파일에서 다른 파일로 직접 복사 할 수 없다는 것을 의미합니다.

물론 이러한 복사본을 수행하는 기능이나 프로그램을 작성하여 세부 정보를 숨길 수 있습니다. 결국 cp 명령이 수행하지만 C 표준 라이브러리에는 그 목적을위한 함수가 포함되어 있지 않습니다.

특히 프로세스 읽기가 읽으려는 파일의 크기를 모르는 경우?

그 비트는별로 중요하지 않습니다. 하나는 읽은 것을 단순히 쓴 다음 쓴다. "더 읽을 것이 없다"는 것은 읽기 시도가 반환 값에 의해 파일의 끝에 도달했음을 나타냅니다.

하나의 프로세스가 하나의 파일을 읽고 다른 프로세스가 다른 파일에 데이터를 쓰고 파이프를 사용하여 두 프로세스간에 데이터를 전달하려면 두 패턴 모두를 구현해야합니다. 하나는 소스 파일에서 읽고 파이프에 쓰고 다른 하나는 파이프에서 읽고 대상 파일에 씁니다.

특별 참고 사항 : 파이프에서 읽는 프로세스가 해당 파이프에서 EOF를 감지 할 경우 두 프로세스에서 다른 끝을 닫아야합니다. 포크 후 각 프로세스는 사용하지 않을 파이프 끝을 닫을 수 있고 닫아야합니다. 쓰기 엔드를 사용하는 사용자는 쓰기 작업이 더 이상 없을 때 해당 엔드를 닫습니다.

1

BSD와 같은 다른 유닉스 시스템에서는 두 가지 파일 기술자를 직접 연결하여 원하는 것을 수행 할 수 있지만 Linux에서 수행 할 시스템 호출이 있는지 여부는 알 수 없습니다. Anywya는 FILE * 설명자로 수행 할 수 없습니다. 이는 버퍼 파일의 인스턴스이므로 <stdio.h> 라이브러리가 파일을 나타내는 데 사용됩니다. getfd(3) 함수 호출을 호출하여 FILE * 인스턴스의 파일 설명자를 얻을 수 있습니다 (시스템이 알고있는 것처럼).

시스템에서 얻으려고하는 의미 체계는 매우 정교합니다. 프로세스 설명 (커널에 직접 포함됨)없이 하나의 파일 디스크립터에서 다른 파일 디스크립터로 직접 데이터를 전달하기를 원하기 때문에, 커널 요구 사항 스레드 풀은 읽기 호출에서 쓰기 호출로 직접 복사하는 작업을 수행합니다.

오래된 방법은 하나의 파일 설명자 (FILE * 포인터가 아님)에서 읽는 작업을 만들고 다른 쪽 쓰기 작업을하는 스레드를 만드는 것입니다.

언급 할 또 다른 점은 pipe(2) 시스템 호출이 당신에게 두 번째의 write(2) N합니다 (1 인덱스)이 무엇인지는 1 개 (0 인덱스)에 read(2) 당신을 수있는 두 가지 연결 설명을 제공한다는 것입니다. 두 번째 프로세스가 fork(2)이고 두 프로세스 모두에서 pipe(2) 호출을 수행하면 각 프로세스에 하나씩 (두 개의 설명자가있는) 두 개의 파이프가 있고 둘 사이에 관계가 없습니다. 각 프로세스를 자신과 만 통신 할 수 있지만 다른 프로세스의 파이프 설명자에 대해 알지 못하는 다른 프로세스와 통신 할 수 없으므로 이들 사이의 통신은 불가능합니다.

다음은 당신이하려고 무엇의 완벽한 예입니다

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

#define length 100 

#define FMT(fmt) "pid=%d:"__FILE__":%d:%s: " fmt, getpid(), __LINE__, __func__ 
#define ERR(fmt, ...) do {     \ 
      fprintf(stderr,      \ 
        FMT(fmt ": %s (errno = %d)\n"), \ 
        ##__VA_ARGS__,     \ 
        strerror(errno), errno);  \ 
      exit(1);       \ 
     } while(0) 

void copy(int fdi, int fdo) 
{ 
    unsigned char buffer[length]; 
    ssize_t res, nread; 

    while((nread = res = read(fdi, buffer, sizeof buffer)) > 0) { 
     res = write(fdo, buffer, nread); 
     if (res < 0) ERR("write"); 
    } /* while */ 
    if (res < 0) ERR("read"); 
} /* copy */ 

int main() 
{ 
    int pip[2]; 
    int res; 

    res = pipe(pip); 
    if (res < 0) ERR("pipe"); 

    char *filename; 

    switch (res = fork()) { 
    case -1: /* error */ 
     ERR("fork"); 

    case 0: /* child */ 
     filename = "file1"; 
     res = open(filename, O_RDONLY); 
     if (res < 0) ERR("open \"%s\"", filename); 
     close(pip[0]); 
     copy(res, pip[1]); 
     break; 

    default: /* parent, we got the child's pid in res */ 
     filename = "file2"; 
     res = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0666); 
     if (res < 0) ERR("open \"%s\"", filename); 
     close(pip[1]); 
     copy(pip[0], res); 
     int status; 
     res = wait(&status); /* wait for the child to finish */ 
     if (res < 0) ERR("wait"); 
     fprintf(stderr, 
       FMT("The child %d finished with exit code %d\n"), 
       res, 
       status); 
     break; 
    } /* switch */ 
    exit(0); 
} /* main */ 
관련 문제