进程的创建与并发执行-带答案版

更新时间:2024-05-18 08:39:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验二 进程管理

2.1 进程的创建与并发执行

1.实验目的

(1) 加深对进程概念的理解,理解进程和程序的区别。

(2) 认识并发进程的实质。分析进程争用资源的现象,学习解决进程互斥的方法。 (3) 理解系统调用和用户命令的区别。 2.实验类型:验证型 3.实验学时:2 4.实验原理和知识点

(1) 实验原理:程序的并发执行具有随机性和不可再现性。程序并发执行会导致资源共享和资源竞争,各程序向前执行的速度会受资源共享的制约。程序的动态执行过程用进程这个概念来描述。由于向前推进的速度不可预知,所以多个进程并发地重复执行,整体上得到的结果可能不同。但要注意,就其中某单个进程而言,其多次运行结果是确定的。 (2) 知识点:进程、子进程、并发执行的特性; 5.实验环境(硬件环境、软件环境):

(1)硬件环境:Intel Pentium III 以上CPU,128MB以上内存,2GB以上硬盘 (2)软件环境:linux操作系统。 6. 预备知识

(1) fork()系统调用

头文件:#include unix standard header

/*是POSIX标准定义的unix类系统定义符号常量的头文件,包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数*/ 函数原型: pid_t fork(void);

/*是Linux下的进程号类型,也就是Process ID _ Type 的缩写。其实是宏定义的unsigned int类型*/

函数功能:fork的功能是创建子进程。调用fork的进程称为父进程。如图2.1所示。子进程是父进程的一个拷贝,它继承了父进程的用户代码、组代码、环境变量、已打开的文件代码、工作目录及资源限制。fork语句执行后,内核向父进程返回子进程的进程号,向子进程返回0。父子进程都从fork()的下一句开始并发执行。 返回值:

返回值==-1:创建失败。

返回值==0: 程序在子进程中。 返回值>0: 程序在父进程中。(该返回值是子进程的进程号)

编程提示: 虽然子进程是父进程的一个复制品,但父子的行为是不同的。编程时要抓住内核的返回值。通过返回值,可以知道是父进程还是子进程,因而可以编写不同行为的代码。

1

图2.1 fork()创建进程示意图

(2) wait()系统调用

头文件:#include

函数原型:pid_t wait(int *status);

函数功能:wait的功能是等待子进程结束。发出wait调用的进程只要有子进程,就会睡眠直到子进程中的一个终止为止。若没有子进程,则该调用立即返回。 函数参数:status是子进程退出时的状态信息。 返回值:成功则返回子进程号,否则返回-1。 (3) getpid()系统调用

头文件:unistd.h,在VC++6.0下可以用process.h 函数原型:pid_t getpid(void);

函数功能:wait的功能是将父进程挂起,等待子进程终止。getpid函数用来取得目前进程的进程ID,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。 返回值:目前进程的进程ID。 (4) 其他系统调用 exit – 终止进程

exec – 执行一个应用程序 nice – 改变进程的优先

7. 实验内容与步骤(将所有截图换成用户名为你们自己姓名的拼音,并回答所有的问题) (1)运行图2.1所示程序

将图2.1中的源程序保存为e201.c 在终端中编译gcc –o e201 e201.c

运行 ./e201

2

此时,程序为死循环,在该终端中无法继续输入命令执行,于是,我们可以暂时不管这一个终端,而是再新建一个终端,然后键入 ps –e,列出当前所有进程

观察屏幕,是否有两个名为e201的进程。比较它们的进程号,判别哪个是父进程,哪个是子进程。

程序中的while(1);语句是为了不让程序退出来,以便于你观察进程状态。用kill命令把这两个进程终止。可见,第一个终端如下图所示,已经从死循环中解救出来了。

当然,最简单粗暴的方法不是关闭相关进程,而是直接通过ctrl+c 强制结束。 对图2.1的程序稍加改进,可看见两个进程的进程号。

3

(2)编写一段名为e202.c的源程序,使用系统调用fork()创建两个子进程p1和p2。p1的功能为显示字符'b',p2的功能为显示字符'c',父进程的功能为显示字符'a',父进程和两个子进程并发运行。不停的运行e202,观察并记录屏幕上的显示结果。

程序设计过程:

