版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、操作系统实验一进程管理实验班级:2021211311学号:姓名: schnee 目 录1.实验目的32.实验预备内容33.环境说明34.实验内容44.1.进程的创立4程序1题目要求:4程序设计说明:4源代码:4运行结果:5分析:54.2.进程的控制6程序2(a)题目要求:6程序设计说明:6源代码:6运行结果:7分析:7程序2(b)题目要求:7程序设计说明:8源代码:8运行结果:9分析:104.3.进程的软中断通信11程序3(a)题目要求:11程序设计说明:11源代码:12运行结果:14分析:14程序3(b)题目要求:14程序设计说明:14源代码:(略)15运行结果及分析:154.4.进程的管道
2、通信17程序4题目要求:17程序设计说明:17源代码:17运行结果:19分析:195.思考201. 实验目的1) 加深对进程概念的理解,明确进程和程序的区别2) 进一步认识并发执行的实质3) 分析进程争用资源的现象,学习解决进程互斥的方法4) 了解Linux/windows系统中进程通信的根本原理2. 实验预备内容1) 阅读Linux的sched.h源码文件,加深对进程管理概念的理解2) 阅读Linux的fork()源码文件,分析进程的创立过程3. 环境说明此实验采用的是Win7下虚拟机VMware-workstation-6.5.3-185404及kanas-ubuntu-10.10-des
3、ktop-i386。直接编写文件在终端用命令行执行。虚拟机分配8G 内存中的512M。操作尚未取得root权限。ubuntu用户名jrayty。4. 实验内容4.1. 进程的创立程序一:题目要求:编写一段程序,使用系统调用fork()创立两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a,子进程分别显示字符“b和“c。试观察记录屏幕上的显示结果,并分析原因。程序设计说明:此程序相对简单。详见源代码。4.1.3源代码:#include <cstdio>#include <cstdlib>#include
4、<unistd.h>#include <iostream>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>using namespace std;int main() pid_t p1, p2; while(p1=fork() = -1); /create child progress 1 if(p1 = 0) putchar('b'); /child progress 1 print 'b' exit(0); else w
5、hile(p2=fork() = -1); /create child progress 2 if(p2 = 0) putchar('c'); /child progress 2 print 'c' exit(0); else putchar('a'); /parent progress print 'a' exit(0); return 0;4.1.4运行结果:4.1.5分析:从截图可见运行结果有abc, bac, acb等。这是因为三个进程间没有同步措施,所以父进程和两个子进程的输出次序带有随机性。因此实际上三者的各种组合都可
6、能出现。4.2. 进程的控制程序:.1题目要求: 修改已经编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。程序设计说明:直接改自第一个程序。其间加sleep() 是为了标准下格式。详见源代码。.3源代码:#include <cstdio>#include <cstdlib>#include <unistd.h>#include <iostream>#include <sys/types.h>#include <sys/stat.h>#include <sys/w
7、ait.h>using namespace std;int main() pid_t p1, p2; while(p1=fork() = -1); /create child progress 1 if(p1 = 0) puts("I'm the Child Progress 1 !"); exit(0); else while(p2=fork() = -1);/create child progress 2 if(p2 = 0) puts("I'm the Child Progress 2 !"); exit(0); else s
8、leep(4); puts("I'm the Parent Progress !");/parent progress exit(0); return 0;.4运行结果:.5分析:可见运行情况和第一个程序是很像的。虽然换成了字符串,但同一个进程里puts字符串并不会被中断。程序2:.1题目要求: 如果在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。程序设计说明:学习lockf()函数学了好久。程序中运用了多个sleep()并且让每个进程多输出了几次,从而使结果更明显。且让父进程休息较久,从而让子进程都执行完。.3源
9、代码:#include <cstdio>#include <cstdlib>#include <unistd.h>#include <iostream>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>using namespace std;int main() pid_t p1, p2; int i; while(p1=fork() = -1); /create child progress 1 if(p1 = 0) lockf(1
10、, 1, 0);/lock for(i=0; i<4; i+) sleep(1); puts("I'm the Child Progress 1 !"); lockf(1, 0, 0);/unlock exit(0); else while(p2=fork() = -1);/create child progress 2 if(p2 = 0) lockf(1, 1, 0);/lock for(i=0; i<4; i+) sleep(1); puts("I'm the Child Progress 2 !"); lockf(1,
11、 0, 0);/unlock exit(0); else puts("I'm the Parent Progress !"); sleep(10); puts("I'm the Parent Progress !"); exit(0); return 0;.4运行结果:*假设是去掉lockf(),那么运行结果如下.5分析:从上面运行结果可以看出。无论加不加锁,两个子进程运行的次序是随机的。但是加锁后一个进程会全部输出完了才转给另一个进程。从而我们可以看出lockf()对两个进程对标准输出流的互斥使用。lockf(fileno(fp),F_
12、LOCK,0L)函数的第一个参数是加锁的文件,上述程序用的是1,即标准输出流;第二个参数是操作,1表示加锁0表示解锁。第三个参数是文件长度,文中用0表示整个文件。4.3. 进程的软中断通信程序3:4.3.1题目要求: (a)使用系统调用fork()创立两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号即按Del/CTRL+C键.当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后分别输出以下信息后终止:Child Process 1 is killed by Parent!Child Process 2 is killed by Pare
13、nt!父进程等待两个子进程终止后,输出如下的信息后终止:Parent Process is killed!程序设计说明:1题目解析和问题解决一, 要求Del后引发父进程的动作。实际就是触发软中断SIGINT。二, 要求在中断到来前两子进程处于等待状态,中断到来后立刻动作。对此,我自定义了两个函数my_wait()函数和my_stop()函数,通过对flag标志位的操作来实现。flag为真时等待,中断到来后通过my_stop()函数使flag改为假,从而退出等待的死循环。虽然这样效率很低,但是在这个小程序里还是可以的。三, 至于如何控制父进程杀死子进程后再自杀,我用了signal()函数预留给用
14、户自定义的10和12号信号,即SIGUSR1和SIGUSR2。让两个子进程分别监听这两个信号,父进程被触发后分别向两个子进程发出这两个信号杀死他们,然后再退出即可。2知识点补充学习到的函数的定义。1软中断信号预置函数signal (sig , function)sig 系统给定的软中断信号中的序号或名称。function 与软中断信号关联的函数名,当进程在运行过程中捕捉到指定的软中断信号后,中断当前程序的执行转到该函数执行。注意:软中断信号必须提前预置,然后才可以在程序运行中捕获。2发送软中断信号函数 int kill ( pid , sig )pid表示一个或一组进程的标识符:当pid>
15、;0时,将信号发送给指定pid的进程;当pid=0时,将信号发送给同组的所有进程;当pid=-1时,将信号发送给以下所有满足条件的进程:该进程用户标识符等于发送进程有效用户标识符;sig软中断信号的序号或名称功能:向指定进程标识符pid的进程发软中断信号sig。本章中用来实现父进程给子进程发终止执行软中断信号。3父子父同步的实现在进程同步中,使用exit()和wait()实现了父进程等子进程终止的同步,但是这种同步方法不能实现子进程对父进程的等待。要实现子进程对父进程的等待可以使用父进程向子进程发软中断信号,子进程接收信号的方式实现。这两种同步方式相结合,可以实现父子父的同步序列。实现父子父同
16、步的步骤如下:子进程使用signal()预置软中断处理函数,然后等待父进程发软中断信号;父进程中使用kill()发软中断信号给子进程,再用wait(0)等待子进程结束;子进程接收到软中断信号后转去执行中断处理函数子进程在中断处理返回后,使用exit(0)终止执行,向父进程发终止信息。父进程使用wait(0)接收到子进程的终止信息后结束等待,并终止自己的程序的执行。源代码:#include <cstdio>#include <cstdlib>#include <unistd.h>#include <iostream>#include <sig
17、nal.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>using namespace std;bool flag;pid_t p1, p2;void my_wait(int q) while(flag);void my_stop(int q) flag=false;int main() signal(SIGINT, my_stop); /Del or Ctrl+C trigger while(p1=fork() = -1); /create child progres
18、s 1 if(p1 = 0) flag=true; /p1 set waiting signal(SIGUSR1, my_stop);/set SIGUSR1 to stop my_wait(0); /waiting lockf(1, 1, 0); /lock puts("nChild Process 1 is killed by Parent!"); lockf(1, 0, 0); /unlock sleep(1); exit(0); else while(p2=fork() = -1); /create child progress 2 if(p2 = 0) flag=
19、true; /p2 set waiting signal(SIGUSR2, my_stop);/set SIGUSR2 to stop my_wait(0); /waiting lockf(1, 1, 0); /lock puts("nChild Process 2 is killed by Parent!"); lockf(1, 0, 0); /unlock sleep(1); exit(0); else flag=true; /parent set waiting my_wait(0); kill(p1, SIGUSR1); kill(p2, SIGUSR2); wai
20、t(NULL); wait(NULL); puts("nParent Process is killed!"); exit(0); return 0;.4运行结果:.5分析:如上图,可见两个子进程的执行顺序还是随机的。程序:.1题目要求:(b)在上面的程序中增加语句signal(SIGINT,SIG_IGN)和signal(SIGQUIT,SIG_IGN),观察执行结果,并分析原因。.2程序设计说明: signal(SIGTINT, SIG_IGN);/后台进程读中断信号,默认挂起 signal(SIGQUIT, SIG_IGN);/程序终止信号,默认操作写dump-cor
21、e文件.3源代码:(略) .4运行结果及分析: *signal(SIGINT, my_wait)加到第二个else里面*加signal(SIGINT, SIG_IGN)*加signal(SIGINT, SIGIGN)后signal(SIGINT, my_wait)加到第二个else里面分析:1单纯在程序3的根底上把signal(SIGINT, my_wait)加到第二个else里面后一开始子进程不再输出了。这是因为SIGINT信号不只向父进程还向子进程发出了信号,而子进程并未对它重定义故就执行默认定义直接被杀死了。于是子进程实际上是被SIGINT杀死的而不是被父进程kill的。2单纯地加了si
22、gnal(SIGINT, SIGIGN)后虽然外表看起来和不加它没区别,但是本质却完全不同了。现在子进程确实是被父进程杀死的。因为SIGINT已经被忽略了。3加signal(SIGINT, SIGIGN)并且signal(SIGINT, my_wait)加到第二个else里面后输出也是一样,不会再发生子进程不输出的情况了。因为现在子进程的SIGINT已经被忽略了。*加了signal(SIGQUIT,SIG_IGN)分析:在程序3的根底上在两个进程的前面参加signal(SIGQUIT, SIG_IGN), 运行结果如上图输入ctrl+C时还是不变但是后直接退出了,所有的进程都没有输出,并没有被
23、屏蔽。资料说signal(SIGTINT, SIG_IGN);/后台进程读中断信号,默认挂起 signal(SIGQUIT, SIG_IGN);/程序终止信号,默认操作写dump-core文件但是我还是没有太了解。4.4. 进程的管道通信程序4:题目要求:编制一段程序,实现进程的管道通信。使用系统调用pipe()建立一条管道线,两个子进程P1和P2分别向管道各写一句话:Child 1 is sending a message!Child 2 is sending a message!而父进程那么从管道中读出来自于两个子进程的信息,显示在屏幕上。要求父进程先接收子进程P1发来的消息,然后再接收子
24、进程P2发来的消息。程序设计说明:为了防止两个进程抢占管道,我把第二个子进程延时了,并且对管道加锁,从而形成独占,防止冲突产生。而父进程只需用之前的wait()函数即可确保在两个子进程后执行。源代码:#include <cstdio>#include <cstdlib>#include <unistd.h>#include <iostream>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h
25、>using namespace std;const int PIPE_MAX = 0x7f; /pipe buffer max sizeconst int RW_MAX = 0x40; /r/w buffer max sizeint main() pid_t p1, p2; int river2; /1 in, 0 out char rbPIPE_MAX, wbPIPE_MAX; pipe(river); /create pipe while(p1=fork() = -1); /create child progress 1 if(p1 = 0) lockf(river1, 1, 0)
26、; /lock sprintf(wb, "Child 1 is sending a message!n"); write(river1, wb, RW_MAX); lockf(river1, 0, 0); /unlock exit(0); else while(p2=fork() = -1);/create child progress 2 if(p2 = 0) sleep(1); /wait p1 lockf(river1, 1, 0);/lock sprintf(wb, "Child 2 is sending a message!n"); write
27、(river1, wb, RW_MAX); lockf(river1, 0, 0);/unlock exit(0); else wait(NULL); /wait p1 read(river0, rb, RW_MAX); printf("%sn", rb); wait(NULL); /wait p2 read(river0, rb, RW_MAX); printf("%sn", rb); exit(0); return 0;4.4.4运行结果:.5分析:管道通信通过系统调用pipe()初始化一个二元组为管道,1出0进。5. 思考1系统是怎么创立进程的?答
28、:新进程通过克隆老进程或是当前进程来创立。系统调用fork或clone可以创立新任务,复制发生在核心状态下地核心中。在类UNIX系统中,除了根进程之外,如果想要在系统之中创立一个新的进程,唯一的方法就是利用一个已存在的进程通过系统调用fork()函数来实现,fork()函数被调用时,它会将调用它的进程复制出一个副本一般会共享代码段,其它的数据段和堆栈等会复制个新的,原进程是复制得到进程的父进程,两个进程除了进程号不同,是一模一样,fork 调用结束后将 0 返回给子进程,将子进程的进程号返回给父进程,在调用fork函数之后,父子进程都将从位于fork函数的调用点之
29、后的指令处开始执行,因为是两个不同的进程,它们的执行是并行的,先后次序是不定的。参考 ?Linux内核完全解析?和 编程爱好者网站相关文章2可执行文件加载时进行了哪些处理?答:当操作系统装载一个可执行文件的时候,首先操作系统判断该文件是否是一个合法的可执行文件。如果是操作系统将按照段表中的指示为可执行程序分配地址空间。 加载文件最重要的是完成两件事:加载程序段和数据段到内存,以及进行外部定义符号的重定位。下面是ELF文件为例的可执行文件加载处理:1, 内核读文件的头部,然后根据文件的数据指示分别读入各种数据结构,找到可加载的段加载到内存中。2, 内核分析出文件对应的动态连接器名称并加载动态连接器。3, 内核在新进程的堆栈中设置一些标记-值对,以指示动态连接器的相关操作。4, 内核把控制传递给动态连接器。5, 动态连接器检查程序对外部文件共享库的依赖性,并在需要时对其进行加载。6, 动态连接器对程序的外部引用进行重定位。7, 动态连接器进行程序运行的初始化。8, 动态连接器把控制传递给程序,从文件头部定义的程序进
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年石油化工班组长安全试题带答案
- 2026年四川省什邡市高一化学上册期末考试模拟卷(全优)附答案
- 2026年湖南省汨罗市高三生物下册期末考试模拟检测卷及参考答案
- 2026年吉林省集安市高三生物下册期末考试模拟试卷含答案
- 2026年福建省邵武市高三生物下册期末考试模拟测试卷及答案
- 2026年黑龙江省尚志市高三生物下册期末考试模拟测试卷(含答案)
- 2026年山东省安丘市高一化学上册期末考试试卷附参考答案(综合卷)
- 2026年江苏省如皋市高三物理下册期末考试模拟测试卷(含答案)
- 2026年安徽省宁国市高一化学上册期末考试考试卷含完整答案【夺冠】
- 2026年江苏省仪征市高三生物上册期末考试自测卷带答案
- 《计算政治学概论》课件 第1-8章 计算政治学的起源与发展-数字社会治理
- CSCO非小细胞肺癌诊疗指南(2026版)
- 2025湖南长沙矿山研究院发布校招招聘52人笔试历年典型考点题库附带答案详解
- 压缩空气储能地下洞库施工方案
- 自密实混凝土施工方法及浇筑管控要点
- (2026年)护理查对制度课件
- 冻品食材配送服务方案
- 电力重大事故隐患判定与治理监督规定(2026版)深度解读课件
- 水库 旅游项目实施方案
- 2026上海市民政第三精神卫生中心招聘7人笔试备考题库及答案解析
- 2025-2030中国直线伺服电机市场经营动态及发展行情走势预测研究报告
评论
0/150
提交评论