View Code
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #define PSIZE 211 12 int main(){13 int fd[2];14 int flag = 1;15 //16 if((flag = pipe(fd)) == -1){17 printf("error in create pipe.");18 exit(1);19 }else if(flag == 0){20 // printf("success in create pipe.");21 }22 23 pid_t pid_1,pid_2;24 char outpipe[50];25 // ******************问题所在********************//26 if(((pid_1 = fork()) == -1)||((pid_2 = fork()) == -1)){27 // ******************问题所在********************//28 printf("error in fork()!");29 }30 else if(pid_1 == 0){31 printf("\n ...................%d %d...................\n",pid_1,pid_2);32 printf("i am a child 1, my pid is %d ,my fatherpid is %d.\n",getpid(),getppid());33 lockf(fd[1],1,0);// 对管道的写入端口jia锁。34 strcpy(outpipe,"Child process 1 is sending message!\n");35 printf("i am a child, i am writing %s \n",outpipe);36 write(fd[1],outpipe,sizeof(outpipe));37 sleep(5);38 lockf(fd[1],0,0);// 对管道的写入端口解锁。39 //getchar();//must write40 exit(0);41 }else if(pid_2 == 0){42 printf("\n ...................%d %d...................\n",pid_1,pid_2);43 44 printf("i am a child 2, my pid is %d ,my fatherpid is %d..\n",getpid(),getppid());45 lockf(fd[1],1,0);// 对管道的写入端口jia锁。46 strcpy(outpipe,"Child process 2 is sending message!");47 printf("i am a child, i am writing %s \n",outpipe);48 write(fd[1],outpipe,sizeof(outpipe));49 sleep(5);50 lockf(fd[1],0,0);// 对管道的写入端口解锁。51 //getchar();//must write52 exit(0);53 }else if(pid_1 > 0&&pid_2>0){54 printf("i am father, my pid is %d, my sonpid is %d and %d.\n",getpid(),pid_1,pid_2);55 int i = 0;56 pid_t pid;57 while(i < PSIZE){58 if((pid = wait(0)) < 0){59 printf("error in waitepid.\n");60 exit(1);61 }else{62 read(fd[0],outpipe,sizeof(outpipe));63 printf("father process read from pipe : %s son pid is %d.\n",outpipe,pid);64 }65 i++;66 }67 //getchar();//must write, if not ,the son process will be an orphen process. 相当于停了一下68 exit(0);69 }70 }
错误在于父进程同时fork()生成两个子进程。
子进程有可能在连续fork过程中生成自己的子进程,是否生成与子进程执行的顺序相关。
简要说明:
执行顺序(应该是运行结果更恰当)
父进程:(pid :2000)
fork()(子进程pid :2001)||fork()(子进程pid :2002)
子进程2:(pid :2002)
fork()(子进程pid : 2001)||fork()(子进程pid : 0)
子进程1:(pid :2001)
fork()(子进程pid : 0 )||fork()(子进程pid : 2003)
子进程至少保证了与所属父进程在调用fork()的位置处,fork()返回值为 0.
但是子进程继续fork(),返回值就与各进程的执行顺序相关了。
具体,比如 子进程2:pid 2001,我认为是由于父进程刚第一次fork,子进程2就fork了,那返回值为什么不是0呢?
这个问题我也不知到,欢迎大家指正。应该跟编译器有关。
最后结论:
父进程可以fork多个子进程,但是得一个一个fork,必须使得每fork一次后都需要有控制语句将其父子进程执行的程序段完全隔离开。避免使用 fork()||fork()连续fork子进程。
修改后:
View Code
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #define PSIZE 211 12 int main(){13 int fd[2];14 int flag = 1;15 if((flag = pipe(fd)) == -1){ //创建管道16 printf("error in create pipe.");17 exit(1);18 }else if(flag == 0){19 // printf("success in create pipe.");20 }21 pid_t pid_1,pid_2;22 char outpipe[50];23 if((pid_1 = fork()) == -1){ //创建子进程24 printf("error in fork()!");25 }else if(pid_1 == 0){ //子进程执行代码段26 printf("i am child 1, my pid is %d ,my fatherpid is %d.\n",getpid(),getppid());27 lockf(fd[1],1,0);// 对管道的写入端口jia锁。28 strcpy(outpipe,"Child process 1 is sending message!\n");29 printf("i am writing : %s \n",outpipe);30 write(fd[1],outpipe,sizeof(outpipe));31 sleep(5);// 让自己睡眠,好让父进程读出pipe内的数据。32 lockf(fd[1],0,0);// 对管道的写入端口解锁。33 //getchar();//must write34 exit(0);35 }else if(pid_1 > 0){ //父进程执行代码段36 if((pid_2 = fork()) == -1){37 printf("error in fork()!");38 }else if(pid_2 == 0){39 printf("i am child 2, my pid is %d ,my fatherpid is %d..\n",getpid(),getppid());40 lockf(fd[1],1,0);// 对管道的写入端口jia锁。41 strcpy(outpipe,"Child process 2 is sending message!");42 printf("i am writing : %s \n",outpipe);43 write(fd[1],outpipe,sizeof(outpipe));44 sleep(5);45 lockf(fd[1],0,0);// 对管道的写入端口解锁。46 //getchar();//must write47 exit(0);48 }49 printf("i am father, my pid is %d, my son pid is %d and %d.\n",getpid(),pid_1,pid_2);50 int i = 0;51 pid_t pid;52 while(i < PSIZE){53 if((pid = wait(0)) < 0){ //等待子进程结束后返回,返回值为子进程pid54 printf("error in waitepid.\n");55 exit(1);56 }else{57 read(fd[0],outpipe,sizeof(outpipe));58 printf("father process read from pipe : %s from son pid: %d.\n",outpipe,pid);59 }60 i++;61 }62 //getchar();//must write, if not ,the son process will be an orphen process. 相当于停了一下63 exit(0);64 }65 }
关键在于子进程2,是如何执行父子共享代码段的。
修正:
wait函数,父进程需等待子进程结束后返回,才可继续执行。
因此,code中 子进程1,2的程序段中的sleep函数的作用:保证子进程将数据全部写入管道。
而非等待以保证父进程从管道中读出数据。