解释管道和叉子输出

问题描述

我第一次在 Linux 中处理管道和叉子,如果有人能向我解释以下程序的输出,我会很高兴:(哪行代码导致输出,是通过子进程还是父进程)

int main(){                              //1
    int ipc[2];                          //2
    pipe(ipc);                           //3
    write(2,"start\n",6);              //4
    if (fork()) {                        //5
        sleep(1);                        //6
        char c;                          //7
        do {                             //8
            read(ipc[0],&c,1);         //9
            write(1,1);             //10
        } while (c != '\n');             //11
        write(1,"if\n",3);             //12
        waitpid(-1,NULL,0);            //13
    }                                    //14
    else {                               //15
        write(ipc[1],"else1\n",6);     //16
        write(1,"else2\n",6);          //17
    }                                    //18
    write(1,"done\n",5);               //19
    return 0;                            //20
}                                        //21

程序的输出为:

start
else2
done
else1
if
done

解决方法

fork() 创建一个子进程,执行与原始进程相同的代码。如果成功,您的两个进程之间的唯一区别是:

  • 在原始进程中,fork 将返回一个非零值(即子进程的 id)
  • 在子进程中,fork 将返回零值

所以,换句话说:当你写:

if (fork()) {
    // Block "If"
} else {
    // Block "Else"
}

原进程执行“block if”,子进程执行“block else”。

pipe 返回两个文件描述符,一个可用于写入管道,另一个可用于从管道读取。所以当你写:

int ipc[2];
pipe(ipc);

您在ipc[1]中写的任何内容都可以在您阅读ipc[0]时阅读。 换句话说,这是在 fork 创建的两个进程之间进行通信的好方法。

在您的示例中,子进程(在“else”中)将数据写入 ipc[1],原始进程(在“if”中)读取它。

您创建了一个在管道中写入数据的子进程,而您的原始进程从管道中读取数据。