用while语句控制fork()直到创建成功。用if语句判别是在子进程中还是在父进程中。程序运行后会创建三个进程,它们分别是子进程p1、p2、父进程。这三个进程并发运行。假定子进程有些任务要做,完成这些任务要花一定时间,因此,可以用一个延时函数简单地模拟这些任务。 //e202.c

#include

void delay(int x) /* 延时函数 */ {

int i,j;

for(i=0;i

for(j=0;j

int main() {

int p1,p2;

while((p1=fork())==-1); /* 创建子进程p1 */

if(p1==0) /* 子进程p1创建成功 */ {

delay(4096); /* 子进程p1延时*/

putchar('b'); /* 子进程p1显示字符'b' */ }else{

while((p2=fork())==-1); /* 创建子进程p2 */ if(p2==0) /* 子进程p2创建成功 */ {

delay(2048); /* 子进程p2延时*/

putchar('c'); /* 子进程p2显示字符'c' */ }else{

putchar('a'); /* 父进程显示字符'a' */ } }

return 0; }

按向上的光标键、回车,运行刚才的程序。快速重复这个步骤,观察并记录结果。

4

请回答问题:屏幕上是否有时显示bac,有时显示bca,…。为什么会这样呢?

(3) 参考(1)完成下列程序设计

父子进程同步实验:编写一段程序, 使用系统调用fork()创建一个子进程,子进程求1+2+……+100的和并打印出来,使用系统调用wait()让父进程等待子进程结束。 请贴出源代码截图:

请贴出正确运行截图:

(4) 已知下列Linux程序执行后, 运行结果如下,请画出进程家族树(以进程号标示进程,注意,每次运行进程号都不一样)。 //Linux程序

#include \#include \int main()

5

gethostname sethostname

获取本主机名称 设置主机名称 六、socket控制 socketcall socket bind connect accept send sendto sendmsg recv recvfrom recvmsg listen select shutdown getsockname getpeername getsockopt setsockopt sendfile socketpair

socket系统调用 建立socket 绑定socket到端口 连接远程主机 响应socket连接请求 通过socket发送信息 发送UDP信息 参见send 通过socket接收信息 接收UDP信息 参见recv 监听socket端口 对多路同步I/O进行轮询 关闭socket上的连接 取得本地socket名字 获取通信对方的socket名字 取端口设置 设置端口参数 在文件或端口间传输数据 创建一对已联接的无名socket 七、用户管理

getuid setuid getgid setgid getegid setegid geteuid seteuid setregid setreuid getresgid setresgid getresuid setresuid setfsgid setfsuid getgroups

获取用户标识号 设置用户标志号 获取组标识号 设置组标志号 获取有效组标识号 设置有效组标识号 获取有效用户标识号 设置有效用户标识号 分别设置真实和有效的的组标识号 分别设置真实和有效的用户标识号 分别获取真实的,有效的和保存过的组标识号 分别设置真实的,有效的和保存过的组标识号 分别获取真实的,有效的和保存过的用户标识号 分别设置真实的,有效的和保存过的用户标识号 设置文件系统检查时使用的组标识号 设置文件系统检查时使用的用户标识号 获取后补组标志清单 11

setgroups

设置后补组标志清单 八、进程间通信

ipc

进程间通信总控制调用 1、信号 sigaction sigprocmask sigpending sigsuspend signal kill *sigblock *siggetmask *sigsetmask *sigmask *sigpause sigvec ssetmask

设置对指定信号的处理方法 根据参数对信号集中的信号执行阻塞/解除阻塞等操作 为指定的被阻塞信号设置队列 挂起进程等待特定信号 参见signal 向进程或进程组发信号 向被阻塞信号掩码中添加信号,已被sigprocmask代替 取得现有阻塞信号掩码,已被sigprocmask代替 用给定信号掩码替换现有阻塞信号掩码,已被sigprocmask代替 将给定的信号转化为掩码,已被sigprocmask代替 作用同sigsuspend,已被sigsuspend代替 为兼容BSD而设的信号处理函数,作用类似sigaction ANSI C的信号处理函数,作用类似sigaction 2、消息 msgctl msgget msgsnd msgrcv

消息控制操作 获取消息队列 发消息 取消息 3、管道 pipe

创建管道 4、信号量 semctl semget semop

信号量控制 获取一组信号量 信号量操作 5、共享内存 shmctl shmget shmat shmdt 控制共享内存 获取共享内存 连接共享内存 拆卸共享内存

12

本文来源:https://www.bwwdw.com/article/gm47.html

Top