实验目的
(1)通过实验使学生了解Linux C程序的编译和运行;
(2)掌握fork函数的编程方法;
(3)热悉并发进程的程序的编写。
实验预备知识
(1)Linux文本编辑器vi和gedit;
(2)gcc编译器。
实验内容
1 父进程创建子进程 1)父进程显示“11111” 2)子进程显示“22222” 3)多次执行该程序观察结果。
2 父进程创建子进程 1)父进程显示“I am parent\n”5次,每次输出后使用sleep(1)延时1秒,然后再进入下次循环。 2)子进程显示“I am child\n”5次,每次输出后使用 sleep(1)延时1秒,然后再进入下次循环。
3.进程家族树:在原程序中连续使用4个fork(),然后输出 字母“A”。观察并分析输出结果。
实验步骤
1.先打开终端输入
1
| $ sudo apt-get install gcc
|
安装C、C++编译器gcc
2.编写代码,在代码所在文件夹下打开终端,运行
1 2
| $ gcc C语言源文件文件名 -o 输出文件名 $ ./输出文件名
|
编译运行C语言文件
代码
E2-3-1.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <unistd.h> #include <stdio.h>
int main () { int pid = fork(); if (pid < 0) { printf("Error in fork!"); } else if (pid == 0) { printf("子进程:\n22222\npid:%d \n",getpid()); } else { printf("父进程:\n11111\npid:%d \n",getpid()); } return 0; }
|
E2-3-2.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <unistd.h> #include <stdio.h>
int main () { int pid = fork(); if (pid < 0) { printf("Error in fork!"); } else if (pid == 0) { for(int i=0; i < 5; i++){ printf("I am child.\n"); sleep(1); } } else { for(int i=0; i < 5; i++){ printf("I am parent.\n"); sleep(1); } } return 0; }
|
E2-3-3.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <unistd.h> #include <stdio.h>
int main () { int pid1 = fork(); if (pid1 < 0) { printf("Error in fork!"); } else if (pid1 == 0) { printf("A\n"); int pid2 = fork(); if (pid2 < 0) { printf("Error in fork!"); } else if (pid2 == 0) { printf("A\n"); int pid3 = fork(); if (pid3 < 0) { printf("Error in fork!"); } else if (pid3 == 0) { printf("A\n"); int pid4 = fork(); if (pid4 < 0) { printf("Error in fork!"); } else if (pid4 == 0) { printf("A\n"); } else { printf("A\n"); } } else { printf("A\n"); } } else { printf("A\n"); } } else { printf("A\n"); } return 0; }
|
截图
E2-3-1.c编译运行截图
E2-3-2.c编译运行截图
E2-3-3.c编译运行截图
进程创建方法与创建进程数
fork()函数的原理:以当前进程作为父进程创建出一个新的子进程,并且将父进程的所有资源拷贝给子进程,这样子进程作为父进程的一个副本存在。父子进程几乎时完全相同的,但也有不同的如父子进程ID不同。即为创建一个新的进程里面从新进程(即fork处)运行,新的进程拷贝原本进程的所有状态(包括变量,输入输出流等),这两个进程有pid不同(原进程大于0,子进程等于0)、 getpid()(该函数返回当前进程的id号)返回值不同;
利用循环(for)(循环里无判断)/顺序并列创建进程
循环次数n→进程数n2(父进程1个+子进程n2-1个)
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h>
int main() { int pid[3]; for(int i=0;i<3;i++){ pid[i]=fork(); } if(pid[0]*pid[1]*pid[2]==0){ printf("子进程ID=%d\n",getpid()); } printf("父进程ID=%d\n",getpid()); return 0; }
|
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| randall@ubuntu:~/Desktop$ gcc exper.c randall@ubuntu:~/Desktop$ ./a.out 父进程ID=2344 randall@ubuntu:~/Desktop$ 子进程ID=2345 父进程ID=2345 子进程ID=2346 子进程ID=2347 父进程ID=2347 父进程ID=2346 子进程ID=2348 子进程ID=2349 父进程ID=2349 子进程ID=2350 父进程ID=2350 父进程ID=2348 子进程ID=2351 父进程ID=2351
|
利用循环(for)(循环里有判断)/嵌套创建进程
循环次数n→进程数n+1(父进程1个+子进程n个)
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h>
int main() { int pid[3]; for(int i=0;i<3;i++){ pid[i]=fork(); if(pid[i]>0){ break; } } if(pid[0]*pid[1]*pid[2]==0){ printf("子进程ID=%d\n",getpid()); } printf("父进程ID=%d\n",getpid()); return 0; }
|
运行结果
1 2 3 4 5 6 7 8 9
| randall@ubuntu:~/Desktop$ gcc exper.c randall@ubuntu:~/Desktop$ ./a.out 父进程ID=2446 randall@ubuntu:~/Desktop$ 子进程ID=2447 父进程ID=2447 子进程ID=2448 父进程ID=2448 子进程ID=2449 父进程ID=2449
|