C 从管道读取的子进程失败,似乎出现了故障
我有以下带有输出的代码:C 从管道读取的子进程失败,似乎出现了故障,c,linux,process,pipe,fork,C,Linux,Process,Pipe,Fork,我有以下带有输出的代码: #include <stdio.h> #include <errno.h> #include <unistd.h> #include <string.h> #include <wait.h> #define PIPE_STDIN 0 #define PIPE_STDOUT 1 #define msg "hello world" int main() { int fd_pipe[2]; in
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#define PIPE_STDIN 0
#define PIPE_STDOUT 1
#define msg "hello world"
int main()
{
int fd_pipe[2];
int ret = fork();
if (ret < 0)
{
printf("Failed to fork\n");
return -1;
}
else if (ret == 0)
{
printf("Parent with PID %d\n", getpid()); fflush(stdout);
//sleep(3);
ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg)); fflush(stdout);
printf("Parent wrote string %d\n", ret); fflush(stdout);
wait( NULL );
printf("Parent done wait\n"); fflush(stdout);
}
else
{
char buf[80];
printf("Child with PID %d whose parent PID %d\n", getpid(), ret); fflush(stdout);
ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
printf("Child read %s %d\n", buf, ret); fflush(stdout);
}
}
从输出中,为什么孩子无法从管道中读取(返回-1),然后在稍后打印消息“hello world”?请解释给出上述日志的执行顺序
fork
之前调用pipe
以初始化文件描述符fork()==0
表示子进程code
可以工作:
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#define PIPE_STDIN 0
#define PIPE_STDOUT 1
#define msg "hello world"
int main()
{
int fd_pipe[2];
int ret;
if (pipe(fd_pipe) == -1) {
perror("pipe");
return -1;
}
ret = fork();
if (ret < 0)
{
printf("Failed to fork\n");
return -1;
}
else if (ret != 0)
{
printf("Parent with PID %d\n", getpid()); fflush(stdout);
//sleep(3);
ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg)); fflush(stdout);
printf("Parent wrote string %d\n", ret); fflush(stdout);
wait( NULL );
printf("Parent done wait\n"); fflush(stdout);
}
else
{
char buf[80];
printf("Child with PID %d whose parent PID %d\n", getpid(), getppid()); fflush(stdout);
ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
printf("Child read %s %d\n", buf, ret); fflush(stdout);
}
}
#包括
#包括
#包括
#包括
#包括
#定义管道标准0
#定义管道标准件1
#定义消息“hello world”
int main()
{
int fd_管道[2];
int ret;
如果(管道(fd_管道)=-1){
佩罗(“管道”);
返回-1;
}
ret=fork();
如果(ret<0)
{
printf(“未能分叉\n”);
返回-1;
}
否则如果(ret!=0)
{
printf(“PID为%d的父项”,getpid());fflush(stdout);
//睡眠(3);
ret=写入(fd_管道[pipe_STDOUT],msg,sizeof(msg));fflush(STDOUT);
printf(“父写入字符串%d\n”,ret);fflush(stdout);
等待(空);
printf(“父完成等待”);fflush(stdout);
}
其他的
{
char-buf[80];
printf(“PID为%d且其父PID为%d的子项,\n”、getpid()、getppid());fflush(stdout);
ret=读取(fd_管道[pipe_STDIN],buf,sizeof(msg));
printf(“子读取%s%d\n”,buf,ret);fflush(stdout);
}
}
fork
之前调用pipe
以初始化文件描述符fork()==0
表示子进程code
可以工作:
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#define PIPE_STDIN 0
#define PIPE_STDOUT 1
#define msg "hello world"
int main()
{
int fd_pipe[2];
int ret;
if (pipe(fd_pipe) == -1) {
perror("pipe");
return -1;
}
ret = fork();
if (ret < 0)
{
printf("Failed to fork\n");
return -1;
}
else if (ret != 0)
{
printf("Parent with PID %d\n", getpid()); fflush(stdout);
//sleep(3);
ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg)); fflush(stdout);
printf("Parent wrote string %d\n", ret); fflush(stdout);
wait( NULL );
printf("Parent done wait\n"); fflush(stdout);
}
else
{
char buf[80];
printf("Child with PID %d whose parent PID %d\n", getpid(), getppid()); fflush(stdout);
ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
printf("Child read %s %d\n", buf, ret); fflush(stdout);
}
}
#包括
#包括
#包括
#包括
#包括
#定义管道标准0
#定义管道标准件1
#定义消息“hello world”
int main()
{
int fd_管道[2];
int ret;
如果(管道(fd_管道)=-1){
佩罗(“管道”);
返回-1;
}
ret=fork();
如果(ret<0)
{
printf(“未能分叉\n”);
返回-1;
}
否则如果(ret!=0)
{
printf(“PID为%d的父项”,getpid());fflush(stdout);
//睡眠(3);
ret=写入(fd_管道[pipe_STDOUT],msg,sizeof(msg));fflush(STDOUT);
printf(“父写入字符串%d\n”,ret);fflush(stdout);
等待(空);
printf(“父完成等待”);fflush(stdout);
}
其他的
{
char-buf[80];
printf(“PID为%d且其父PID为%d的子项,\n”、getpid()、getppid());fflush(stdout);
ret=读取(fd_管道[pipe_STDIN],buf,sizeof(msg));
printf(“子读取%s%d\n”,buf,ret);fflush(stdout);
}
}
您没有显示调用管道()
-您使用的是随机文件描述符。调用write()
之后的fflush(stdout)
基本上是不可操作的。常识规定fork()
的结果是子进程的pid号,因为父进程pid总是可以通过getppid()获得
system调用,但在UNIX中无法获取子系统的pid,只能直接从fork()
syscall获取。@JonathanLeffler,write()
正在fflush()
实现中。它对缓冲区一无所知(它不是stdio
的一部分),因此如果只执行write(2)
syscall,缓冲区中可能有数据。如果他使用了fwrite(3)
,则无需说明。@LuisColorado-是的,但是write()
之前的调用也是fflush(stdout)
,因此后面的调用与我所说的无关。您没有显示调用pipe()
-您使用的是随机文件描述符。fflush(stdout)
在write()
调用之后,调用基本上是不可操作的。常识规定fork()
的结果是子进程的pid号,因为父进程pid总是可以通过getppid()
系统调用获得,但在UNIX中无法获得子进程的pid,只能直接从fork()获取
syscall.@JonathanLeffler,write()
正在fflush()
实现中。它对缓冲区一无所知(它不是stdio
的一部分),因此如果只执行write(2)
syscall,缓冲区中可能有数据。如果他使用了fwrite(3)
,则无需说明。@LuisColorado-是的,但是write()
之前的调用也是fflush(stdout)
,因此后面的调用与我所说的无关。