鉴于此代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
int fd[2], nbytes;
pid_t childpid;
char string[] = "Hello, world! I'm the son and this my message!\n";
char readbuffer[80];
pipe(fd); // piping fd[0] & fd[1]
if((childpid = fork()) == -1) // here we create a SON process
{
perror("fork");
exit(1);
}
if(childpid == 0) // child process
{
/* Child process closes up input side of pipe */
close(fd[0]); // closing the READ end from reading , after that the SON would write into fd[1]
/* Send "string" through the output side of pipe */
write(fd[1], string, (strlen(string)+1));
printf("Verification : Message was sent successfully by the SON!\n");
exit(0);
}
else // father process
{
/* Parent process closes up output side of pipe */
close(fd[1]);
/* Read in a string from the pipe */
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("I'm the father and I received that string: %s", readbuffer);
}
return(0);
}
输出结果为:
I'm the father and I received that string: Hello, world! I'm the son and this my message!
Verification : Message was sent successfully by the SON!
我正在试图理解管道,我很少有事情不清楚:
如果儿子在该行write(fd[1], string, (strlen(string)+1));
发送了他的消息,之后我们有printf
验证消息是否已发送,为什么我会得到验证(例如{{1}父亲收到儿子的消息之后 是不是假设首先来自儿子的验证,然后才是字符串?
如果父亲试图从管道中读取并且儿子想要写入管道,那么这里的某处隐藏(我认为)死锁,不是吗?为什么我没有陷入僵局?
谢谢
答案 0 :(得分:3)
你的第一个问题:
1. wasn't it suppose to be first the verification from the son and only then the string ?
答案:当您运行多个进程时,这些进程的指令执行顺序不确定。这取决于调度程序何时进行调度。因此,从程序的输出中,我们可以按如下方式告诉指令执行顺序:
CHILD-PROCESS:
写(fd [1],string,(strlen(string)+1));在此指令之后,此过程暂停
PARENT-PROCESS:
nbytes = read(fd [0],readbuffer,sizeof(readbuffer));
PARENT-PROCESS:
printf(“我是父亲,我收到了那个字符串:%s”,readbuffer);
CHILD-PROCESS:
printf(“验证:消息由SON成功发送!\ n”);
这个序列也可能不同以及其他时间。
你的问题:
2. Why am I not getting a deadlock ?
答案:在这种情况下,父进程只是阻塞等待管道上的某些输入。但孩子可以写,它不必等待。所以没有死锁的可能。
答案 1 :(得分:2)
1)来自子进程的消息之后的原因是因为写入管道可能会阻塞,直到缓冲区中有足够的空间(来自here):
如果进程尝试写入完整管道(请参阅 在下面),然后写入(2)块,直到从管道读取了足够的数据 允许写完成。
换句话说,子进程等待父进程在write()
的调用中读取消息。
2)如果子进程无法向管道写入任何内容,那么父进程将阻塞(它不会死锁)。
答案 2 :(得分:2)
由于I / O缓冲,无法保证输出将按照打印顺序显示。
答案 3 :(得分:1)
当孩子写入管道时,内核会将父级更改为运行状态。
似乎调度程序在父项打印文本之前将父项切换为运行(可能在子项从write
调用返回之前)。
所以行
printf("I'm the father and I received that string: %s", readbuffer);
在line:
之前执行printf("Verification : Message was sent successfully by the SON!\n");
您可以使用strace -f
命令验证这一点。
答案 4 :(得分:1)
if(childpid == 0) // child process
{
write(fd[1], string, (strlen(string)+1)); #C1
printf("Verification : Message was sent successfully by the SON!\n"); #C2
exit(0);
}
else // father process
{
/* Read in a string from the pipe */
nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); #F1
printf("I'm the father and I received that string: %s", readbuffer); F2
}
在上述情况下,我们无法确定是先发生 C1还是F1 。它取决于内核调度,不应该依赖。但是 C1&amp;如果管道处于bock模式,F1 是相关的。相关= 两者都必须发生,否则会出现死锁。以下情况会导致死锁。
如果孩子/父母退出,那么你会得到一个破管/ sig-pipe。