OPERATING SYSTEM实验报告.docx
- 文档编号:11616369
- 上传时间:2023-03-28
- 格式:DOCX
- 页数:26
- 大小:249.82KB
OPERATING SYSTEM实验报告.docx
《OPERATING SYSTEM实验报告.docx》由会员分享,可在线阅读,更多相关《OPERATING SYSTEM实验报告.docx(26页珍藏版)》请在冰豆网上搜索。
OPERATINGSYSTEM实验报告
课程实验报告
课程名称:
操作系统原理
专业班级:
学号:
姓名:
指导教师:
报告日期:
计算机科学与技术学院
目录
1课程实验概述1
2实验一Linux线程及信号灯2
2.1实验目的与内容2
2.1.1目的与要求2
2.1.2实验内容2
2.2实验原理与方案3
2.2.1实验原理3
2.2.2实验方案5
2.3实验测试与结果8
3实验二Linux进程及同步9
3.1实验目的与内容9
3.1.1目的与要求9
3.1.2实验内容9
3.2实验原理与方案9
3.2.1实验原理9
3.2.2实验方案12
3.3实验测试与结果14
3.4实验总结14
4实验三Linux文件目录操作16
4.1实验目的与内容16
4.1.1目的与要求16
4.1.2实验内容16
4.2实验原理与方案16
4.2.1实验原理16
4.2.2实验方案19
4.3实验测试与结果22
5实验总结与评价23
1课程实验概述
计算机系统由硬件和软件两部分组成。
硬件出于计算机系统的底层;软件在硬件的外围。
硬件是计算机系统的物质基础,没有硬件就不能执行和实施最基本最简单的操作,软件也就失去了效用;而若只有硬件,没有配置相应的软件,计算机也不能发挥它的潜能,这些硬件资源也就没有活力。
硬件和软件有机地结合在一起构成了计算机系统。
在所有的软件中,有一个重要的系统软件称为操作系统。
它管理系统中的各种软、硬件资源,控制用户和应用程序的工作流程,将系统各部件有机地融合成一个整体,是计算机真正体现了系统的完整性和可利用性。
操作系统是由客观的需要而产生,随着计算机技术的发展,计算机体系结构的变化和计算机应用的日益广泛而不断地发展和完善。
它的功能由弱到强,在计算机系统中的地位也不断提高,以致成为计算机系统的核心。
因此学习并熟练掌握计算机操作系统的相关知识和基本原理是对一个计算机专业的学生的最基本也是最至关重要的要求。
为了更好的理解和掌握计算机操作系统的基本理论和相关知识,与操作系统原理课程配套设计了三个实验。
第一个实验是线程与信号灯及互斥和同步的相关知识,通过这个实验,实验者将对Linux系统下线程和信号灯的创建以及互斥和同步机制的实现有一个更加深入的理解。
第二次实验要求通过三个进程完成文件的拷贝功能,实验内容涉及进程的创建、进程之间的通讯、进程间的互斥和共享缓冲区等。
第三次实验为了让学生对Linux的文件管理及树形目录结构有一个更加直观的认识,要求学生实现一个类似于Linux内置功能的“ls-lR”功能。
三次实验分别涉及到操作系统原理中的多线程、信号灯、同步互斥、多进程以及文件管理的知识。
与课程内容相结合,由浅入深。
通过实验,既能让学生更好的消化课堂上所讲授的知识,又能增加学生的动手能力。
学以致用,让学生在实验中体会到计算机操作系统的重要以及相关设计思想的巧妙之处。
增加学生对计算机操作系统学习的兴趣,弥补课堂上被动接受知识的枯燥。
2实验一Linux线程及信号灯
2.1实验目的与内容
2.1.1目的与要求
(1)目的
了解并掌握Linux线程及信号灯
(2)要求
a)Linux线程
b)Linux信号灯
c)线程互斥
d)线程同步
2.1.2实验内容
(1)熟悉Linux线程接口
(2)熟悉Linux信号灯的编程
(3)编程模拟实现飞机售票
a)创建多个售票线程
b)使用公用全局变量保存已售票数量
c)创建互斥信号灯
d)对售票线程临界区施加P、V操作
(4)编程模拟实现双线程单缓冲区的合作
a)创建一个计算线程和一个输出线程
b)创建同步信号灯
c)缓冲区用全局公用数组变量
d)对计算线程和输出线程施加P、V操作
2.2实验原理与方案
2.2.1实验原理
(1)线程接口
a)线程创建:
创建一个新的线程。
intpthread_create__P((pthread_t*__thread,__constpthread_attr_t*__attr,
void*(*__start_routine)(void*),void*__arg));
参数:
__thread指向返回线程标识符的指针;
__attr设置线程属性;
__start_routine线程运行函数地址;
__arg运行函数的参数。
当创建线程成功时,函数返回0;否说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL:
EAGAIN表示系统限制创建新的线程,例如线程数目过多;EINVAL表示第二个参数代表的线程属性值非法。
创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。
示例:
pthread_create(&p1,NULL,subp,NULL);
b)线程等待:
等待一个线程的结束
intpthread_join__P((pthread_t__th,void**__thread_return));
__th为被等待的线程标识符
__thread_return为一个用户定义的指针,可以用来存储被等待线程的返回值。
这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。
示例:
pthread_join(p1,NULL);
c)线程撤销:
结束当前线程
voidpthread_exit__P((void*__retval))__attribute__((__noreturn__));
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。
(2)信号灯
a)创建信号灯集
intsemget(key_tkey,intnsems,intsemflg);
key是一个关键字,为IPC_PRIVATE时表示由系统选用一个关键字;
nsems创建的信号灯个数,编号为0到nsems-1;
semflg创建的权限标志,如IPC_CREAT|0666;/*IPC_CREAT表示不存在则创建*/
执行成功时返回信号灯的ID,否则返回-1。
b)信号灯控制
intsemctl(intsemid,intsemnum,intcmd,unionsemunarg);
semid是要操作的信号灯集ID;
semnum是信号灯在信号灯集中的编号;
cmd是操作的命令,常用操作有SETVAL(设置信号量的值)和IPC_RMID(删除信号灯);
arg给cmd的参数:
arg.val=1;
res=semctl(semid,0,SETVAL,arg);
semctl(semid,0,IPC_RMID,0)
c)信号灯操作
intsemop(intsemid,structsembuf*spos,intnspos);
semid是要操作的信号灯集ID;
spos操作数组,
nspos表明数组的个数。
structsembuf{
shortsem_num;/*信号灯编号*/
shortsem_op;/*进行什么操作*/
shortsem_flg;/*操作的标志,置为0;*/
/*IPC_NOWAIT:
不挂起;SEM_UNDO:
退出还原*/
};
sem_op>0:
将sem_op加入到信号灯的值中,并唤醒等待信号灯增加的进程;sem_op=0:
当信号灯的值是0的时候,函数返回,否则阻塞直到信号灯的值为0;sem_op<0:
函数判断信号灯的值加上这个负值,结果0唤醒等待信号灯为0的进程,如果小于0函数阻塞,如果大于0,那么从信号灯里面减去这个值并返回。
对应信号灯P操作实现:
voidP(intsemid,intsemno)
{
structsembufsop;
sop.sem_num=semno;
sop.sem_op=-1;
sop.sem_flg=0;
semop(semid,&sop,1);
}
对应信号灯V操作实现:
voidV(intsemid,intsemno)
{
structsembufsop;
sop.sem_num=semno;
sop.sem_op=1;
sop.sem_flg=0;
semop(semid,&sop,1);
}
2.2.2实验方案
(1)三线程卖票实验设计方案
本实验模拟实际生活中的多柜台卖票的实例。
本实验程序中创建pthread1、pthread2和pthread3三个卖票线程模拟三个卖票窗口。
用全局常量total表示总共有多少张票要卖,这里设置为30张。
用全局变量sold表示已经卖的票数,设置初始值为0,这也是三个买票线程的临界资源。
表2.1给出了程序中的变量和函数清单。
表2.1买票程序变量和函数清单
变量或函数
说明
ints
信号灯集的ID
intsold=0
已卖票数,三个线程的临界资源
constinttotal=30
票的总数目,此处设置为30张票
pthread1、pthread2、pthread3
三个售票线程
P、V
信号灯的P、V操作
主线程函数源代码如下。
intmain(void)
{
pthread_tid[3];
intret;//线程创建状态值
s=semget(IPC_PRIVATE,1,IPC_CREAT|0666);
if(s==-1){
printf("创建信号灯失败!
\n");
exit
(1);
}
unionsemunarg;
arg.val=1;
semctl(s,0,SETVAL,arg);
//创建线程
ret=pthread_create(&id[0],NULL,(void*)thread1,NULL);
if(ret!
=0){
printf("Createpthreaderror!
\n");
exit
(1);
}
ret=pthread_create(&id[1],NULL,(void*)thread2,NULL);
if(ret!
=0){
printf("Createpthreaderror!
\n");
exit
(1);
}
ret=pthread_create(&id[2],NULL,(void*)thread3,NULL);
if(ret!
=0){
printf("Createpthreaderror!
\n");
exit
(1);
}
pthread_join(id[0],NULL);
pthread_join(id[1],NULL);
pthread_join(id[2],NULL);
semctl(s,0,IPC_RMID,0);
return(0);
}
卖票线程函数源代码如下。
voidthread1()
{
while(sold { P(s,0); if(sold { sold=sold+1; printf("线程1卖出票no.%d\n",sold); } V(s,0); } return; } 由于三个卖票线程基本相同,此处只列取pthread1。 其实,可以通过线程传参来实现卖票线程的复用。 但由于对pthread_create函数的这种特殊的传参方式不太了解,所以只能简单的用三个pthread函数来实现不同的线程。 这也是本实验有待改进的地方。 从主线程中可以看出,创建了三个卖票线程,并让主线程等待三个子线程运行完毕之后才会结束。 三个线程并发运行。 从子线程pthread1中可以看出,对临界区加上了P、V操作,以解决三个线程对临界资源sold操作的冲突问题。 此处只需要一个信号灯即可实现三个线程之间的同步。 另外,注意到在pthread1函数中while(sold 看起来好像重复,但其实在P、V操作之间加这个if条件判断语句是十分必要的。 比如sold为29时,pthread1、pthread2和pthread3三个线程的while(sold 当然,这时如果只有两个线程进入while循环,将卖31张票,多卖1张。 也即是说,这将导致所卖的票数可能多出1张或2张,而且这种结果随着线程抢占资源的不同而不同,是完全随机的,这是我们不希望看到的结果。 所以,我们需要在P、V操作中间加上if(sold (2)计算、输出双线程操作同一缓冲区实验设计方案 本实验实现两个不同的线程共享同一个缓冲区,故缓冲区是临界资源,因此需要用信号灯及其P、V操作实现线程之间的同步。 缓冲区分满和空两种状态,因此需要两个信号灯,一个表示缓冲区满、一个表示缓冲区空。 程序关键部分源代码如下 voidcompute() {//计算线程 while(count--) { P(s,0);//空缓冲区信号灯 inti; for(i=0;i buffer[i]=count*(i+1); V(s,1); } } voidoutput() {//输出线程 while(count){ P(s,1);//满缓冲区信号灯 inti; for(i=0;i printf("%4d",buffer[i]); printf("\n"); V(s,0);//释放空缓冲区 } } 2.3实验测试与结果 (1)卖票线程输出结果截图见下图2.1 图2.1卖票线程运行结果截图 从图中可以看出,票的顺序是从小到大,而卖票的线程是随机的。 图2.1中线程1、2、3交替出现,说明linux分配资源的策略有一定的公平性。 每次运行会出现不同的结果,这也说明linux分配资源的随机性。 (2)计算输出线程输出结果截图见下图2.2 图2.2计算输出共享缓冲区程序运行结果截图 由2.2.2实验方案中的代码可以看出,程序先计算count*(i+1),然后存放在缓冲区数组BUF[i]中,i从0自增到BUF_SIZE-1,每执行compute线程一次,全局变量count--,然后输出线程将BUF数组中的结果输出。 从图2.2可以看出,实现了双线程对同一缓冲区的互斥操作。 3实验二Linux进程及同步 3.1实验目的与内容 3.1.1目的与要求 (1)目的 了解并掌握Linux进程及同步。 (2)要求 了解Linux进程与信号灯的使用: a)Linux进程控制 b)Linux信号灯 c)Linux共享内存 d)进程互斥/同步 3.1.2实验内容 (1)熟悉Linux进程接口; (2)了解Linux信号灯的编程; (3)了解Linux共享内存的使用; (4)编程模拟实现誊抄; a)创建三个誊抄进程; b)基于共享内存建立缓冲区; c)创建同步信号灯; d)对各誊抄进程施加P、V操作。 3.2实验原理与方案 3.2.1实验原理 (1)Linux进程基本接口 a)进程创建 新进程是调用fork()父进程的副本,称为子进程。 子进程继承了父进程的许多特性,具有与父进程完全相同的用户级上下文,父进程与子进程并发执行。 接口: intfork() >0: 父进程返回,子进程的PID; =0: 子进程返回; -1: 创建失败。 b)加载程序 exec()系列可以将一个可执行的二进制文件覆盖在进程的用户级上下文的存储空间上,即把一个新程序装入内存,来改变调用进程的执行代码。 如果exec()调用成功,进程从新程序的入口开始执行。 exec()系列系统调用在unistd.h中,共有execl、execlp、execle、execv、execvp五个,其基本功能相同,只是以不同的方式来给出参数。 c)等待子进程结束 如果子进程没有完成,父进程一直等待。 wait()将调用进程挂起,直至其子进程因暂停或终止而发来软中断信号为止。 如果在wait()前已有子进程暂停或终止,则调用进程做适当处理后便返回。 intwait(status) int*status; 其中,status是用户空间的地址。 它的低8位反应子进程状态,为0表示子进程正常结束,非0则表示出现了各种各样的问题;高8位则带回了exit()的返回值。 exit()返回值由系统给出。 d)进程终止 系统调用格式: voidexit(status) intstatus; 其中,status是返回给父进程的一个整数,以备查询。 为了及时回收进程所占用的资源并减少父进程的干预,UNIX/LINUX利用exit()来实现进程的自我终止,exit(0)表示进程正常终止,exit (1)表示进程运行有错,异常终止。 如果调用进程在执行exit()时,其父进程正在等待它的终止,则父进程可立即得到其返回的整数。 (2)Linux共享内存 共享存储区是UNIX系统中通信速度最高的一种通信机制。 该机制可使若干进程共享主存中的某一个区域,且使该区域出现(映射)在多个进程的虚地址空间中。 共享存储区机制只为进程提供了用于实现通信的共享存储区和对共享存储区进行操作的手段,当用户需要使用该机制时,必须自己设置同步和互斥措施才能保证实现正确的通信。 (3)文件操作 a)文件打开操作 open函数用于打开和创建文件。 格式: #include intopen(constchar*pathname,intoflag,...); 返回值: 成功则返回文件描述符,否则返回-1。 pathname: 待打开/创建文件的路径名(如/hust/get.c) oflag: 用于指定文件的打开/创建模式 O_CREAT、O_APPEND、O_EXCL…… O_RDONLY 、O_WRONLY、O_RDWR 第三个参数在创建新文件时指定访问权限位。 例1: fd=open("./get.c",O_RDONLY); 例2: fd=open("./test1.c",O_CREAT|O_WRONLY); b)文件读取操作 read函数用于从已打开的文件中读取数据。 格式: #include ssize_tread(intfd,void*buf,size_tcount); 返回值: 若读取成功,则返回读出的字节数;若遇到EOF,则返回0;若遇到错误,则返回-1。 fd: 待读取文件的文件描述符(即open返回的值); buf: 存放所读取到的数据的内存缓冲区; count: 需要读取的字节数。 例1: num=read(fd,buf1,10); c)文件写操作 write函数用于向已打开的文件中写入数据。 格式: #include ssize_twrite(intfd,void*buf,size_tcount); 返回值: 若写入成功,则返回实际写入的字节数;若遇到错误,则返回-1。 fd: 待写入文件的文件描述符(即open返回的值); buf: 存放需写入的数据的内存缓冲区; count: 需要写入的字节数。 例1: num=write(fd,buf1,10); 3.2.2实验方案 该实验由main、get、copy和put三个可执行程序,通过两个共享缓冲区S、T来实现文件的誊抄。 设置一个含有四个信号灯的信号灯集s来实现进程之间的同步。 当S缓冲区为空的时候,get进程从指定的源文件总读取数据到S缓冲区,并释放一个S满的信号灯。 当S满且T空时,copy进程将S缓冲区的内容拷贝到T缓冲区中,并释放一个S空的信号和一个T满的信号灯。 当T满,put进程将T中的数据放到目的文件中,并释放一个T空的信号灯。 各变量以及程序清单见表3.1。 main 初始化信号灯、缓冲区,创建三个子进程,等待子进程运行结束后做善后处理;主进程。 get 读源文件,送入缓冲区S;子进程。 copy 从S复制信息到T;子进程。 put 将T中信息写入目标文件;子进程。 ints 含有四个信号灯的信号灯集,信号灯0、1、2、3分别表示S空、S满、T空、T满 intS_shmid S缓冲区id intT_shmid T缓冲区id BUF_SIZE10 缓冲区大小,此处设置为10 mycreate() 创建信号灯、缓冲区的函数 mydelet() 删除信号灯、缓冲区的函数 init_sem() 初始化信号灯函数 main进程程序结构如下: voidmain(intargc,char*argv[]) {mycreat();//创建缓冲区、信号灯集 init_sem();//初始化信号灯集 if((fork())==0){//get进程 execv("./get",argv); }elseif((fork())==0){//copy进程 execv("./copy",argv); }elseif((fork()==0)){//put进程 execv("./put",argv); } wait(0);wait(0);wait(0);//等待子进程结束 mydelet();//删除信号灯、缓冲区 } get进程程序代码如下: intmain(intargc,char*argv[]) { mycreat(); intfd=open(argv[1],O_RDWR);//打开指定文件 intnum=0; while(fd>0) { P(s,0);//S缓冲区是否为空? puts("get1"); num=read(fd,S_addr,BUF_SIZE); printf("%d\n",num); if(num S_addr[num]=0;//设置进程结束标志,以进程进程间通信 V(s,1);//释放S满信号灯 if(num } return0; } copy进程程序代码如下 int
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OPERATING SYSTEM实验报告 SYSTEM 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)