【问题标题】:minor issue with fork() and pipe()fork() 和 pipe() 的小问题
【发布时间】:2009-12-24 15:09:36
【问题描述】:

我正在编写一个小程序来实现管道,就像它们在 shell 中工作一样。 即:

ls -hal | sort | grep p | wc

它工作正常,有一个小问题,当 CMD_NO=n 时,比较 i 大于 CMD_NO 不起作用,但 i!=(CMD_NO-1) 可以。我试图弄清楚为什么在这种特殊情况下(该行在代码中被称为 TROUBLED LINE)这些语句是不等价的。非常感谢。

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

#define READ_END 0
#define WRITE_END 1
#define CMDS_NO 5

int main (int argc, char **argv) 
{
    pid_t pid;
    int new_fds[2];
    int old_fds[2];

    char *array[CMDS_NO];
    char *param[CMDS_NO];

    array[0]="ls";
    array[1]="sort";
    array[2]="grep";
    array[3]="grep";
    array[4]="wc";

    param[0]="-hal";
    param[1]=NULL;
    param[2]="p";
    param[3]="out";
    param[4]=NULL;


    for (int i=0; i<CMDS_NO; i++) {

        if (i<CMDS_NO) //if there is a next command 
           pipe(new_fds);

        pid=fork();

        if (pid==0) { //if child
            if (i!=0) { //if there is ap revoius commmand
                dup2(old_fds[0], 0);
                close(old_fds[0]);
                close(old_fds[1]);
            }

            if (i!=(CMDS_NO-1)) { //TROUBLED LINE i<CMDS_NO does not work,  
                                  //if there is a next command
                close(new_fds[0]);
                dup2(new_fds[1],1);
                close(new_fds[1]);
            }
            execlp(array[i], array[i], param[i], NULL);

            } else {
                if (i!=0) { //if there is a previous command
                    close(old_fds[0]);
                    close(old_fds[1]);
                }

                if (i<CMDS_NO) { //if there is a next command
                    old_fds[0] = new_fds[0];
                    old_fds[1] = new_fds[1];
                }
            }
     }
     if (CMDS_NO>1) {
        close(old_fds[0]);
        close(old_fds[1]);
     }     

     while (1) { //wait for child processes to end
         wait(NULL);
         if(errno== ECHILD) {
             printf("all children ended\n"); 
             break;
         }
     }

return 0;
}

【问题讨论】:

  • i0CMDS_NO-1 以及介于两者之间的值时,请多考虑您希望发生的事情。请注意i &lt; CMDS_NO,只要您在循环中。

标签: c unix posix pipe fork


【解决方案1】:

条件i&lt;CMDS_NO 将始终为真,因为i 从0 运行到CMDS_NO-1。我认为您的意思是将您的条件写为i&lt;CMDS_NO-1。当然,i!=CMDS_NO-1 同样有效。

请注意,这会影响您拥有if (i&lt;CMDS_NO) 的其他几个地方;这些也应该是if (i&lt;CMDS_NO-1)

【讨论】:

    【解决方案2】:

    这很正常。

    for (int i=0; i&lt;CMDS_NO; i++) {

    这意味着“只要i 小于CMDS_NO 就循环”。只要i == CMDS_NO 循环就会停止;因此,在循环内部,i 将达到的最高值是 CMDS_NO - 1

    PS:CMDS_NO 是一个很糟糕的变量名,比如叫它MAX_COMMANDS

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-07
      • 2012-09-12
      相关资源
      最近更新 更多