最近学习到操作系统原理中的进程同步的知识点时,为了加深对进程的了解,就实践了一下在Linux系统中fork()函数的使用。
装有Linux系统的电脑
以下过程都默认对Linux系统的基本命令有一定的了解,像cd,mkdir 等命令都比较熟悉,然后基本上会用vim编辑器
Linux系统版本不限,虚拟机中也行! |
编写一段程序,使用系统调用fork()创建两个进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程输出不同的内容。试观察记录屏幕上的显示结果,并分析原因。
以下的显示结果中 wzm 为我的用户名!
1.打开终端,切换到root用户
sudo su
2.新建一个文件夹命名为process,用来存放学习过程中用到的文件
mkdir process
3.新建一个文件夹命名为test1,存放任务1用到的C程序文件
mkdir test1
4.建一个C程序 test1.c
vim test1.c
上述过程中我的文件夹已存在,我就直接使用cd命令切换进去的!!! |
#include
2 #include<stdio.h>
3
4 int main(){
5 pid_t fpid1,fpid2; //fpid表示fork函数返回的值
6 fpid1=fork(); //进程1
7 if(fpid1 < 0){
8 printf("error in fork!\n");
9 }else if(fpid1 == 0){
10 printf("I am the child1 process, my process id is %d\n", getpid());
11 }else{
12 printf("I am the parent1 process, my process id is %d\n", getpid());
13
14 }
15
16
17 fpid2=fork(); //进程2
18 if(fpid2 < 0){
19 printf("error in fork!\n");
20 }else if(fpid2 == 0){
21 printf("I am the child2 process, my process id is %d\n", getpid());
22
23 }else{
24 printf("I am the parent2 process, my process id is %d\n", getpid());
25
26 }
27
28 return 0;
29 }
6.编译运行
gcc test1.c
./a.out
运行结果如下:
不难发现上述程序执行之后,进程2中的语句被输出了两遍,分析原因如下:
fork()函数:一个现有进程通过调用fork()函数可以创建一个新进程
fork()函数被调用一次,能够返回两次,返回值有三种:
1.进程创建出现错误,返回一个负值;
2.在子进程中,返回值为0;
3.在父进程中,返回值为新创建的子进程的ID;
因此可以通过返回值来判断当前进程是父进程还是子进程。
而关于多次运行出现的顺序不同则是因为:在调用fork()函数之后,父进程与子进程之间的执行顺序是不确定的,这个取决于内核的调度算法。
而将test1.c的内容改为如下:显示的数目又将不一样
因此在创建了多个新进程的情况下,一定要注意是只让父进程创建新进程还是之前的父进程和子进程都创建新进程!!!
修改上述程序,每一个进程循环显示一句话。子进程显示’daughter …‘及’son …’,父进程显示’parent …’,观察结果,分析原因。
1.打开终端,切换到root用户,切换到process目录下
sudo su
cd /home/wzm/process
2.新建文件夹test2,并在其中建test2.c
mkdir test2
cd /home/wzm/process/test2
vim test2.c
3.向test2.c中写入
1 #include<unistd.h>
2 #include<stdio.h>
3
4 int main(){
5 pid_t fpid1,fpid2; //fpid表示fork函数返回的值
6 fpid1=fork(); //子进程1
7 if(fpid1 < 0){
8 printf("error in fork!\n");
9 }else if(fpid1 == 0){
10 printf("I am the son process, my process id is %d\n", getpid());
11 }else{
12 fpid2=fork(); //子进程2
13 if(fpid2 < 0){
14 printf("error in fork!\n");
15 }else if(fpid2 == 0){
16 printf("I am the daughter process, my process id is %d\n", getpid());
17 }else{
18 printf("I am the parent process, my process id is %d\n", getpid());
19 }
20 }
21
22 return 0;
23 }
4.编译运行
gcc test2.c
./a.out
运行结果如下:
不难发现父程序与子程序之间的执行顺序仍然是不确定的
任务二的原理与任务一的原理很相似
再调用exec()用新的程序替换该子进程的内容,并利用wait()来控制进程执行顺序。调用exit()使子进程结束。
1.打开终端,切换到root用户,切换到process目录下
sudo su
cd /home/wzm/process
2.新建文件夹test3,并在其中建test2.c
mkdir test3
cd /home/wzm/process/test3
vim test3.c
3.向test3.c中写入
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4 #include<sys/types.h>
5 #include<sys/wait.h>
6 void main(){
7 int pid;
8 pid=fork();
9 switch(pid){
10 case -1:{
11 //表示创建失败
12 printf("error in fork!\n");
13 exit(1);
14 }
15 case 0:{
16 //子进程
17 execl("/bin/date","date",NULL);
18 printf("error in execl");
19 exit(1);
20 }
21 default:{
22 //父进程
23 wait(NULL);
24 printf("command date completed!\n");
25 exit(0);
26 }
27 }
28 }
4.编译运行
gcc test3.c
./a.out
运行结果如下:
exec是一组函数的统称,在这里我用的是execl()函数,exec()函数用来替代fork()函数新创建的子进程执行。
执行成功的话就不会返回,进程结束;
执行失败的话会返回错误信息,继续执行后面的代码,并且之后必须的用exit()函数来让子进程退出。
这里我用来替代子进程的程序的功能是执行命令date,在Linux系统中date命令只是简简单单地用来显示目前的时间信息。
作为一个Linux系统新手,刚开始看fork()函数时也是很懵逼的,也是看了好多博客才逐渐明白的,上面的解释可能写得不是很清楚,自己Linux系统的学习之路还很遥远,但是慢慢来慢慢练,一天了解几个命令总会用熟的。最后很感谢那些将自己的心得体会分享的博客主们!!!