福大操作系统实验.doc

上传人:laozhun 文档编号:2888621 上传时间:2023-03-01 格式:DOC 页数:26 大小:905.50KB
返回 下载 相关 举报
福大操作系统实验.doc_第1页
第1页 / 共26页
福大操作系统实验.doc_第2页
第2页 / 共26页
福大操作系统实验.doc_第3页
第3页 / 共26页
福大操作系统实验.doc_第4页
第4页 / 共26页
福大操作系统实验.doc_第5页
第5页 / 共26页
点击查看更多>>
资源描述

《福大操作系统实验.doc》由会员分享,可在线阅读,更多相关《福大操作系统实验.doc(26页珍藏版)》请在三一办公上搜索。

1、 计算机操作系统设计实践实验报告学号: 姓名: 学院: 专业: 计算机 年级: 班级: 实验时间:年第一学期指导教师:黄目录计算机操作系统实验一2【实验名称】:2【实验目的】:2【实验原理】:2一、预计结果:2二、实验代码:2三、关键代码分析:2四、实际结果:2五、实验结果分析2计算机操作系统实验二2【实验名称】:2【实验目的】:2【实验原理】:2一、背景知识:2二、设计方案2三、实验代码2四、关键代码分析:2五、实验结果:2六、实验结果分析:2七、对比分析:2计算机操作系统实验三2【实验名称】:2【实验目的】:2【实验原理】:2一、背景知识2二、实验方案(如图):2三、预计实验结果:2四、关

2、键代码:2五、实验代码分析2六、调试过程2七、实验结果:2八、实验结果分析:2计算机操作系统实验一【实验名称】:并发程序设计【实验目的】:掌握在程序中创建新进程的方法, 观察并理解多道程序并发执行的现象。【实验原理】:fork():建立子进程。子进程得到父进程地址空间的一个复制。返回值:成功时,该函数被调用一次,但返回两次,fork()对子进程返回0,对父进程返回子进程标识符(非0值)。不成功时对父进程返回-1,没有子进程。一、预计结果:353535555535553535553535535355535355出现出现出现出现二、实验代码:#include#includevoid main (v

3、oid) int x=5;/* fork调用,创建了一个新的进程, 这个进程共享父进程的数据和堆栈空间等,这之后的代码指令为子进程创建了一个拷贝。 fock 调用是一个复制进程, fock调用后,新进程的入口就在 fock的下一条语句。*/ if( fork( ) )/fork()返回给子进程0,给父进程为子进程的pid x+=30;/父进程执行到,x=35 printf(%dn,x);/输出35 else printf(%dn,x);/子进程执行到,输出5/父进程,子进程都输出,不过输出的是自己空间里的x,父进程35,子进程5 printf(%dn,x); 三、关键代码分析:Linux下一个

4、进程在内存里有三部分的数据,就是代码段、堆栈段和数据段。代码段,顾名思义,就是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用相同的代码段。堆栈段存放的就是子程序的返回地址、子程序的参数以及程序的局部变量。而数据段则存放程序的全局变量,常数以及动态数据分配的数据空间(比如用malloc之类的函数取得的空间)。系统如果同时运行数个相同的程序,它们之间就不能使用同一个堆栈段和数据段。仔细分析后,我们就可以知道:一个程序一旦调用fork函数,系统就为一个新的进程准备了前述三个段,首先,系统让新的进程与旧的进程使用同一个代码段,因为它们的程序还是相同的,对于数据段和堆栈

5、段,系统则复制一份给新的进程,这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始运行,虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不再共享任何数据了。fork()不仅创建出与父进程代码相同的子进程,而且父进程在fork执行点的所有上下文场景也被自动复制到子进程中,包括:全局和局部变量打开的文件句柄共享内存、消息等同步对象由进程见并行执行,故父子进程间的输出是乱序的。在经过上百次的实验下,并没有发现全部的预计结果。四、实际结果:五、实验结果分析 现在操作系统在设计时大多都应用了轮转调度算法,也就是说,进程按分配到是时间片执行,当一个进程

