实验:
1 #include <unistd.h>
2 #include <sys/types.h>
3
4 int
5 main (void)
6 {
7 pid_t pid;
8
9 printf("fork!/n");
//输出"fork!"这一行一定是最先输出的(这是一人在未做老爸之前,在屏幕上涂鸦的)
10 pid=fork();
//创建子进程(生了一个小孩了) ,并且将返回值赋给pid(时刻注意:家里多了一个人了,
//小孩的pid赋0,老爸的pid为子进程的ID)
11 if (pid < 0)
12 printf("error in fork!/n");
13 else if (pid == 0)
//这是一个判断语句,子进程,父进程都会执行这一句
//pid为0的进程会执行下面的语句(知道是哪个进程的pid为0了吧?
//不错,这是儿子在屏幕上写的.
//老爸的pid是子进程的ID,因为子进程ID不会为0,因此老爸pid不可能为0,自然老爸不会写这一行)
14 printf("i am the child process, my process id is %d/n",getpid());
15 else
//判断语句,pid不为0的进程会输出这一句(嗯,老爸的会在屏幕上写上这么一句,
//儿子的pid为0,因此儿子不会写这一行)
16 printf("i am the parent process, my process id is %d/n",getpid());
17 }
验证1:
交互式运行(标准输出为行缓冲:遇到/n就冲洗其数据)
[root@mylinux ~]# ./a.out
fork!
//不错这时只有一个人,他最先输出这一行
i am the child process, my process id is 27991
//fork后,子进程先输出了这一行,因为一般来说子进程的优先级高一点(老爸让着它呢)
i am the parent process, my process id is 27990
//老爸接着写了这一行
验证2:
非交互式运行(标准输出为全缓冲:缓冲区满后冲洗其数据)
[root@mylinux ~]# ./a.out > 1.out
[root@mylinux ~]# cat 1.out
fork!
//同上,最先输出的,永远是这一行
i am the child process, my process id is 28002
//依然是子进程先输出了这一行
fork!
//这是哪多来的?原来这是老爸printf写东西时,残留在缓冲区中的东东,因为缓冲未满,数据没有被冲洗干净,
//fork后,儿子从老爸那获得的,现在一起被子进程写了出来.
//其实printf语句只执行了一句,但是因为缓冲有残留数据,因此才会一起被输出,这样就输出了两行
//然而为什么在交互式运行时却没有这样的东东,原来是换行符/n帮着冲洗数据,
//由于缓冲区被清空,fork后,老爸并没有遗留给儿子什么东东.儿子自然只输出了一行
i am the parent process, my process id is 28001
//这是老爸最后写的
***************************************************************************************************
[root@mylinux ~]# vi temp2.c
1 #include <unistd.h>
2 #include <sys/types.h>
3
4 int
5 main (void)
6 {
7 pid_t pid;
8
9 printf("fork!"); //这里没有了/n了
10 pid=fork();
11 if (pid < 0)
12 printf("error in fork!/n");
13 else if (pid == 0)
14 printf("i am the child process, my process id is %d/n",getpid());
15 else
16 printf("i am the parent process, my process id is %d/n",getpid());
17 }
验证3:
交互式运行
[root@mylinux ~]# ./a.out
fork!i am the child process, my process id is 28696
//最先输出的依然是"fork!"然后是子进程的输出
fork!i am the parent process, my process id is 28695
//父进程的printf是行缓冲,因为没有/n的冲洗,缓冲中有"fork"的残留,
//frok后子进程从父进程获得的"fork!"并输出
//再说一遍printf语句只执行了一次,但是因为缓冲有残留才会多输出这一部分
//最后才是父进程输出
验证4:
非交互式运行
[root@mylinux ~]# ./a.out > 2.c
[root@mylinux ~]# cat 2.c
fork!i am the child process, my process id is 28698
//最先输出的依然是"fork!"然后是子进程的输出
fork!i am the parent process, my process id is 28697
//父进程printf是全缓冲,它只有在缓冲满了时才会冲洗,因此父进程没有被冲洗"fork",
//子进程会从父进程获得的"fork!"并输出,最后才是父进程输出
[root@mylinux ~]#
总结:
一般来说,因为子进程的优先级别高一点(但并不一定)
因此其执行顺序:未做父进程的进程(从main到fork),子进程(从fork到子进程结束),父进程(也是从fork到父进程结束)
数据复制:
子进程复制父进程的数据段包括缓冲区的数据,但是只是逻辑上的复制,物理上数据的地址是一致的,只有当子进程做出修改以后才真正复制父进程的部分数据,如果其他的数据是一致的,不会做真正的复制;
代码共享:
父子进程共享代码段