【问题标题】:Better understanding of pipes更好地理解管道
【发布时间】:2015-12-31 08:01:23
【问题描述】:

在学习管道的时候,不小心写了如下代码

int main()
{
    pid_t pid;
    int status;
    int p1[2];

    pid = fork();
    pipe(p1);

    if(pid==0)
    {
        dup(p1[0], 0);
        close(p1[1]);
        execv(abs_addr_of_some_bin , argv);
    }
    else
    {
        dup(p1[1] , 1);
        close(p1[0]);
        write(p1[1] , some_rand_text , size_of_text);
        wait(&status);
    }
}

正在执行的二进制文件有一个read(0 , buf , size) 语句,从 STDIN 读取。

好吧,上面的代码显然是不正确的,因为我在pipe() 之前有fork()。因此,当我尝试在另一个二进制文件中输出buf 时,它会打印一些随机值,每次执行此文件时都会有所不同。 这可能是什么原因?

另外,如果我更正我的代码(即在fork() 之前调用pipe()),与管道工作相关的某些事情会让我感到困惑:

  1. 由于p1 数组对于两个进程(父进程和子进程)都有不同的内存地址,操作系统如何知道 p1[0] 的另一端(在子进程中)是 p1[1] (在父级中)?

  2. 在这个过程中会发生什么样的内存操作?

提前致谢!

【问题讨论】:

  • how does the OS know that the other end of p1[0] (in the child) is p1[1]:一个进程有一个结构,其中有打开的文件和管道的列表。当您执行fork 时,孩子会收到相同的管道。 fork 是一个系统函数,在 linux 内核中可用(它的名字是 __sys_fork)。
  • @Pierre - 是什么让你认为 fork() 只存在于 linux 中,或者使用“unix”标签的人对 linux 特别感兴趣
  • @Arlie Stephens:我从没说过。至少在所有 POSIX OS 中都有。并且对于信息,在 Windows 中没有/没有对fork 的内核系统调用。一些编译器添加了 fork 的实现。

标签: c unix pipe fork


【解决方案1】:

不要在分叉之后而是之前创建管道!如果您在之后创建它,那么您将创建两个不相关的管道......因为您需要为两个进程共享相同的管道,所以在分叉之前创建它。

您有随机值,因为您的管道没有连接,并且在您的execed 进程中没有真正测试reads。

关于地址。没有p1在父母和孩子的地址完全一样!但是这些地址位于不同的地址空间中。进程操作的地址总是与其给定的地址空间相关的。

fork 复制了父进程的地址空间,并为子进程构建了一个严格的副本。

【讨论】:

  • 对不起,但没有得到这一行:在你的execed 进程中没有真正测试reads。?
  • 你说你有垃圾,因为你的管道没有很好地连接,execed 命令可能错误地读入了管道......你没有给我们所有的代码;我们只能给出一些提示。
猜你喜欢
  • 2020-09-04
  • 2016-04-09
  • 2018-11-04
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多