日期:2014-05-16  浏览次数:20704 次

pipe使用的十分奇怪,怎么会受printf语句影响
问题在于父进程的那段代码,有无printf语句,输出结果不同!!加上printf正常,去掉出错
十分的不解???


#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<sched.h>

void proc1(int sig)
{
}
void proc2(int sig)
{
}

int main(void)
{
int pipe_fd1[2] = { 0 }, pipe_fd2[2] = { 0 }; //声明管道
char rbuf1[128] = "", rbuf2[128] = "", wbuf[128] = ""; //缓冲区
pid_t pid1, pid2;

if(pipe(pipe_fd1) < 0) //建立管道
{
printf("pipe1 create error");
exit(-1);
}

//fork函数被调用一次,却能返回两次
//在语句fork之前,只有一个进程在执行这段代码
pid1 = fork();//产生第一个子进程
//fork之后,变为两个进程,并且代码部分完全相同,新进程入口在fock()函数调用后的下一条语句


//子进程和父进程都执行fork函数调用之后的代码,子进程是父进程的一份拷贝
if (pid1 < 0)
{
printf("Fork1 Error");
exit(-1);
}
else if (pid1 == 0) //在子进程中fork函数返回0
{
close(pipe_fd1[0]); //关闭读端,该线程只写数据

signal(SIGINT, proc1); //等待父线程的信号
pause();

sprintf(wbuf, "Child 1 is sending a message!");
write(pipe_fd1[1], wbuf, sizeof(wbuf)); //写端
close(pipe_fd1[1]); //写数据完毕,关闭写端
}
else //在父进程中fork函数返回子进程的pid
{
if (pipe(pipe_fd2) < 0) //建立管道
{
printf("pipe2 create error");
exit(-1);
}

pid2 = fork(); //产生第二个子进程

if (pid2 < 0)
{
printf("Fork2 Error");
exit(-1);
}
else if (pid2 == 0) //在子进程中fork函数返回0
{
close(pipe_fd2[0]); //关闭读端

signal(SIGINT, proc2); //等待父线程的信号
pause();

sprintf(wbuf, "Child 2 is sending a message!");
write(pipe_fd2[1], wbuf, sizeof(wbuf));
close(pipe_fd2[1]); //写数据完毕,关闭写端
}
else
{
//printf(" ");
close(pipe_fd1[1]); //关闭写端,只读取数据
kill(pid1, SIGINT); //告诉进程1可以写管道
read(pipe_fd1[0], rbuf1, sizeof(rbuf1));
close(pipe_fd1[0]); //关闭读端

close(pipe_fd2[1]); //关闭写端,只读取数据
kill(pid2, SIGINT); //告诉进程2可以写管道
read(pipe_fd2[0], rbuf2, sizeof(rbuf2));
close(pipe_fd2[0]); //关闭读端

wait(NULL); //等待所有子进程结束
printf("result:\n%s\n%s\n", rbuf1, rbuf2);
}
}

//代码段共享,但数据段和堆栈段却是相互独立的
return 0;
}


/*
 * 管道半双工,数据只能向一个方向流动,单独构成独立的文件系统,只存在于内存中
 * 一个进程向管道中写的内容被管道另一端的进程读出,写的内容每次都添加到管道缓冲区的末尾,并且每次都是从头部读取数据
 * 管道两端用描述子字fd[0](只能读),fd[1](只能写);read,write,close
 * 若管道写段不存在,则读端读出数据为零;最大buf在PIPE_BUF定义
 * 管道写端关闭后,写入的数据一直存在,直到读出为止
 * 只要管道缓冲区有空闲,写端就会一直写数据,满则阻塞,直到读端读出数据;
 * 写端依赖于读端
 */


------解决方案--------------------
父进程运行的太快了,
子进程还没跑到pause()的地方,甚至连signal()的地方都没到,父进程就给子进程送了SIGINT,
SIGINT的缺省动作是杀死进程,子进程很早就终止了,所以也就不会write pipe了,父进程就只能在read的地方干等着

父进程给子进程送SIGINT之前加了个printf,大概是这个函数是阻塞函数,会引发进程切换,所以子进程得到机会运行,赶在SIGINT送过来之前调了signal(),避免了被SIGINT误杀。