繁体   English   中英

Unix C管道问题

[英]Unix C pipe Question

我试图了解管道的用法。

父进程将进行管道传输,如果是父进程,子进程将继承管道。 那么现在我们与子进程有直接联系,他们可以沟通吗?

当我们开始关闭管道并重定向管道时,我迷路了。 有没有人对关闭管道和重定向管道有一个很好的解释?

先感谢您。

这是交易。

  1. 管道是一种软件抽象,它有两个端点,每个端点都是一个fd。 无论你在一端写什么(写fd),你都可以读到另一端(读fd)。
  2. 使用管道的技巧是使用管道的读取fd切换某个进程的stdin。 现在,你可以写入管道的写入fd,当另一个进程读取他认为是他的stdin时,他实际上读取了管道的读取fd(并获取了你的数据)。
  3. 对于双向通信,您可以获取另一个管道,并使用管道的写入fd切换进程的标准输出。 现在,无论进程写入其stdout,您都可以读取管道的读取fd。

这是它的样子:

P1=[WR FD]===========[RD FD]=[STDIN]=P2
P1=[RD FD]===========[WR FD]=[STDOUT]=P2

P1 and P2 are processes. And "===" depict the pipes.

您的问题专门针对关闭和重定向。 当你执行我之前提到的开关时,它就会发挥作用。 假设您已通过使用pipe()系统调用获取了管道。

int fd[2];
pipe(fd);

现在您创建一个子进程,并在该进程中执行切换,如下所示:

if (!fork()) // 0 return value indicates that you are in the child process
{
    dup2(fd[0], 0); // dup2 first closes 0 in the child process, then duplicates
                    // fd[0] as 0; keep in mind that 0 is stdin and fd[0] is the
                    // read end of the pipe

    exec(something); // start the new process, which when it reads stdin, will be
                     // reading the pipe instead
}

管道

简单的例子

 ls -l | less 

在此示例中,ls是Unix目录列表器,less是具有搜索功能的交互式文本寻呼机。 管道允许用户向上和向下滚动可能不适合屏幕的目录列表。

以编程方式创建管道

可以在程序控制下创建管道。 Unix pipe()系统调用要求操作系统构造一个新的匿名管道对象。 这导致进程中有两个新的打开文件描述符:管道的只读端和只写端。 管道端部看起来是正常的匿名文件描述符,除了它们没有能力搜索。

为了避免死锁并利用并行性,具有一个或多个新管道的Unix进程通常会调用fork()来创建新进程。 然后,每个过程将关闭在生成或使用任何数据之前不会使用的管道的末端。

替代文字

您使用dup系列调用将新文件描述符更改为前三个系统调用之一。

int new_stdout = open("filename", O_WRONLY);
/* ... error check ... */
if (!fork()) {
    /* in child */
    dup2(new_stdout, 1);
    execve("program", argv, envp);

这使得“filename”将其标准写入“filename”。

子进程继承父进程的开放描述符。 默认的是stdin,stdout,stderr。 他们没有为孩子提供直接与父母沟通的方法,因为他们实际上是去了控制台。 因此,通常关闭或重定向这些,这样就不会污染父控制台的I / O.

但是如果你打开了一对管道,你可以使用它们继承的描述符来在两个进程之间进行通信。 每个方向使用一个描述符。

我们经常使用烟斗。 正如Amardeep所说,子进程继承了父进程的描述符,包括管道。

以下是2个命令的示例。 我不确定我的n命令算法:-)

void do__pipe(char** cmd1, char** cmd2)
{
    int fd[2]; /* fd[0] for reading fd[1] for writting */

    if (pipe(fd) == -1)
    {
       perror("pipe");
    }

    switch (fork())
    {
       case -1:
      perror("fork"); exit (1);
       case 0:
      close (fd[0]);
      dup2 (fd[1], STDOUT_FILENO);
      close (fd[1]);
      execvp (cmd1[0], cmd1);
      exit (1);
    }

    dup2(STDIN_FILENO, STDIN_FILENO);

    switch (fork())
    {
       case -1:
      perror("fork (2)"); exit (1);
       case 0:
      close (fd[1]);
      dup2 (fd[0], STDIN_FILENO);
      close (fd[0]);
      execvp (cmd2[0], cmd2);
      exit (1);
    }u

    wait((int*)NULL);
}

这个代码取自我必须为我的学习写的一个小shell,所以char ** cmd1就像[“cat”,“/ etc / passwd”],而cmd2可能是[“wc”,“ - l “]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM