linux实验报告.docx

上传人:b****7 文档编号:11328988 上传时间:2023-02-27 格式:DOCX 页数:39 大小:126.59KB
下载 相关 举报
linux实验报告.docx_第1页
第1页 / 共39页
linux实验报告.docx_第2页
第2页 / 共39页
linux实验报告.docx_第3页
第3页 / 共39页
linux实验报告.docx_第4页
第4页 / 共39页
linux实验报告.docx_第5页
第5页 / 共39页
点击查看更多>>
下载资源
资源描述

linux实验报告.docx

《linux实验报告.docx》由会员分享,可在线阅读,更多相关《linux实验报告.docx(39页珍藏版)》请在冰豆网上搜索。

linux实验报告.docx

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\n",argv[0]);

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 历史学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1