6、执行的时间片到了,即使该进程还未执行完就要被挂起,去执行另一个进程。在父进程或子进程执行当中,如果时间片到,则会中断,去执行另一个进程,造成输出结果的交叉。因此就出现了父子进程结果的交叉。 在linux系统中,fork函数创建子进程所需的资源一般是足够的,因此对于子进程创建不成功的情况基本上是不会出现的,而且由于本题的程序耗时很短,因此时间片对于每一个进程也是绝对够用的,因此父子进程结果交叉出现的可能性是比较小的。 计算机操作系统实验二【实验名称】:进程通信(实验2) 【实验目的】:掌握用邮箱方式进行进程通信的方法,并通过设计实现简单邮箱理解进程通信中的同步问题以及解决该问题的方法。【实验原理

7、】:邮箱机制类似于日常使用的信箱。对于用户而言使用起来比较方便,用户只需使用send()向对方邮箱发邮件 receive()从自己邮箱取邮件, send()和 receive()的内部操作用户无需关心。因为邮箱在内存中实现,其空间有大小限制。其实send()和 receive()的内部实现主要还是要解决生产者与消费者问题。进程A进程B信箱A信箱BSend()Send()receive()receive()【实验内容】:进程通信的邮箱方式由操作系统提供形如send()和receive()的系统调用来支持,本实验要求学生首先查找资料了解所选用操作系统平台上用于进程通信的系统调用具体形式,然后使用该

8、系统调用编写程序进行进程间的通信,要求程序运行结果可以直观地体现在界面上。在此基础上查找所选用操作系统平台上支持信号量机制的系统调用具体形式,运用生产者与消费者模型设计实现一个简单的信箱,该信箱需要有创建、发信、收信、撤销等函数,至少能够支持两个进程互相交换信息,比较自己实现的信箱与操作系统本身提供的信箱,分析两者之间存在的异同。一、背景知识:1、信号量机制信号量主要用来控制多个进程对共享资源的访问。当一个进程要访问某个共享资源时,按下列步骤进行:(1) 检测控制这个资源的信号量的值。(2) 如果信号量的值时正数,就可以使用这个资源。进程将信号量的值减一,表示它正在使用资源的某个小单元。(3)

9、 如果信号量的值为零,那么这个进程进入睡眠状态,直到信号量的值重新大于零时被唤醒,转入第一步操作。2、共享内存机制共享内存是允许多个进程共享一块内存,由此来达到交换信息的进程通信机制。共享内存机制是最快的一种进程通信机制。共享内存需要一定的同步机制控制多个进程对同一块内存的读写。当一个进程在写数据时,不允许其他的进程写数据或读数据,这可以通过信号量控制实现。二、设计方案Send共享内存Receive 综合信号量和共享内存机制,用信号量来控制多个进程对共享内存的读写操作,一次只能读写一次。 信号量S1=1,S2=0; Send Receive A: B: P(S1) P(S2) 发送数据或删除数

10、据 读取数据 V(S2) V(S1) GOTO A GOTO B三、实验代码1、系统调用实现邮箱通信程序代码A:#include#include#include#include#include#include#define MSGKEY1 100#define MSGKEY2200typedef struct msgformlong mtype;char mtxt100;msg;/消息结构int main(int agrc,char *argv)msg amsg;int pid,*pint,msgqid1,msgqid2;int cmd,msglen,msgtype;/创建消息队列1用于发送消

11、息给B,或者获得qidmsgqid1 = msgget(MSGKEY1,IPC_CREAT|0666);if(msgqid1 = -1)printf(errorn);return 0;/创建消息队列2用于接收B消息,或者获得qidmsgqid2 = msgget(MSGKEY2,IPC_CREAT|0666);if(msgqid2 = -1)printf(errorn);return 0;while(1)/输入操作命令1代表发送消息,2代表接收消息printf(please input cmd(send = 1,receive = 2)n);scanf(%d,&cmd);if(cmd = 1)

