/*fork1.c*/
#include
int main()
{
int p1, p2, i;
while ((p1 = fork()) == -1)
; /*创建进程p1*/
if(p1 == 0)
{
for (i = 0; i < 8; i++)
{
printf("daughter %d \n", i);
}
}
else
{
while ((p2 = fork()) == -1); /*创建进程p2*/
if (p2 == 0)
{
for (i = 0; i < 8; i++)
{
printf("son %d \n", i);
}
}
else
{
for (i = 0; i < 8; i++)
{
printf("parent %d \n", i);
}
}
}
}
运行结果
执行结果中打印出来的语句没有交叉,好像三个进程是顺序执行,而不是并发执行。
5. 进程创建2,增加sleep 语句使得打印结果有交叉。
/*fork2.c*/
#include
int main()
{
int p1, p2, i;
while ((p1 = fork()) == -1); /*创建进程p1*/
if(p1 == 0)
{
for (i = 0; i < 8; i++)
{
printf("daughter %d \n", i);
sleep(4);
}
}
else
{
while ((p2 = fork()) == -1); /*创建进程p2*/
if (p2 == 0)
{
for (i = 0; i < 8; i++)
{
printf("son %d \n", i);
sleep(4);
}
}
else
{
for (i = 0; i < 8; i++)
{
printf("parent %d \n", i);
sleep(4);
}
}
}
return 0;
}
程序运行结果
6. 增加代码,判断以下程序的执行产生多少个进程
#include
int main()
{
fork();
fork();
fork();
return 0;
}
试着使用两个系统调用
(1)获得当前的进程号getpid();
(2)获得父进程的进程号getppid();
(3)等待子进程结束wait();
(4)在创建多个进程后,执行的过程中可能会产生孤儿进程,即父进程先于子进程之前结
束。在这种情况下,系统将子进程的父进程设定为init 进程(进程号为1)。
(5)要解决孤儿进程问题,可以在父进程中增加wait 系统调用。
参考程序:
/*count2.c*/
#include
#include
int main()
{
fork();
fork();
fork();
printf("Hello, world! from process id %d, it's parent id %d\n", getpid(), getppid());
wait(0);
wait(0);
wait(0);
return 0;
}
执行结果如下图所示。
可以画出这8 个进程的进程关系树。
10
root@duanwh-virtual-machine:~# ./count2.out
Hello, world! from process id 17361, it's parent id 16421
Hello, world! from process id 17362, it's parent id 17361
Hello, world! from process id 17363, it's parent id 17361
Hello, world! from process id 17364, it's parent id 17361
root@duanwh-virtual-machine:~# Hello, world! from process id 17365, it's parent id
17362
Hello, world! from process id 17366, it's parent id 17362
Hello, world! from process id 17367, it's parent id 17363
Hello, world! from process id 17368, it's parent id 17365
进程号父进程号
17361 16421
17362 17361
17363 17361
17364 17361
17365 17362
17366 17362
17367 17363
17368 17365
16421 是bash 的进程号,16421 创建了第一个进程17361;17361 创建了17362,17363,
17364 三个进程;17362 进程创建了17365 和17366 两个进程;17363 创建了17367 一个
进程;17365 创建了17368 一个进程。
#include
int main()
{
int pid;
pid = fork();
if (pid == 0)
{
printf("child pid = %d, ppid = %d\n", getpid(), getppid());
sleep(2);
printf("child pid = %d, ppid = %d\n", getpid(), getppid());
}
else
{
printf("parent pid = %d, ppid = %d\n", getpid(), getppid());
}
return 0;
}
执行结果
执行结果分析:
(1)执行了两次,第一次是parent 先打印,第二次是child 进程先打印。两次的执行结果
不同,这个就体现了操作系统基本特性中的异步性。
(2)分析第一次执行结果。(父进程的进程号是23331,子进程的进程号是23332)
1)父进程先打印,打印结束后,父进程结束。
2)子进程打印第一次的时候已经是孤儿进程了。子进程的两次打印结果是一样的。
(3)分析第二次执行结果。(父进程的进程号是23334,子进程的进程号是23335)
1)子进程先打印第一次,此时父进程没有结束,子进程不是孤儿进程,打印出了子进
12
程的进程号和父进程的进程号。子进程执行sleep 语句进入阻塞状态。
2)父进程执行,打印自身的进程号和自己的父进程的进程号。父进程结束。
3)子进程等待时间到了后继续执行,打印第二句话,此时父进程已经结束,子进程变
成了孤儿进程。
10. 以下的程序执行会出现僵尸进程。
/*daemon.c*/
#include
int main()
{
int pid;
pid = fork();
if (pid > 0)
{
while(1)
{
//nothing
}
}
else
{
printf("child pid = %d, ppid = %d\n", getpid(), getppid());
}
return 0;
}
另打开一个终端,使用ps -al|grep daemo 可以看到子进程是僵尸状态。
执行结果分析:
(1)涉及到两个进程,父进程的进程号23473,子进程的进程号23474。