我试图理解管道是如何工作的,当我在教科书中阅读这段代码时,这是相当混乱的。在行
dup(fd2[0]); close(fd2[0]);
为什么我们要复制fd2[0]
,然后在我们复制后立即关闭它?
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
struct timespec ts1, ts2;
pid_t newpid;
int fd1[2], fd2[2];
char m0[] = "\nabout to fork....\n";
char m1[] = "message from parent to child\n";
char m2[] = "message from child to parent\n";
char m3[] = "\ndone....\n";
char rbuf1[256];
char rbuf2[256];
int cn1, cn2;
ts1.tv_sec=(time_t)1;
ts1.tv_nsec=(long)1;
ts2.tv_sec=(time_t)1;
ts2.tv_nsec=(long)1;
if ((pipe(fd1)==-1)) printf("error\n");
if ((pipe(fd2)==-1)) printf("error\n");
printf("fd1 %d %d fd2 %d %d\n", fd1[0], fd1[1], fd2[0], fd2[1]);
if ((newpid=fork()) ==-1) {
printf("failed to fork\n\n");
return 0;
}
if (newpid > 0) { // parent ***************
close(fd1[1]); close(fd2[0]); // closing 4 and 5
dup(fd2[1]); close(fd2[1]); // taking 4 in place of 6
write(4, m1, sizeof(m1)); // parent_to_child messg
usleep(10000);
cn1=read(3, rbuf1, 256);
write(1, rbuf1, cn1);
} else { // child ***************
close(fd1[0]); close(fd2[1]); // closing 3 and 6
dup(fd2[0]); close(fd2[0]); // taking 3 in place of 5
write(4, m2, sizeof(m2)); // child_to_parent messg
usleep(10000);
cn2=read(3, rbuf2, 256);
write(1, rbuf2, cn2);
}
write(2, m3, sizeof(m3));
return 0;
}
答案 0 :(得分:1)
但是,您没有通过dup()
的{{3}}
int dup(int oldfd);
和
dup() uses the lowest-numbered unused descriptor for the new descriptor.
这清楚地说明,dup()
将为oldfd
返回一个新的文件描述符。您需要指定dup()
的返回值才能获得新的fd
。获得新的fd
后,您可以关闭旧的fd
并使用新返回的描述符来访问该文件。
常用的方法是关闭一个众所周知的文件描述符,然后调用dup()
,将最近关闭的fd
指定为新的fd
。 [示例:STDIN_FILENO
]
答案 1 :(得分:0)
通常的顺序是在close
调用之前进行另一次dup
调用,或者分配dup
的结果并使用它。
第一个变体是最常见的,例如将管道读取结束用作您可以执行的新STDIN_FILENO
close(STDIN_FILENO); // Close the current standard input descriptor
dup(pipefds[0]); // Duplicate the pipe read-end, which will become our new standard input
close(pipefds[0); // Close the old pipe descriptor, to save descriptor resources
这将有效,因为dup
将选择最低可用描述符,该描述符在第一个close
调用后将为STDIN_FILENNO
(描述符0
)。
并且dup
完全正如它所说的那样,重复描述符,因此在调用dup
之后,您将有两个描述符引用相同的“文件”,并且可以自由地关闭其中一个。
我建议你阅读the dup(2)
manual page。