0

我试图理解管道是如何工作的,当我在教科书中阅读这段代码时,这相当令人困惑。在行

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;
}
4

2 回答 2

1

但是,您没有从手册页中向我们展示您的代码dup()

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]

于 2014-12-09T19:47:08.480 回答
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(descriptor 0)。

并且dup完全按照听起来的方式复制描述符,因此在调用dup您之后将有两个描述符引用同一个“文件”,并且可以自由关闭其中一个。

我建议您阅读手册dup(2)

于 2014-12-09T19:49:02.447 回答