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 */
'파이프 (핍)'은'포크()하기 전에해야한다;'. – mch
분기 후에 파이프를 만드는 것이 불가능합니까? –
'pipe' 함수를 사용하면 yes입니다. 또한'write'와'read'를 잘못 사용하고 있고, 두번째 매개 변수는 버퍼이며,'FILE'에 대한 포인터가 아닙니다. 'FILE * fp' 다음에'='를 잊어 버렸습니다. – mch