- 一、实验目的
- 二、实验要求
- 三、实验过程
- 四、思考
加深对进程概念的理解,明确进程与程序的区别,并认识并发执行的实质。
二、实验要求- 编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每个进程在屏幕上显示一个字符,父进程显示“a”;子进程1显示“b”;子进程2显示“c”。多运行几次,观察并分析显示结果。
- 修改程序,将每个进程输出一个字符改为每个进程输出一句话,观察分析显示结果;
- 如果在父进程fork之前,输出一句话,这句话后面不加“\n”或加“\n”,结果有什么不同,为什么?
- 如果在程序中使用系统调用lockf来给临界资源加锁,可以实现临界资源的互斥访问。将lockf加在输出语句前后运行试试;将一条输出语句变成多条输出语句,将lockf语句放在循环语句外部或内部试试,观察显示结果并分析原因。
- 以上各种情况都多运行几次,观察每次运行结果是否都一致?为什么?
-
编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每个进程在屏幕上显示一个字符,父进程显示“a”;子进程1显示“b”;子进程2显示“c”。多运行几次,观察并分析显示结果。
源程序:
#include #include #include int main() { pid_t pid1, pid2; while ((pid1 = fork()) == -1); if (pid1 == 0) printf("b"); else { while ((pid2 = fork()) == -1); if (pid2 == 0) printf("c"); else printf("a"); } return 0; }
分析: 程序输出为’bca’,其中’b’为pid1的输出,’c’为pid2的输出,’a’为父进程的输出。 首先在执行语句pid1 = fork()时,创建了子进程pid1,此时打印’b’; 然后在执行语句pid2 = fork()时,创建了子进程pid2,此时打印’c’; 最后父进程运行,打印’a’。 程序运行多次,发现结果一致,并未有改变。 原因可能是我的操作系统(CentOS5.5)总是按照如上的顺序进行运行。
-
修改程序,将每个进程输出一个字符改为每个进程输出一句话,观察分析显示结果;
源程序:
#include #include #include int main() { pid_t pid1, pid2; while ((pid1 = fork()) == -1); if (pid1 == 0) printf("pid1 here : b\n"); else { while ((pid2 = fork()) == -1); if (pid2 == 0) printf("pid2 here : c\n"); else printf("father progress here : a\n"); } return 0; }
结果和(1)问类似,先由子进程pid1输出,再由子进程pid2输出,最后父进程输出。
-
如果在父进程fork之前,输出一句话,这句话后面不加“\n”或加“\n”,结果有什么不同,为什么?
源代码:
#include #include #include int main() { pid_t pid1, pid2; printf("This is a sentence."); // printf("This is a sentence.\n"); while ((pid1 = fork()) == -1); if (pid1 == 0) printf("pid1 here : b\n"); else { while ((pid2 = fork()) == -1); if (pid2 == 0) printf("pid2 here : c\n"); else printf("father progress here : a\n"); } return 0; }
不加’\n’:
加上’\n’:
结果不同: 第一种情况每个进程都打印了This is a sentence.这句话,而第二种情况只打印了一次。
查阅相关资料后进行分析: (1)不加’\n’: 由于输出时,我们要将内存中的数据输出到磁盘中,系统会先将要printf的内容存到磁盘缓冲区buffer,也就是将This is a sentence.这句话写入buffer。而子进程会继承父进程的buffer内容,于是在子进程中也会打印这句话,第1个子进程会输出,第2个子进程也会输出。
(2)加’\n’: 系统检测到“\n”会自动清空缓冲区,于是子进程继承父进程时,缓冲区里面没有要打印这句话的信息,于是在2个子进程中只分别输出c和b。
-
如果在程序中使用系统调用lockf来给临界资源加锁,可以实现临界资源的互斥访问。将lockf加在输出语句前后运行试试;将一条输出语句变成多条输出语句,将lockf语句放在循环语句外部或内部试试,观察显示结果并分析原因。 (1)直接对stdout加锁,发现和之前的输出没有区别,因为进行互斥约束后仍然可以访问stdout中的资源:
#include #include #include int main() { pid_t pid1, pid2; while ((pid1 = fork()) == -1); if (pid1 == 0) { lockf(1, 1, 0); printf("pid1 here : b\n"); lockf(1, 0, 0); } else { while ((pid2 = fork()) == -1); if (pid2 == 0) { lockf(1, 1, 0); printf("pid2 here : c\n"); lockf(1, 0, 0); } else { lockf(1, 1, 0); printf("father progress here : a\n"); lockf(1, 0, 0); } } return 0; }
(2)进行循环访问并在内部加锁,发现子进程pid1先执行5次输出,然后轮到pid2,最后是parent输出:
#include #include #include int main() { pid_t pid1, pid2; while ((pid1 = fork()) == -1); if (pid1 == 0) { for (int i = 0; i
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?