12、/发送消息printf(please input message type:n);scanf(%d,&amsg.mtype);/输入消息类型getchar();printf(please input message:n);scanf(%s,amsg.mtxt);/输入消息msglen = strlen(amsg.mtxt);msgsnd(msgqid1,&amsg,msglen,0);/发送消息if(cmd = 2)/接收消息memset(&amsg,0,sizeof(msg);printf(please input message type:n);scanf(%d,&msgtype);/输入

13、消息类型if(msgrcv(msgqid2,&amsg,100,msgtype,IPC_NOWAIT)= -1)/接收消息printf(msgrcv failed!n);elseprintf(Receive a message from B:ntype: %dn%sn,msgtype,amsg.mtxt);if(cmd = 3)/结束通信,销毁消息队列msgctl(msgqid1,IPC_RMID,0);msgctl(msgqid2,IPC_RMID,0);break;return 0;程序代码B:#include#include#include#include#include#include

14、#define MSGKEY1 100#define MSGKEY2200typedef struct msgformlong mtype;char mtxt100;msg;int main(int argc,char *argv)msg bmsg;int pid,*pint,msgqid1,msgqid2;int cmd,msglen,msgtype;/创建消息队列1用于接收消息,或者获得qidmsgqid1 = msgget(MSGKEY1,IPC_CREAT|0666);if(msgqid1 = -1)printf(error);return 0;/创建消息队列2用于发送消息给A,或者获

15、得qidmsgqid2 = msgget(MSGKEY2,IPC_CREAT|0666);if(msgqid2 = -1)printf(error);return 0;while(1)/输入命令,1代表发送消息,2代表接收printf(please input cmd(send = 1,receive = 2)n);scanf(%d,&cmd);if(cmd = 1) /发送消息printf(please input message type:n);scanf(%d,&bmsg.mtype);/输入消息类型printf(please input message:n);scanf(%s,bmsg

16、.mtxt);/输入消息msglen = strlen(bmsg.mtxt);msgsnd(msgqid2,&bmsg,msglen,0);if(cmd = 2) /接收消息memset(&bmsg,0,sizeof(msg);printf(please input message type:n);scanf(%d,&msgtype);/输入接收的消息类型if(msgrcv(msgqid1,&bmsg,100,msgtype,IPC_NOWAIT) = -1)printf(msgrcv failed!n);elseprintf(Receive the message from A:ntype:

17、 %dn%sn,msgtype,bmsg.mtxt);if(cmd = 3)/命令3销毁队列msgctl(msgqid1,IPC_RMID,0);msgctl(msgqid2,IPC_RMID,0);break;return 0; 2、验证系统调用消息队列实现的邮箱通信A:发送消息B:接收消息B:尝试接收已接收的消息失败:B:连续发送消息A:连续接收消息(逆序接收)删除消息队列-结果:3、自己实现邮箱通信:文件a.c,定义信号量调用结构及信号量操作函数的系统调用形式:#include#include#include#include#include#include#include#define

18、shmsz 256union semun/信号量固定结构 int val; struct semid_ds *buf; unsigned short *array;void init_a_semaphore(int sid,int semnum,int initval) /信号量初始化函数 union semun semopts; semopts.val=initval; semctl(sid,semnum,SETVAL,semopts);/信号量操作函数int semaphore_p(int sem_id)/p操作的封装 struct sembuf sb; sb.sem_num=0; sb.

19、sem_op=-1; sb.sem_flg=SEM_UNDO; if(semop(sem_id,&sb,1)=-1) printf(semaphore_p failed.n); return 0; return 1;int semaphore_v(int sem_id)/v操作的封装 struct sembuf sb; sb.sem_num=0; sb.sem_op=1; sb.sem_flg=SEM_UNDO; if(semop(sem_id,&sb,1)=-1) printf(semaphore_v failed.n); return 0; return 1;文件r.c:读取消息的程序#i

20、nclude a.cint main() char *shm; int shmid; int producer,consumer,i; if(consumer=semget(key_t)1234,1,IPC_CREAT|0660)=-1)/创建或者获取信号量id printf(semget failed.n); exit(1); init_a_semaphore(consumer,0,1);/初始信号量 if(producer=semget(key_t)2345,1,IPC_CREAT|0660)=-1) printf(semget failed.n); exit(1); init_a_sem

