linux实验报告.docx
- 文档编号:11328988
- 上传时间:2023-02-27
- 格式:DOCX
- 页数:39
- 大小:126.59KB
linux实验报告.docx
《linux实验报告.docx》由会员分享,可在线阅读,更多相关《linux实验报告.docx(39页珍藏版)》请在冰豆网上搜索。
linux实验报告
《Linux操作系统设计实践》
实验报告
学号:
0309888888姓名:
8***
学院:
数计学院专业:
*****
年级:
09
本组其它成员:
学号035463445姓名*****
学号035634563姓名******
学号06456456姓名****88
实验时间:
2011-2012学年第一学期
指导教师:
目录
《Linux操作系统设计实践》实验一:
进程管理-3-
《Linux操作系统设计实践》实验二:
进程通信-8-
《Linux操作系统设计实践》实验三:
综合应用-15-
一、实验内容-15-
1.1【实验目的】-15-
1.2【实验环境】RedHatEnterpriseLinux5-16-
1.3【实验内容】-16-
二、综合应用的选题及系统开发情况简介-16-
三、系统设计的背景说明及需求分析-16-
四、应用系统的功能设计-17-
4.1总体设计思想-17-
4.2服务器端设计-18-
4.2.1简单界面信息设计及演示-18-
4.2.2服务器算法设计流程图-18-
4.2.3主要数据结构设计-19-
4.2.4调试结果-19-
4.3客户端设计-19-
4.3.1主要数据结构设计-19-
4.3.2客户端算法流程图-20-
4.3.3调试结果-21-
五、程序源代码及分析-21-
六、设计的优缺点及改进方向-28-
七、实验小结-28-
《Linux操作系统设计实践》实验一:
进程管理
实验目的:
(1)加深对进程概念的理解,明确进程和程序的区别。
(2)进一步认识并发执行的实质。
(3)学习通过进程执行新的目标程序的方法。
(4)了解Linux系统中进程信号处理的基本原理。
实验环境:
RedHatEnterpriseLinux5
实验内容:
实验一进程管理
(1)进程的创建
编写一段程序,使用系统调用fork()创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:
父进程显示字符“a”:
子进程分别显示“b”和“c”。
试观察记录屏幕上显示结果,并分析原因。
#include
intmain()
{
intp1,p2;
while((p1=fork())==-1);
if(p1==0)
putchar('b');
else
{
while((p2=fork())==-1);
if(p2==0)
putchar('c');
else
putchar('a');
}
return0;
}
显示结果:
分析总共可能的结果有:
1.子进程全部创建成功:
bcabaccabcbaacbabc
2.子进程一创建失败:
b
3.子进程二创建失败:
bccb
我的虚拟机上实验结果显示:
bca
分析原因:
首先,根据fock()函数原理,fock()对于该语句之前的程序段只执行一次。
此外,fock()对于该语句返回两次值,并针对两次返回值依次执行之后的语句,一般来说fock()是先进入子程序执行代码,再执行父进程代码。
父进程与子进程的执行是相互独立的,相互之间没有任何时序上的关系。
完全由操作系统的调度程序来决定进城的执行次序、速度。
所以在没有加入进程同步机制(比如信号,信号量等)的代码的情况下,打印结果是随机出现的。
在本程序中,对于子进程p1,p2和父进程,我使用的计算机操作系统令p1==0时,打印“b”,再让p2==0,打印“c”,最后打印“a”,结果显示为:
bca
由于在单机系统下很难出现因系统资源不足导致的进程创建失败,所以后三种情况很难调试出来,但是根据fock()的实现原理,理论上是完全可能出现的。
(2)进程的控制
1.修改已编写的程序,将每个进程的输出由单个字符改为一句话,再观察程序执行是屏幕上出现的现象,并分析其原因。
#include
intmain()
{
intp1,p2;
while((p1=fork())==-1);
if(p1==0)
printf("Child1isrunning!
\n");
else
{
while((p2=fork())==-1);
if(p2==0)
printf("Child2isrunning!
\n");
else
printf("Fatherisrunning!
\n");
}
return0;
}
显示结果:
本程序是在第一题的源程序基础上直接编程字符串输出,与第一题相似,故输出结果和第一个实验现象一样,预测结果也有9种,这里就不一一例举了。
我的虚拟机上实验结果显示为:
Child1isrunning!
Child2isrunning!
Fatherisrunning!
分析原因:
本题的原理与第一小题相同,在本程序中,对于子进程p1,p2和父进程,我使用的计算机操作系统令p1==0时,打印:
“Child1isrunning!
”,再让p2==0,打印“Child2isrunning!
”,最后打印“Fatherisrunning!
”。
2.使用exec函数族使子进程执行新的目标程序。
#include
#include
intmain()
{
printf("===systemcallexecltesting===\n");
execlp("date","date",0);
printf("execerror!
\n");
return0;
}
显示结果:
我的虚拟机上实验结果显示为:
===systemcallexecltesting===
2011年10月29日星期六10:
15:
23PST
分析原因:
exec函数使子进程执行新的目标程序。
如果调用成功则执行另一个进程,与fock()最大的区别是一旦exec调用成功,就不执行原来进程后面的代码。
即不会输出“execerror!
”
(3.)编写一段程序,使其实现进程的软中断通信
[1]使用系统调用fork()创建两个子程序,再用系统调用signal()接收父进程从键盘上来的中断信号(即按Ctrl+c键);当有中断信号后,父进程用系统调用Kill()向两个子进程发出信号,子进程有信号后分别输出
ChildProcessllisKilledbyParent!
ChildProcessl2isKilledbyParent!
父进程等待两个子进程终止后,输出如下的信息后终止:
ParentprocessisKilled!
============================
#include
#include
intwait_mark;
voidwaiting()
{
while(wait_mark==1);
}
voidstop()
{
wait_mark=0;
}
intmain()
{
intp1,p2;
while((p1=fork())==-1);
if(p1==0)
{
wait_mark=1;
signal(SIGINT,SIG_IGN);
signal(16,stop);
waiting();
printf("ChildProcess11isKilledbyParent!
\n");
exit(0);
}
else
{
while((p2=fork())==-1);
if(p2==0)
{
wait_mark=1;
signal(SIGINT,SIG_IGN);
signal(17,stop);
waiting();
printf("ChildProcess12isKilledbyParent!
\n");
exit(0);
}
else
{
wait_mark=1;
signal(SIGINT,stop);
waiting();
kill(p1,16);
kill(p2,17);
wait(0);
wait(0);
printf("ParentProcessisKilled!
\n");
exit(0);
}
}
}
结果显示:
我的虚拟机上实验结果显示:
ChildProcessllisKilledbyParent!
ChildProcessl2isKilledbyParent!
ParentProcessisKilled!
分析原因:
首先对wait函数进行分析,进程一旦调用了wai,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经推出,如果让它找到已经这样一个已经阻塞的进程,wait就会收集这个子进程的信息,并把它销毁之后再返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
如果成功,wai会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1。
执行中signal函数的作用是连接,在相应条件激活时候只需连接的函数。
《Linux操作系统设计实践》实验二:
进程通信
实验目的:
进一步了解和熟悉Linux支持的多种IPC机制,包括信号,管道,消息队列,信号量,共享内存。
实验环境:
RedHatEnterpriseLinux5
实验内容:
(1)进程间命名管道通信机制的使用
使用命名管道机制编写程序实现两个进程间的发送接收信息。
可参见参考教材例6-12.
===================================================
/*ex12server.c*/
#include
#include
#include
#include
#include
#defineFIFO_FILE"MYFIFO"
intmain()
{
FILE*fp;
charreadbuf[80];
if((fp=fopen(FIFO_FILE,"r"))==NULL)
{
umask(0);
mknod(FIFO_FILE,S_IFIFO|0666,0);
}
else
fclose(fp);
while
(1)
{
if((fp=fopen(FIFO_FILE,"r"))==NULL)
{
printf("openfifofailed.\n");
exit
(1);
}
if(fgets(readbuf,80,fp)!
=NULL)
{
printf("Receivedstring:
%s\n",readbuf);
fclose(fp);
}
else
{
if(ferror(fp))
{
printf("readfifofailed.\n");
exit
(1);
}
}
}
return0;
}
==============================================
/*ex12client.c*/
#include
#include
#defineFIFO_FILE"MYFIFO"
intmain(intargc,char*argv[])
{
FILE*fp;
inti;
if(argc<=1)
{
printf("usage:
%s
exit
(1);
}
if((fp=fopen(FIFO_FILE,"w"))==NULL)
{
printf("openfifofailed.\n");
exit
(1);
}
for(i=1;i { if(fputs(argv[i],fp)==EOF) { printf("writefifoerror.\n"); exit (1); } if(fputs("",fp)==EOF) { printf("writefifoerror.\n"); exit (1); } } fclose(fp); return0; } 显示结果: 首先在一个终端窗口中运行server程序,运行成功后,程序就停留在等待接收状态,然后新建一个终端窗口,运行client程序: (我在此窗口输入Youareright! ) 这时在server窗口中会显示: Receivedstring: Youareright! 结果分析: 该结果表明server程序没有出错,基本上一直运行下去,等待接受客户进程的输入。 它首先创建一个命名管道MYFIFO,然后不停重复下面的操作: 打开,接受一行信息,输出在屏幕上,关闭。 client程序只运行一段时间就停止了,它打开命名管道,向其中写入一行信息,关闭命名管道,退出运行状态。 在 #defineS_IFIFO0010000type=namedpipe S_IFIFO值就是为了使MODE第5位置1,表示的类型是命名管道后面跟着的0666表示设置的权限不能漏,因为权限由10个位标记。 函数分析: umask该命令用来设置限制新文件权限的掩码。 当新文件被创建时,其最初的权限由文件创建掩码决定。 用户每次注册进入系统时,umask命令都被执行,并自动设置掩码改变默认值,新的权限将会把旧的覆盖 Mknod用来创建特殊文件,只能由root用户或系统组成员运行,创建FIFO(已命名管道)。 ============================================== (2)进程间消息队列通信机制的使用 使用消息队列机制自行编制有一定长度的消息(1k左右)的发送和接收程序。 参考程序段: #include #include #include #include #include #include #include #definekey1 #definebuffersize1024 intmain() { structSMSG { longmtype; charmtext[buffersize]; }msg; intpid; intp; structtimevaltpstart,tpend; floattimeuse; gettimeofday(&tpstart,NULL); while((p=fork())==-1); if(p==0) { sleep(5); pid=msgget(key,IPC_CREAT|0600); msgrcv(pid,&msg,buffersize,1,0); printf("receivemsgis: %s\n",msg.mtext); msgctl(pid,IPC_RMID,0); } else { pid=msgget(key,IPC_CREAT|0600); msg.mtype=1; strcpy(msg.mtext,"Thisisthemessagewhichtheparenthavesent! "); while((msgsnd(pid,&msg,buffersize,0))==-1); gettimeofday(&tpend,NULL); timeuse=1000000*tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec; timeuse/=1000000; printf(“UsedTime: %f\n”,timeuse); } return0; } 显示结果: UsedTime: 0.000067 receivemsgis: Thisisthemessagewhichtheparenthavesent! UsedTime: 0.000087 receivemsgis: Thisisthemessagewhichtheparenthavesent! UsedTime: 0.000075 receivemsgis: Thisisthemessagewhichtheparenthavesent! UsedTime: 0.000071 receivemsgis: Thisisthemessagewhichtheparenthavesent! 平均耗时在0.000075 结果分析: 首先程序创建一个子进程,并暂停它5秒,然后两个进程申请共享一个地址为addr的内存空间,父进程往里面写入字符串,子进程读出这个字符串,然后两个进程都同时禁止使用这块共享内存。 相比于 (2)程序来说,共享内存速度应该更快,比消息队列机制少了一步发送消息的步骤,父子进程都是直接操作同一块内存 1、消息队列创建函数分析 intmsgget(key_tkey,intflag) key: key_tftok(constchar*pathname,intproj_id) pathname: 必须是存在而且可读取的文件,proj_id: 表示序号,用来区别同时存在的文件 成功返回pathname对应的键值,也就是key,错误返回-1 flag: IPC_CREAT、IPC_EXCL、IPC_NOWAIT IPC_CREAT用于创建原来不存在的的队列,IPC_CREAT|0777,设置权限位 IPC_EXCL用于测试文件是否存在,若文件已存在则返回EEXIST,(IPC_EXCL与IPC_CREAT联合使用作为一个原子操作) IPC_NOWAIT: 不阻塞 若成功则返回消息队列的ID,若出错则返回-1 2、消息发送函数分析 intmsgsnd(intmsgid,struct msgbuf*msgp,size_tmsgsz,intmsgflg) msgid: 已打开的消息队列ID msgp: 存储要发送的消息结构体的地址 msgsz: 消息数据长度 msgflag: IPC_NOWAIT: 若消息没有立即被发送则调用进程会立即返回 0: msgsnd调用阻塞直到条件满足为止 若成功则返回0,若失败则返回-1 3、消息接受函数分析 ntmsgrcv(intmsgid,structmsgbuf*msgp,size_tmsgsz,longmsgtype,intmsgflag) msgid: 要接受消息队列的ID msgp: 存储要接收的消息结构体的地址 msgsz: 消息数据长度 msgtyoe: 消息类型,如果为0则接受第一个,如果>0则接受具有与函数msgtype相同的msgtype消息结构 (与fifo不同,可以从队列中接受自己想接受的消息)。 如果<0则接受消息队列中第一个类型值不小于msgtype绝对值且类型值又最小的消息 msgflag: IPC_NOWAIT: 若消息没有立即被接收则调用进程会立即返回 IPC_NOERROR: 若返回的消息比msgsz长度字节多,则消息会截断到与msgsz长度相等。 且不通 知消息发送进程 0: msgsnd调用阻塞直到条件满足为止 若成功则返回0,失败则返回-1 4、消息队列控制函数分析 intmsgctl(intmsgid,intcmd,structmsqid_ds*buf) msgid: 要接受消息队列的ID cmd: IPC_STAT: 取得队列状态 IPC_SET: 设置队列属性 IPC_RMID: 删除队列属性 buf: 存放队列的属性结构 (3)进程间共享存储区通信机制的使用 使用共享内存机制编制一个与上述 (2)功能相同的程序。 并比较分析与其运行的快慢。 参考程序段: #include #include #include #include #include #include #include #definebuffersize1024 #defineKey1 intmain() { intp; structtimevaltpstart,tpend; floattimeuse; gettimeofday(&tpstart,NULL); while((p=fork())==-1); if(p==0) { intpid; sleep(5); pid=shmget(Key,buffersize,IPC_CREAT|0600); char*addr; addr=(char*)shmat(pid,NULL,0); printf("receivemsgis: %s\n",addr); shmdt(addr); } else { intpid; pid=shmget(Key,buffersize,IPC_CREAT|0600); char*addr; addr=(char*)shmat(pid,NULL,0); strcpy(addr,"Thisisthemessagewhichtheparenthavesent! "); shmdt(addr); gettimeofday(&tpend,NULL); timeuse=1000000*tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 实验 报告