Linu并发程序设计实习报告.docx
- 文档编号:25906918
- 上传时间:2023-06-16
- 格式:DOCX
- 页数:25
- 大小:755.45KB
Linu并发程序设计实习报告.docx
《Linu并发程序设计实习报告.docx》由会员分享,可在线阅读,更多相关《Linu并发程序设计实习报告.docx(25页珍藏版)》请在冰豆网上搜索。
Linu并发程序设计实习报告
实习报告:
Linux并发程序设计
学生姓名:
张云龙班级:
12软工A2学号:
一、实习内容
1、Linux进程控制
调试上面7.1Linux进程控制的各程序代码。
1〉示例:
使用系统调用fork(),创建新进程。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.1。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.1.c–o7.1对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.1对程序进行编译执行!
《三》通过测试,可以很清楚的知道,一个进程有2801个子进程!
2〉示例:
使用系统调用getpid(),获得进程标识符
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.2。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.2.c–o7.2对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.2对程序进行编译执行!
《三》通过测试,可以很清楚的知道,现在正在运行的进程的ID是2813!
3〉示例:
fork()创建子进程后,子进程在屏幕上显示子进程标识符与父进程标识符。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.3。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.3.c–o7.3对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.3对程序进行编译执行!
《三》通过测试,可以很清楚的知道,现在正在运行的进程的ID是2834!
父进程2863个!
4〉使用execl()系统调用,运行目录列表程序ls。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.4。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.4.c–o7.4对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.4对程序进行编译执行!
《三》通过测试,可以很清楚的知道,该程序实际上是实现了”ls–l”的命令!
5〉功能改用execv()系统调用完成。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.5。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.5.c–o7.5对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.5对程序进行编译执行!
《三》通过测试,可以很清楚的知道,该程序实际上是实现了”ls–l”的命令!
6〉使用系统调用fork()与exec,使父子进程运行完全不同的程序。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.6。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.6.c–o7.6对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.6对程序进行编译执行!
《三》通过测试,可以很清楚的知道,该程序实际上是实现了”ls–l”的命令!
7〉使用系统调用exit(),终止进程。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.7。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.7.c–o7.7对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.7对程序进行编译执行!
《三》通过测试,可以很清楚的知道,该程序实现了把进程为18188的程序退出的命令!
8>使用wait()系统调用,实现父子进程的简单同步。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.8。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.8.c–o7.8对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.8对程序进行编译执行!
《三》。
在等待了大约十秒钟之后,会弹出如下的结果图~
《四》。
通过测试,我很清楚的知道,该程序实际上是实现了进程等待的命令~
9>系统调用sleep()
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.9。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.9.c–o7.9对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.9对程序进行编译执行!
《三》。
在等待了大约一分钟之后,会弹出如下的结果图~
四》。
通过测试,我很清楚的知道,该程序实际上是实现了子进程开始睡眠,而父进程等待的命令~也就是所谓的程序的挂起!
2、Linux进程通信
调试上面7.2Linux进程通信的各程序代码。
事例:
在父子进程间建立管道,且子进程向父进程输送信息。
《一》在linux中打开vi编辑器,新建一个c程序,名字叫做7.10。
然后将上面的程序代码输入其中!
在将程序完整的输入之后!
保存程序,并退出!
《二》。
然后在提示符$后输入命令:
gcc–g7.9.c–o7.9对程序进行调试!
若是没有任何的错误和提醒的话,那么在接着出现的提示符$后输入命令:
./7.9对程序进行编译执行!
并完成并发程序设计的实验内容:
并发程序的设计关键是使用创建进程的系统调用,使一个程序运行时可以生成几个同时运行的程序,如果程序中没有创建进程的动作则为顺序程序设计。
本实验中的并发程序例子完成两个程序child和father之间的数据传递工作,具体做法分为四步。
步骤1:
编制并发程序pipeline.c。
单击红帽子,在“GNOME帮助”菜单中单击“附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为pipeline.c。
在该程序中定义管道和文件描述符,并且创建子进程child。
该程序用到的系统调用有pipe()、dup()、fork()、close、execl()、exit,它们的功能分别是建立管道、复制文件描述符、创建进程并使子进程与父进程有相同的程序正文、关闭文件描述符、用指定文件覆盖调用程序、撤销当前进程。
清单4-5pipeline.c
//定义管道程序
#defineSTD_INPUT0//定义标准输入设备描述符
#defineSTD_OUTPUT1//定义标准输出设备描述符
intfd[2];
main()
{
staticcharprocess1[]="father",process2[]="child";
pipe(fd);//定义管道
pipeline(process1,process2);//调用自定义函数pipeline()
exit
(1);//程序结束
}
pipeline(char*process1,char*process2)
{
inti;
while((i=fork())==-1);//创建进程,直到创建成功为止
if(i)
{
close(fd[0]);//关闭管道输入描述符
close(STD_OUTPUT);//关闭标准输出描述符1
dup(fd[1]);//指定标准输出描述符1为管道写指针
close(fd[1]);//关闭原始管道写指针
execl(process1,process1,0);//用程序father覆盖当前程序
printf("fatherfailed.\n");//execl()执行失败
}
else
{
close(fd[1]);//关闭管道输出描述符
close(STD_INPUT);//关闭标准输入描述符0
dup(fd[0]);//指定标准输入描述符0为管道读指针
close(fd[0]);//关闭原始管道读指针
execl(process2,process2,0);//用程序child覆盖当前程序
printf("childfailed.\n");//execl()执行失败
}
exit
(2);//程序结束
}
步骤2:
编制“管道写”程序father.c作为父进程的一部分工作。
其内容如下:
单击红帽子,在“GNOME帮助”菜单中单击“附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为father.c。
清单4-6father.c
main()
{
staticcharstring[]=“Parentisusingpipewrite.”;
intlen;
len=sizeof(string);
write(l,string,len);/*将string中的内容写入管道中*/
printf(“parent,parent,parent\n\n\n”);
exit(0);
}
步骤3:
编制“管道读”程序child.c作为子进程的一部分工作。
其内容如下:
单击红帽子,在“GNOME帮助”菜单中单击“附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为child.c。
清单4-7child.c
main()
{
charoutput[30];
read(0,output,30);/*从管道中读数据并存入output中*/
printf(“%s\nchild,child.\n”,output);
return(0);
}
步骤4:
编译。
cc–ochildchild.c
cc-ofatherfather.c
cc-opipelinepipeline.c
步骤5:
运行。
./pipeline
首先单击红帽子,在“GNOME帮助”菜单中单击“附件”-“文本编辑器”命令,在文本编辑中分别键入三个程序。
三个程序的程序名分别为pipeline.c,father.c和child.c。
若运行不成功,则应该用文本编辑器对源程序进行修改调试。
运行显示结果为:
____
________________________________________________________________
3、Linux命令接口管理进程
步骤1:
登录进入GNOME。
在Linux登录框中填写指导老师分配的用户名和口令,登录Linux系统。
步骤2:
访问命令行。
单击红帽子,在“GNOME帮助”菜单中单击“系统工具”-“终端”命令,打开“终端”窗口。
步骤3:
回顾系统进程概念。
每个运行的程序都会创建一个进程,进程分配到一个唯一的进程标识符(PID)。
PID被系统用于标识和跟踪进程,直到进程结束。
操作系统内核管理所有进程的初始化和终止。
每一个进程都要求系统资源(例如CPU时间和RAM空间)在其中工作。
当进程启动的时候,操作系统把系统资源分配给每个进程,当进程终止的时候,系统回收这些资源。
在Linux系统启动的时候,首先启动的两个进程是sched(调度)和init(初始化),它们管理着其他进程。
Linux系统中有几种不同类型的进程:
守护进程:
由Linux内核启动的进程,为了特定目的而存在。
例如,lpsched守护进程存在只是为了处理打印作业。
父进程:
派生其他进程的进程是父进程。
一个叫做init的守护进程是第一个调用的进程。
每一个进程,除了init之外,都有一个父进程。
子进程:
由其他进程派生出来的进程叫做子进程。
孤儿进程:
在进程返回输出之前,它的父进程结束了,这样的进程叫做孤儿进程。
僵进程:
子进程没有带着输出返回给父进程。
这样的进程在系统中变成丢失的进程。
使用此前的信息,完成以下填空:
1)Linux系统中,几乎每一个启动的进程,都会由内核分配一个唯一的____进程标识符(PID)____,用于跟踪从进程启动到进程结束。
2)当启动新进程的时候,内核也给它们分配系统资源,如___内存____和__资源______。
3)永远不向父进程返回输出的进程叫做_____僵进程_________。
4)由父进程派生出来的进程叫做________子__________进程。
5)_______父_________进程是一个派生另一个进程的进程。
6)运行用于提供服务的Linux系统进程是____守护进程__________。
7)如果父进程在子进程之前结束,它创建了一个_____孤儿_________进程。
步骤4:
回顾ps命令和信息。
ps命令用于列出当前系统中运行的进程。
如果一个进程耗时太长,或者看上去好像已经终止了,表现为一个终端窗口不再响应或挂起,通常需要使用ps查看系统中的进程。
通过列出进程,可以查看初始化进程的命令或程序的名字,以及所有它派生出来的子进程。
通过多次执行ps命令,查看进程的时间——进程占用的CPU时间,可以检查一个进程是否还在运行。
如果时间小再增长,那么进程可能已经终止了。
如果进程占用太长的时间或者已经停止,可以使用ps命令检查进程的进程ID(PID),然后杀死进程。
ps命令的输出将显示PID号和与其相关的命令或程序。
PID号通常用于终止一个进程。
ps命令(ps[-options])的3个主要选项如下表所示。
表3-5ps命令选项
ps选项
意义
功能
Ps
无选项
显示当前shell或终端窗口中,当前用户的进程信息
ps–e
每一个
显示系统中每一个进程的信息
ps–f
完全
产生一个完全列表,给出每个进程的所有可用信息
ps-uuserid
用户
显示特定用户的所有进程
基本的ps命令显示在当前shell中的进程信息,用户只能够查看在这个终端窗口中初始化的进程。
输入ps命令,将结果填入表3-6中。
表3-6实验记录
PID
TTY
TIME
CMD
?
2367
?
pts/0
?
00:
00:
00
Bash?
?
3001
?
pts/0
?
00:
00:
00
?
ps
从当前终端窗口中,练习使用给出的每个选项的ps命令。
输入ps-f命令,显示运行在系统中的某个进程的完全信息,填入表3-7中。
表3-7实验记录
UID
PID
PPID
C
STIME
TTY
TIME
CMD
?
root
?
2937
?
2935
0?
?
18:
15
pts/0?
?
00:
00:
00
bash?
?
root
?
3003
2937?
?
0
18:
34?
pts/0?
?
?
00:
00:
00
?
ps-f
ps-f命令输出的各栏标题见表3-8所示。
表3-8ps-f栏标题
值
描述
UID
初始化进程的用户ID
PID
进程的进程标识号。
PID可以用来杀死进程
PPID
进程的父进程标识号
C
进程的优先级
STIME
进程的启动时间
TTY
控制进程终端的终端举型
TIME
进程使用的CPU时间的数量
CMD
命令名守护进程(执行的程序的名字)
步骤5:
列出系统中运行的所有进程。
输入ps-ef命令,显示运行在系统中的各个进程的完全信息。
执行该命令,并与ps–f命令的输出结果对照,一致吗?
有何不同?
_______不一致!
用户类型增加了!
________________________________________
注意分析当前终端窗口中的输出结果:
a.显示了多少个进程?
_____________64______________________________________________________
b.进程ID的PID是什么?
____________进程的进程标识号。
PID可以用来杀死进程_________________________
c.启动进程的命令(CMD)是什么?
________________sched___________________
d.请观察,什么命令的PID号是1?
___________intit________________________________________________________
e.再次运行ps–ef命令,计算进程的数目:
____________________________________________________________________
然后执行下列命令把输出结果输入到wc命令中:
ps-ef|wc-l
第一个数字显示的是行的数目,也是进程的数目:
_________________64___________________________________________________
执行manps命令,可以打开Linux用户命令手册,了解ps命令的用法,输入wq命令可退出用户手册的阅读。
man命令可以执行吗?
结果如何?
___________不可以__________________________________
步骤6:
根据命令名搜索特定的进程。
为了终止一个进程,必须找到该进程的PID。
大多数运行的系统中,有上百个进程在运行,ps-ef的列表可能很长。
如果知道启动进程的执行程序的名字,可以更快地找到PID。
通过把ps命令的输出结果输入到grep中,可以搜索想要终止的特定进程,确定正确的PID。
grep命令可以在其他命令的输出中搜索所有类型的特征字符串。
-l(长的输出)选项将显示和找到的PID相关的进程的名字;-e选项显示PID和初始化命令的名字。
a.单击红帽子,在“GNOME帮助”菜单中单击“游戏”-“堆麻将”命令,打开“堆麻将”游戏。
b.在当前的终端窗口中,执行命令:
ps–e|grepmahjongg
(“堆麻将”游戏的进程名是“mahjongg”),查找和“堆麻将”游戏调度守护进程相关的所有进程。
c.显示了多少个相关进程?
_____________________2_______________________________________________
d.显示进程中最小的进程ID号是多少?
_______________2818_____________________________________________________
c.在当前终端窗口中执行命令:
pgrep–lmahjongg
查找所有和“堆麻将”游戏调度守护进程相关的进程。
ps和pgrep命令输出之间有什么不同?
ps–e|grepmahjongg命令比pgrep–lmahjongg命令输出结果多显示了TTY和TIME___________________________
步骤7:
确定一个要终止的进程。
当试图终止一个程序,或者释放一个挂起的终端窗口的时候,杀死和不响应的应用相关的PID可能还是不够的,一般需要杀死那个进程的父进程,在少数情况下,甚至要杀死父进程的父进程。
为了沿着层次结构,从子进程追溯到派生它们的父进程,必须能够查找PID和PPID。
必须首先确定最低级不响应进程的PID。
通常,可以试着去杀死那个进程。
如果这样做不能够停止那个进程,可能需要杀死它的父进程。
杀死父进程将杀死所有它派生的子进程。
杀死一个父进程也比杀死几个子进程快得多。
1)在GNOME当前终端窗口中,输入ps命令。
有多少进程正在运行?
为什么只有这么少的进程?
____有2个进程正在运行。
因为单前只运行bash和ps这两个程序______
2)正在运行的进程的名字是什么?
它表示什么?
__bash和ps。
bash是打开终端后自动启动的程序,ps是当前执行的命令。
_______
3)这个进程的PID是多少?
_____________2836和2868___________________________________
4)在bashshell中输入命令csh,打开一个Cshell会话,当前系统的会话提示符是什么?
______________________~______________________________________________
5)输入ps-f命令,显示在当前shell中运行的进程的所有信息。
现在什么进程正在运行?
________________bash,-sh和ps-f________________
6)bash的PID是-sh(csh)的PPID吗?
_____________________________是_______________________________________
7)输入命令sleepl000&,创建一个进程,把执行挂起1000秒(大约15分钟)。
&表示在后台运行命令,返回shell提示符,这样您可以继续工作。
8)再次输入ps-f命令。
-sh(csh)的PID是sleep命令的PPID吗?
哪个PID是csh(Cshell)的子进程?
________是,sleep1000和ps-f都是csh(Cshell)的子进程___________
9)输入命令kill-9
然后再次键入ps-f命令。
什么PID是sleep父命令的PPID?
________________________0____________________________________________
sleep进程现在是什么类型的进程?
_____________孤儿进程_____________________________________________
步骤8:
使用kill命令终止一个进程。
信号用于终止、挂起和继续进程。
有时候使用Ctrl+c可以终止一个不响应的进程。
这样向进程发送一个中断(INT)信号,终止它及所有它派生的子进程。
kill命令提供了一个终止不想要的命令进程的直接方法。
当想停止一个运行了很长时间的命令的时候,或者当需要终止一个不能够正常退出的进程的时候,它很有用。
指定PID正常地杀死一个进程。
kill[-signal]process-id
为了使用kill命令终止一个进程,应该首先键入ps找出进程的PID,然后键入kill紧跟着PID。
如果使用kill而没有指定信号,则信号15(SIG
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linu 并发 程序设计 实习 报告