21、aphore(producer,0,0); if(shmid=shmget(1,shmsz,0660|IPC_CREAT)=-1)/创建或者获取共享内存id printf(shmget failed.n); exit(1); shm=(char *)shmat(shmid,0,0);/将共享内存映射到自己进程空间for(i=0;i+) printf(Please select R(read) or E(end)n); char s=getchar(); getchar(); if(s=R) semaphore_p(producer);/p操作,让其他进程无法操作给内存 printf(Data

22、receiverd:%sn,shm);/读取消息 sleep(1); semaphore_v(consumer);/v操作,释放给内存操作权限 else if(s=E)break; semctl(producer,0,IPC_RMID,0); semctl(consumer,0,IPC_RMID,0);文件w:发送消息到共享内存#include a.cint main() char *shm,*s; int shmid; int producer,consumer,i; char readbufshmsz; if(consumer=semget(key_t)1234,1,IPC_CREAT|0

23、660)=-1) /创建或者获取信号量id printf(semget failed.n); exit(1); init_a_semaphore(consumer,0,1); if(producer=semget(key_t)2345,1,IPC_CREAT|0660)=-1) printf(semget failed.n); exit(1); init_a_semaphore(producer,0,0); if(shmid=shmget(1,shmsz,0660|IPC_CREAT)=-1)/创建或者获取共享内存id printf(shmget failed.n); exit(1); shm

24、=(char *)shmat(shmid,0,0);/映射到自己进程空间 for(i=0;i+) char s; printf(Please Select D(delet) or S(send) or E(end)n); s=getchar(); getchar(); if(s=S) /发送消息 printf(Enter text:); fgets(readbuf,shmsz,stdin); semaphore_p(consumer); sprintf(shm,Message %4d from producer %d is%sn,i,getpid(),readbuf); semaphore_v

25、(producer); else if(s=E) break; else if(s=D) semaphore_p(consumer); sprintf(shm,NO message); semaphore_v(producer); return 0;四、关键代码分析: 1、信号量实现: 创建或打开信号量集的系统函数原型: int semget(key_t key, int nsems, int flag) key相当于是一个信号量集的标识符,nsems是信号量集中创建的信号量的数量,flag设置为IPC_CREAT,执行创建或打开操作。 调用成功返回信号量集合标识符,否则返回-1。 2、信号量

26、操作: int semop(int semid,struct sembuf *sops,size_t nops) semid为信号集的标识符;sops为sembuf结构的数组,nops为数组中元素的个数。sembuf结构中记录了对信号集的一个操作。P/V原语的操作主要是用到这个函数。 3、信号量控制: int semctl(int semid,int semnum,int cmd,union semnun arg) semid为信号量集合的标识;semnum信号集中某个信号的编号;cmd给出操作命令,可取值如SETVAL(设置信号量的值),IPC_RMID(删除指定的信号量集合)。 4、共享内

27、存的创建与打开 int shmget(key_t key,int size,int flag) 函数shmget除可用于创建一个新的共享内存外,也可用于打开一个已存在的共享内存。参数key表示所创建或打开的共享内存的关键字,参数size表示共享内存的大小。参数flag表示调用函数的操作类型,也可用于设置共享内存的访问权限。 5、共享内存的操作 当一个共享内存创建或打开后,某个进程如果要使用它则必须将此共享内存区域附加到它的地址空间。 void *shmat(int shmid,void *addr,int flag); 参数shimid表示要附加的共享内存段的引用标识符。参数flag用于表示s

28、hmat函数的操作方式。如果flag设置了SHM_RDONLY位,该内存区域被设置为只读,否则设置为可读写。参数addr和flag共同决定共享内存区域要附加到的地址值。 一般addr取0,系统自动查找进程地址空间。五、实验结果:(最后一次读操作被挂起,等待数据)发送方: 接收方: (写操作被挂起,等待接收进程读数据) 发送方: 接收方: 六、实验结果分析: 运行发送进程和接收进程,发送方在一个循环中运行,如果选择发送数据,则它首先强制对信号量S1执行P操作,以等待共享存储区域是空闲的(发送方第三次要写入数据时,因为接收方没有接收第二次的数据,所以此时发送方被挂起),当P操作完成时,它往共享内存

29、写入数据。一旦数据写完后,就对S2执行V操作,告诉接收方在共享内存中有待处理的数据。接收方也在一个循环中运行,每一次循环读取一次数据。首先对信号量S2执行P操作,等待数据写入共享内存中(接收进程的最后一次输入“R”,因为没有新的数据,所以进程被挂起等待),一旦共享内存中有数据后,就将其读取显示。然后对S1执行V操作,告诉发送方数据已被处理,此时可以进行下次的数据写入操作。七、对比分析:使用系统调用消息队列实现的邮箱通信,支持随时读取消息,写入消息。内部实现全部由系统封装完成,用户无需关系具体过程。只需按消息队列规则使用即可。由共享内存实现邮箱通信,要自己调用PV原语实现互斥与通信机制。写入与读

30、出都要进行原语操作保证不会出现同时对一个内存操作,导致错误。计算机操作系统实验三【实验名称】:文件系统的构建(实验3) 【实验目的】:掌握磁盘的工作原理和操作系统进行文件管理的原理【实验原理】:硬盘的MBR:MBR(Main Boot Record),按其字面上的理解即为主引导记录区,位于整个硬盘的0磁道0柱面1扇区。在总共512字节的主引导扇区中,MBR只占用了其中的446个字节(偏移0000-偏移01BD),另外的64个字节(偏移01BE-偏移01FD)交给了DPT(Disk Partition Table硬盘分区表),最后两个字节55,AA(偏移01FE- 偏移01FF)是分区的结束标志

31、。这个整体构成了硬盘的主引导扇区。大致的结构如图所示:硬盘依据分区表中的信息把硬盘划分为最多四个分区(对于扩展分区,可进一步划分为多个逻辑分区)。U盘采用类似的方法划分分区。每个分区或软盘上可建立独立的文件系统。下图是FAT文件系统空间分布结构。引导扇区FAT1FAT2根目录区文件数据区 【实验内容】:在掌握磁盘的工作原理和操作系统进行文件管理原理的基础上,自行设计实现在磁盘上建立文件系统的软件,该软件应该具有与Format类似的功能,至少支持一种文件系统格式,如FAT、NTFS或EXT2,至少能够对一种媒体进行格式化,如软盘,U盘或硬盘(不得在实验室的机器上进行硬盘格式化的实验)等。不能直接

32、调用操作系统提供的格式化工具或类似SHFormatDrive()的高层系统函数实现该软件。在Windows环境可使用biosdisk()函数完成底层盘操作,在Linux环境上可参考format的源代码。比较自己设计实现的软件与FORMAT,分析存在什么异同。 一、背景知识使用“DOC分区”体系时,磁盘的第一个也就是0号扇区被称为主引导记录扇区,也称为主引导记录MBR(Master Boot recorder,MBR)。 1、MBR数据结构 MBR由446个字节的引导代码、64字节的主分区(4个)表及两个字节的“55 AA”是分区的结束标志。FAT文件系统的整体布局2、说明【1】 保留区含有一个

33、重要的数据结构系统引导扇区(DBR)。FAT12、FAT16的保留区通常只有一个扇区,而FAT32的保留扇区要多一些,除0号扇区外,还有其他一些扇区,其中包括了DBR的备份扇区。 【2】 FAT区由来年各个大小相等的FAT表组成FAT1、FAT2,FAT2紧跟在FAT1之后。 【3】 FAT12、FAT16的根目录虽然也属于数据区,但是他们并不由簇进行管理。也就是说FAT12、FAT16的根目录是没有簇号的,他们的2号簇从根目录之后开始。而FAT32的根目录通常位于2号簇。 3、典型的FAT32_DBR【1】0x000x02:3个字节,跳转指令。 【2】0x030x0A:8个字节,文件系统标志

34、和版本号,这里为MSDOC5.0。 【3】0x0B0x0C:2个字节,每扇区字节数,512(0X02 00)。 【4】0x0D0x0D:1个字节,每簇扇区数,8(0x08)。 【5】0x0E0x0F:2个字节,保留扇区数,704(0x02 C0)。 【6】0x100x10:1个字节,FAT表个数,2。 【7】0x110x12:2个字节,根目录最多可容纳的目录项数,FAT12/16通常为512。FAT32不使用此处值,置0。 【8】0x130x14:2个字节,扇区总数,小于32MB时使用该处存放。超过32MB时使用偏移0x200x23字节处的4字节存放。笔者的SD卡容量为2GB,所以不使用该处,

35、置0. 【9】0x150x15:1个字节,介质描述符,0xF8表示本地硬盘。 【10】0x160x17:2个字节,每个FAT表的大小扇区数(FAT12/16使用,FAT32不使用此处,置0)。 【11】0x180x19:2个字节,每磁道扇区数,63(0x00 3F)。 【12】0x1A0x1B:2个字节磁头数,255(0x00 FF)。 【13】0x1C0x1F:4个字节,分区前已使用扇区数,137(0x00 00 00 89)【14】0x200x23:4个字节,文件系统大小扇区数,3841911(0x 00 3A 9F 77)。 【15】0x240x27:4个字节,每个FAT表的大小扇区数,

36、3744(0x 00 00 0E A0)。 【16】0x280x29:2个字节,标记。 【17】0x2A0x2B:2个字节,版本号。 【18】0x2C0x2F:4个字节,根目录簇号,2。(虽然在FAT32文件系统下,根目录可以存放在数据区的任何位置,但是通常情况下还是起始于2号簇) 【19】0x300x31:2个字节,FSINFO(文件系统信息扇区)扇区号,1。(上图的标注即用黄色条纹的标注有误,请读者注意)该扇区为操作系统提供关于空簇总数及下一可用簇的信息。 【20】0x320x33:2个字节,备份引导扇区的位置,6。(上图的标注即用黄色条纹的标注有误,请读者注意)备份引导扇区总是位于文件系

37、统的6号扇区。 【21】0x340x3F:12个字节,未使用。 【22】0x400x40:1个字节,BIOS INT 13H 设备号,0x80。(这个我也不知道什么意思) 【23】0x410x41:1个字节,未用。 【24】0x420x42:1个字节,扩展引导标志。0x29。 【25】0x430x46:1个字节,卷序列号。通常为一个随机值。 【26】0x470x51:11个字节,卷标(ASCII码),如果建立文件系统的时候指定了卷标,会保存在此。笔者当时没有指定卷表,上图中的YCY是后来指定的。 【27】0x520x59:8个字节,文件系统格式的ASCII码,FAT32。 【28】 0x5A0

38、x1FD:410个字节,未使用。该部分没有明确的用途。二、实验方案(如图):三、预计实验结果:四、关键代码:读取FAT32 MBR 保存到tmp.txt#include #include #include #include int main()int fd;char mbr512;FILE *fp;char tmp20;printf(input:n);scanf(%s,tmp);fd=open(tmp,O_RDWR);/打开驱动器read(fd,mbr,sizeof(mbr);fp = fopen(tmp.txt,w);fwrite(mbr,sizeof(mbr),1,fp);写入更改后的MB

39、R,并清空分区表及文件分配表#include #include #include #include /DBR结构typedef struct FAT32_DBR char BS_jmpBoot3; /跳转指令 char BS_OEMName8; /操作系统的名称和版本号 char BPB_BytesPerSec2;/每扇区字节数 char BPB_SecPerClus1; /每簇扇区数 char BPB_RsvdSecCnt2; /保留扇区数目 char BPB_NumFATs1; /此卷中FAT表数 char BPB_RootEntCnt2; /FAT32为0 char BPB_TotSec162; /FAT32为0 char BPB_Media1; /存储介质

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

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号