北京邮电大学操作系统实验 (2)
TEC—4计算机组成原理实验系统

计算机组成原理实验指导(学生用书)天津城建学院计算机系2003年9月第一节 TEC—4计算机组成原理实验系统TEC—4计算机组成原理实验系统由北京邮电大学计算机学院、清华同方教学仪器设备公司、深圳拓普威电子技术有限公司联合研制。
它是一个8位计算机模型实验系统,可用于大专、本科、硕士研究生计算机组成原理课程、计算机系统结构课程的教学实验,对提高学生的动手能力、提高学生对计算机整体和各组成部分的理解、提高学生的计算机系统综合设计能力都会有很大帮助。
一、TEC—4计算机组成原理实验系统特点1.计算机模型简单、实用,运算器数据通路、控制器、控制台各部分划分清晰。
2.计算机模型采用了数据总线和指令总线双总线体制,能够实现流水控制。
3.控制器有微程序控制器或者硬布线控制器两种类型,每种类型又有流水和非流水两种方案。
4.寄存器堆由1片ispLSI1016组成,运算器由1片ispLSI1024组成,设计新颖。
5.实验台上包括了1片在系统编程芯片ispLSI1032,学生可用它实现硬布线控制器。
6.该系统能做运算器组成、双端口存储器、数据通路、微程序控制器、中断、CPU组成与机器指令执行、流水微程序控制器、硬布线控制器、流水硬布线控制器等多种实验。
7.电源部分采用模块电源,重量轻,具有抗电源对地短路能力。
8.采用自锁紧累接接线方式,接线可靠。
二、TEC—4计算机组成原理实验系统的组成TEC—4计算机组成原理实验系统由下述六部分组成:1.控制台2.数据通路3.控制器4.用户自选器件试验区5.时序电路6.电源部分下面分别对各组成部分予以介绍。
三、电源电源部分由一个模块电源、一个电源插座、一个电源开关和一个红色指示灯组成。
电源模块通过四个螺栓安装在实验台下面。
它输出+5V电压,最大负载电流3安培,内置自恢复保险功能,具有抗+5V对地短路能力。
电源插座用于接交流220伏市电,插座内装有保险丝。
电源开关用于接通或者断开交流220伏市电。
北京邮电大学计算机学院 - 操作系统实验报告(含源代码)

1/58
10 年 12 月 19 日
内容目录
实验 1.3 Shell 编程...........................................................4 1、实验目的...............................................................4 2、实验内容...............................................................4 3、实验原理...............................................................4 4、实验步骤...............................................................4 5、实验结果:.............................................................4 6、人员任务分配...........................................................5
实验项目:
1. 实验 1.3 Shell 编程 2. 实验 2.3 内核模块 3. 实验 2.4 系统调用 4. 实验 3.3 Shell 编程实验(进程管理实验) 5. 实验 4.1 观察实验(存储管理实验) 6. 实验 5.1 观察实验(进程通信) 7. 实验 6.3 Io 系统编程实验 8. 实验 6.4 设备驱动程序 9. 实验 7.1 代码分析(文件系统管理实验)
实验 3.3 Shell 编程实验(进程管理实验)......................................18 1、实验目的..............................................................18 2、实验内容..............................................................18 3、实验原理..............................................................18 4、实验步骤..............................................................18 5、实验结果及分析........................................................19 6、人员任务分配..........................................................19 2、实验内容 2............................................................20 3、实验原理..............................................................20 4、实验步骤..............................................................20 5、实验结果及分析........................................................23 6、人员分配..............................................................24
北京邮电大学 操作系统实验 实验报告

操作系统实验实验报告实验日期:11月23日实验名称:实验一一、实验目的1.学习LINUX操作系统2.熟悉UNIX/LINUX的常用基本命令3.理解fork()与clone()函数的区别和联系4.深入理解生产者和消费者问题二、实验内容(1)安装LINUX:(2)熟悉UNIX/LINUX的常用基本命令如ls、who、wc、pwd、ps、pstree、top,cat,cd,chgrp,chmod,chown,comm,cmp,cp,rm,diff,mv,rmdir等,了解环境。
(3)比较fork()和clone()的功能,利用fork()生成子进程和clone()生成线程。
(4)利用pthread库,通过其中的mutex来实现生产者和消费者问题。
三、项目要求及分析基本要求:(1)安装LINUX:使用FEDORA11(2)熟悉UNIX/LINUX的常用基本命令如ls、who、wc、pwd、ps、pstree、top,cat,cd,chgrp,chmod,chown,comm,cmp,cp,rm,diff,mv,rmdir等,了解环境。
(3)比较fork()和clone()的功能,利用fork()生成子进程和clone()生成线程。
(4)利用pthread库,通过其中的mutex来实现生产者和消费者问题。
四、具体实现1.linux常用指令1.1 目录操作和DOS 相似,Linux 采用树型目录管理结构,由根目录开始一层层将子目录建下去,各子目录以“/”隔开。
用户login后,工作目录的位置称为home directory,由系统管理员设定。
‘—’符号代表自己的home directory,例如:~/myfile是指自己home目录下myfile这个文件。
Linux 的通配符有三种:‘*’和‘?’用法与DOS相同,‘’代表区间内的任一字符,如test[05]即代表test0,test1,……,test5的集合。
北邮计算机科学与技术操作系统第二次实验

北京邮电大学操作系统第二次实验实验报告班级302班第一部分:内存管理的伙伴算法1.实验描述:实现一个内存管理的伙伴算法,实现内存块申请时的分配和释放后的回收。
用随机函数仿真进程进行内存申请,并且以较为随机的次序进行释放。
对其碎片进行统计,当申请分配内存失败时区分实际空间不足和由于碎片而不能满足。
2.实验原理解释:假设要求分配的块其大小为128个页面。
该算法先在块大小为128个页面的链表中查找,看是否有这样一个空闲块。
如果有,就直接分配;如果没有,该算法会查找下一个更大的块,具体地说,就是在块大小为256个页面的链表中查找一个空闲块。
如果存在这样的空闲块,内核就把这256个页面分为两等份,一份分配出去,另一份插入到块大小为128个页面的链表中。
如果在块大小为256个页面的链表中也没有找到空闲页块,就继续找更大的块,即512个页面的块。
如果存在这样的块,内核就从512个页面的块中分出128个页面满足请求,然后从384个页面中取出256个页面插入到块大小为256个页面的链表中。
然后把剩余的128个页面插入到块大小为128个页面的链表中。
如果512个页面的链表中还没有空闲块,该算法就放弃分配,并发出出错信号。
以上过程的逆过程就是块的释放过程,这也是该算法名字的来由。
满足以下条件的两个块称为伙伴:两个块的大小相同,两个块的物理地址连续。
伙伴算法把满足以上条件的两个块合并为一个块,该算法是迭代算法,如果合并后的块还可以跟相邻的块进行合并,那么该算法就继续合并。
3.试验运行截图:第一组数据测试截图:第二组数据测试截图:第三组数据测试截图:4.实验代码:#include<iostream>#include<stdio.h>#define GETMIN(a,b) ((a)<(b)?(a):(b)) #define GETMAX(a,b) ((a)>(b)?(a):(b)) using namespace std;struct Node{int size;int remain;int frag;int isSplit;Node *left;Node *right;Node *parent;};struct Process{int oriMem;int reqMem;Node *ptr;void init(int _oriMem){int i;if(_oriMem<=0){oriMem=0;reqMem=0;ptr=NULL;return;}oriMem=_oriMem;for(i=31;i>=0;i--){if(oriMem&(1<<i)){break;}}if(oriMem==1<<i){reqMem=oriMem;}else{reqMem=1<<(i+1);}ptr=NULL;}};class BuddyTree{private:Node *root;Node *newNode(Node *_parent,int _size,int _remain){Node *ptr=new(Node);ptr->size=_size;ptr->remain=_remain;ptr->frag=0;ptr->isSplit=0;ptr->left=NULL;ptr->right=NULL;ptr->parent=_parent;return ptr;}public:Node* getRoot(){return root;}void init(int MaxMem){root=newNode(NULL,MaxMem,MaxMem);}void requestMem(Node *ptr,Node *&res,int reqSize,int oriSize){ if(ptr->remain<reqSize){res=NULL;return;}if(ptr->size==reqSize){res=ptr;ptr->remain=0;ptr->frag+=reqSize-oriSize;return;}if(ptr->isSplit==0){int _size=ptr->size/2;ptr->isSplit=1;ptr->left=newNode(ptr,_size,_size);ptr->right=newNode(ptr,_size,_size);requestMem(ptr->left,res,reqSize,oriSize);}else{int minMem=GETMIN(ptr->left->remain,ptr->right->remain); if(minMem>=reqSize){if(ptr->left->remain<=ptr->right->remain){requestMem(ptr->left,res,reqSize,oriSize);}else{requestMem(ptr->right,res,reqSize,oriSize);}}else{if(ptr->left->remain>=reqSize){requestMem(ptr->left,res,reqSize,oriSize);}else{requestMem(ptr->right,res,reqSize,oriSize);}}}ptr->remain=GETMAX(ptr->left->remain,ptr->right->remain);ptr->frag=ptr->left->frag+ptr->right->frag;}void releaseMem(Node *ptr){int memsize=ptr->size;int frag=ptr->frag;ptr->frag=0;ptr->remain=memsize;ptr=ptr->parent;while(ptr){if(ptr->left->remain==ptr->left->size&&ptr->right->remain==ptr->right->size){ ptr->remain=ptr->size;}else{ptr->remain=GETMAX(ptr->left->remain,ptr->right->remain);}ptr->frag-=frag;ptr=ptr->parent;}}void printTree(Node *ptr){if(ptr==NULL)return;char tmp[100];sprintf(tmp,"[Node size %dB]",ptr->size);printf("%-26s",tmp);sprintf(tmp,"remaining : %dB",ptr->remain);printf("%-26s",tmp);sprintf(tmp,"fragment : %dB",ptr->frag);printf("%s\n",tmp);printTree(ptr->left);printTree(ptr->right);}};Process P[200];int test[3][20]={{24,80,4600,8,100,1,500},{70,480,3300,25,10600,8909,490,99,40},{1,20,300,4000,50000,600000,7000000,80000000,900000000}}; int n[3]={7,9,9};int memory[3]={1024,1024*1024,1024*1024*1024};int main(){BuddyTree BT;char tmp[100];for(int t=0;t<3;t++){printf("Test%d:\n",t+1);printf("Process status:\n");for(int j=0;j<n[t];j++){P[j].init(test[t][j]);sprintf(tmp,"Original request: %d",P[j].oriMem);printf("%-30s",tmp);sprintf(tmp,"Actual request: %d",P[j].reqMem);printf("%s\n",tmp);}printf("\nMemory amount : %dB\n",memory[t]);BT.init(memory[t]);printf("\n");printf("Constructing the tree:\n");for(int j=0;j<n[t];j++){sprintf(tmp,"The process needs %d bytes.",P[j].oriMem);printf("%-35s",tmp);BT.requestMem(BT.getRoot(),P[j].ptr,P[j].reqMem,P[j].oriMem);if(P[j].ptr){printf("Request success,obtain %d bytes.\n",P[j].reqMem);}else{printf("Request failed.\n");}}printf("\n");printf("After constructing,preorder the tree:\n");BT.printTree(BT.getRoot());printf("\n");printf("After constructing the tree,the sum of fragment is %d.\n",BT.getRoot()->frag);printf("\n");printf("After the release,the tree(preorder) is:\n");for(int j=0;j<n[t];j++){if(P[j].ptr){BT.releaseMem(P[j].ptr);}}BT.printTree(BT.getRoot());printf("\n");printf("\n");system("pause");printf("\n");}return 0;}第二部分:设计一个虚拟存储区和内存工作区,并使用下述算法计算访问命中率1.实验描述:设计一个虚拟存储区和内存工作区,并使用下述算法计算访问命中率。
北邮研究生嵌入式系统实验课程——第4-2节 VxWorks任务间通信

创建信号量
SEM_ID semBCreate( options, initialState)
– Options 为阻塞在该信号量的任务规定排队的类 型(SEM_Q_PRIORTY或SEM_Q_FIFO) – initialState 初始化信号量为可用(SEM_FULL)或 不可用(SEM_EMPTY)
VxWorks提供三种类型的信号量
–二进制信号量:最快和常用的信号量,提供阻塞方式,用 于实现同步或互斥 –互斥信号量:用于实现互斥问题的特殊的二进制信号量, 解决具有互斥、优先级继承、删除安全和递归等情况 –计数信号量:类似于二进制信号量,记录信号量被释放的 次数。适合于一个资源的多个实例需要保护的情况
LOCAL SEM_ID fooBinSemId, fooMutexId; LOCAL FOO_BUF fooBuffer; fooSet(); 互斥信号量 … 共享内存 fooGet(); …
链表
lstLib库提供对双向链表进行操作的函数
List Descriptor Header Tail User node1 User node2 NODE
任务锁的使用
taskLock()/taskUnlock()
– 禁止所有其它任务执行 – 当非常频繁地做某事时使用 – 注意要保持critical region短
funcA () {
taskLock (); . . /* critical region of code that cannot be interrupted */ . taskUnlock ();
等待事件的任务调用semTake(),并一直阻塞 到得到信号量 检测到事件的任务或中断调用semGive();解锁 了等待事件的任务
2022年北京邮电大学世纪学院计算机科学与技术专业《操作系统》科目期末试卷B(有答案)

2022年北京邮电大学世纪学院计算机科学与技术专业《操作系统》科目期末试卷B(有答案)一、选择题1、现代操作系统中,文件系统都有效地解决了重名(即允许不同用户的文件可以具有相同的文件名)问题。
系统是通过()来实现这一功能的。
A.重名翻译结构B.建立索引表C.树形目录结构D.建立指针2、下面关于目录检索的论述中,正确的是()。
A.由于散列法具有较快的检索速度,因此现代操作系统中都用它来替代传统的顺序检索方法B.在利用顺序检索法时,对树形目录应采用文件的路径名,应从根目录开始逐级检索C.在利用顺序检索法时,只要路径名的一个分量名未找到,便应停止查找D.在顺序检索法的查找完成后,即可得到文件的物理地址,3、下列关于管程的叙述中,错误的是()。
A.管程只能用于实现进程的互斥B.管程是由编程语言支持的进程同步机制C.任何时候只能有一个进程在管程中执行D.管程中定义的变量只能被管程内的过程访问4、下列选项中,导致创建新进程的操作是()。
I.用户登录成功 II.设备分配 III.启动程序执行A.仅I和IIB.仅II和IIIC. 仅I和IIID. I,II,III5、中断扫描机构是()扫描次中断寄存器。
A.每隔一个时间片B.每条指令执行周期内最后时刻C.每当进程释放CPUD.每产生一次中断6、考虑一个分页式存储管理系统,其页表常驻内存。
I.如果内存访问耗时200ns,那么访问内存中的数据需要多长时间?II.如果引入关联寄存器(Associative Registers),而月.75%的页面可以从关联寄存器中找到,那么此时的有效访问时间(Effective Memory Reference Time)应为()。
假设访问关联寄存器的时间可以忽略。
注:有效访问时间即为平均访问时间。
A.200ns,150nsB.400ns,150nsC.400ns,250nsD.600ns.250ns7、下列关于页式存储说法中,正确的是()。
北邮操作系统进程同步实验报告与源代码

北邮操作系统进程同步实验报告与源代码进程管理实验报告1.实验目的:(1)理解进程/线程同步的方法,学会运用进程/线程同步的方法解决实际问题;(2)了解windows系统或unix/linux系统下中信号量的使用方法。
2.实验内容编写一个有关生产者和消费者的程序:每个生产者每次生产一个产品存入仓库,每个消费者每次从仓库中取出一个产品进行消费,仓库大小有限,每次只能有一个生产者或消费者访问仓库。
要求:采用信号量机制。
3、环境说明本实验是在win7环境下使用dev编译器实现的,采用Win API的信号量机制。
4、程序设计说明该程序根据教材中的消费者生产者问题编写的,使用了教材中提供的框架思路以及库函数,使用CreateThread建立新的线程,使用CreateMutex 创建一个互斥信号量,使用CreateSemaphore创建信号量,使用ReleaseMutex释放线程的互斥信号量,使用ReleaseSemaphore对指定的信号量增加指定的值,使用WaitForSingleObject等待空位,使用CloseHandle在操作结束后关闭线程和信号量。
在这个程序里我设计了三个函数:Int main()是主函数,其中包含了缓冲区大小的设置,生产者消费者发出请求等内容以及线程创建等内容DWORD WINAPI producer(LPVOID lpPara)是生产者等待缓冲区的使用权并对缓冲区进行操作DWORD WINAPI consumer(LPVOID lpPara)是消费者等待缓冲区的使用权并对缓冲区进行操作该程序模拟生产者消费者问题,首先要设置缓冲区的大小,输入请求资源的各个进程的信息以及请求时间,并且按照请求时间对各进程进行排序,创建线程,然后按序依次对缓冲区进行操作,详细设计见源代码。
5、程序运行结果截图:只有生产者请求,没有消费者请求,请求满足只有消费者请求,没有生产者请求,消费者的请求不成功:生产者请求大于消费者请求并且消费者请求在生产者放入产品之后:消费者请求多于生产者请求,只能满足部分消费者请求,不能满足全部:6、源代码:#include#include#include#include#include#includeusing namespace std;#define MAX_BUF 1000#define MAX_REQ 20HANDLE mutex;HANDLE full;HANDLE empty;HANDLE thread[MAX_REQ]; DWORD pro_id[MAX_REQ]; DWORD con_id[MAX_REQ]; struct request{int type;//记录生产者消费者的类型int seq; //记录请求次序}req[MAX_REQ];int buf_size;int req_size;int no;int buffer[MAX_BUF];int in;int out;int result;bool cmp(request a,request b){ return a.seqDWORD WINAPI producer(LPVOID lpPara){WaitForSingleObject(full,INFINITE);WaitForSingleObject(mutex,INFINITE);printf("生产者%d将第%d号产品放入缓冲区……\n",(int)lpPara,no);buffer[in]=no++;in=(in+1)%buf_size;printf("成功放入缓冲区!\n\n",(int)lpPara);ReleaseMutex(mutex);ReleaseSemaphore(empty,1,NULL);return 0;}DWORD WINAPI consumer(LPVOID lpPara){WaitForSingleObject(empty,INFINITE);WaitForSingleObject(mutex,INFINITE);printf("消费者%d将第%d号产品从缓冲区取出……\n",(int)lpPara,buffer[out]);buffer[out]=0;printf("成功从缓冲区取出!\n\n",(int)lpPara);ReleaseMutex(mutex);out=(out+1)%buf_size;ReleaseSemaphore(full,1,NULL);return 0;}int main(){int i;int p=0;no = 1;in=out=0;memset(buffer, 0, sizeof(buffer));printf("请设置缓冲区大小:");scanf("%d",&buf_size);printf("请输入请求使用资源进程的个数:");scanf("%d",&req_size);for(i=0;iprintf("请选择是消费者进程(0)还是生产者进程(1):");scanf("%d",&req[i].type);printf("请输入该进程的请求时间:");scanf("%d",&req[i].seq);}sort(req,req+req_size,cmp);mutex=CreateMutex(NULL,FALSE,NULL);full=CreateSemaphore(NULL,buf_size,buf_size,NULL);empty=CreateSemaphore(NULL,0,buf_size,NULL);for(i=0;i{if(req[i].type==0){thread[i]=CreateThread(NULL, 0, consumer, (LPVOID)i, 0, &con_id[i]); if(thread[i]==NULL)return -1;printf("\n消费者请求从缓冲区中取产品,请求时间为%d\n",req[i].seq);}if(req[i].type==1){thread[i]=CreateThread(NULL,0,producer,(LPVOID)i,0,&pro_id[i]);if(thread[i]==NULL)return -1;printf("\n生产者请求往缓冲区中放产品,请求时间为%d\n",req[i].seq);}}result = WaitForMultipleObjects(req_size, thread, TRUE, 500);if (result == WAIT_TIMEOUT)printf("\n请求不能被完全满足\n");elseprintf("\n能够满足所有请求\n");for(int i=0; iCloseHandle(thread[i]);CloseHandle(mutex);CloseHandle(full);CloseHandle(empty);system("pause");return 0;}7、实验总结:本次实验基于书上的生产者消费者问题,原理在上课的时候老师已经详细地讲解过,但是在具体编程实现的过程中也遇到了很多问题,除了书上的库函数之外还有一些函数书上并没有给出用法,比如如何创建线程等函数,通过查阅参考相关资料解决,通过编写代码也系统地理解了生产者消费者问题的操作过程,线程的创建,信号量的创建以及信号量的使用方法等情况,遇到的好多编代码上的细节问题通过反复调试解决,有较大收获。
北京邮电大学嵌入式操作系统实验报告

北京邮电大学嵌入式操作系统实验报告学院:信息与通信工程学院班级: XXXX学号: XXX姓名: XX指导老师: XX日期: 2017年12月14日目录嵌入式操作系统实验报告 (1)一、实验步骤............................................ 错误!未定义书签。
1.建立Android开发环境 (3)2.建立交叉编译环境 (6)3.内核源码编译 (6)4.内核运行 (9)5.内核裁剪 (9)二、实验中遇到的问题及解决方案 (11)三、实验总结 (11)一、实验步骤1. 建立 Android 开发环境:新建文件夹,命名为学号后四位:0305,在0305文件夹中再新建文件夹命名为“嵌入式软件实验”,最后在“嵌入式软件实验”文件夹下拷贝三个压缩包JDK、Android SDK 和交叉编译器。
在终端切换至嵌入式实验文件目录下查询,查看到所有文件已存在。
解压 JDK:tar zxvf jdk-7u15-linux-x64.tar.gz后,执行ls命令,看到实验文件夹下面生成文件夹 jdk1.7.0_15:设置环境变量,编辑文件/etc/profile,执行 vi /etc/profile打开 profile:执行 source /etc/profile使对/etc/profile 的修改立即生效执行 java -version 命令,出现 java 版本信息为 1.7.0_15,此时Java 开发环境建立好了。
解压 Android SDK,看见目录下产生一个文件夹 android-sdk-linux编辑文件/etc/profile,在环境变量PATH后面增加android的环境变量执行android命令弹出android SDK manager窗口为了获取更新列表,设置Android SDK Manager -Settings,修改配置:安装一个Android 2.1版本的 SDK Platform,再安装 Android SDK Tools、Android SDK Platform-tools和Android SDK Build-tools:新建一个虚拟机,创建的虚拟机名称为 2.1:启动新建的虚拟机:2. 建立交叉编译环境:执行tar jxvf arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2在嵌入式软件实验目录下生成一个arm-2014.05 文件夹再次执行 vi /etc/profile,在 PATH 中添加/home/lq/0305/嵌入式软件实验/arm- 2014.05/bin/ (注意用冒号隔开),保存退出后执行 source /etc/profile。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统班级:2011211302学号:2011211168姓名:康雅微目录实验5.1 进程通信观察实验实验6.3 I/O系统编程实验实验7.1 文件管理系统管理实验代码分析实验5.1 观察实验1、实验目的与内容在Linux下,用ipcs()命令观察进程通信情况,了解Linux基本通信机制。
2、实验原理Linux IPC继承了Unix System V及DSD等,共有6种机制:信号(signal)、管道(pipe 和命名管道(named piped)、消息队列(message queues)、共享内存(shared memory segments)、信号量(semaphore)、套接字(socket)。
本实验中用到的几种进程间通信方式:(1)共享内存段(shared memory segments)方式–将2个进程的虚拟地址映射到同一内存物理地址,实现内存共享–对共享内存的访问同步需由用户进程自身或其它IPC机制实现(如信号量)–用户空间内实现,访问速度最快。
–Linux利用shmid_ds结构描述所有的共享内存对象。
(2)信号量(semaphore)方式–实现进程间的同步与互斥–P/V操作,Signal/wait操作–Linux利用semid_ds结构表示IPC信号量(3)消息队列(message queues)方式–消息组成的链表,进程可从中读写消息。
–Linux维护消息队列向量表msgque,向量表中的每个元素都有一个指向msqid_ds结构的指针,每个msqid_ds结构完整描述一个消息队列LINUX系统提供的IPC函数有:●msgget(关键字,方式):创建或打开一个消息队列●msgsnd(消息队列标志符,消息体指针,消息体大小,消息类型):向队列传递消息●msgrcv(消息队列标志符,消息体指针,消息体大小,消息类型):从队列中取消息●msgctl(消息队列标志符,获取/设置/删除,maqid_ds缓冲区指针):获取或设置某个队列信息,或删除某消息队列Linux系统中,内核,I/O任务,服务器进程和用户进程之间采用消息队列方式,许多微内核OS中,内核和各组件间的基本通信也采用消息队列方式.3、实验结果实验6.3 编程实验1、实验目的编写一个daemon进程,该进程定时执行ps命令,然后将该命令的输出写至文件F1尾部。
通过此实验,掌握Linux I/O系统相关内容。
2、实验原理在这个程序中,首先fork一个子程序,然后,关闭父进程,这样,新生成的子进程被交给init进程接管,并在后台执行。
新生成的子进程里,使用system系统调用,将ps的输出重定向,输入到f1.txt 里面。
3、实验步骤编写daemon.c代码如下:#include<stdio.h>#include<stdlib.h>int main(int argc,char* argv[]){int i,p;p = fork();if(p > 0){exit(0);}else if(p == 0){for(i = 0; i < 100; i++){sleep(100);system("ps > f1.txt");}}else{perror("Create new process!");}return 1;}}编译程序# gcc -o daemon daemon.c执行程序# ./daemon5、实验结果及分析程序sleep(100)后会在当前目录生成一个文件f1.txt,内容如下:PID TTY TIME CMD1258 pts/0 00:00:00 bash2729 pts/0 00:00:00 daemon2801 pts/0 00:00:00 sh2802 pts/0 00:00:00 ps再sleep(100),此文件会更新。
重复执行100次。
实验7.1 代码分析1、实验目的了解与文件管理有关的Linux内核模块的代码结构。
2、实验内容阅读Linux/Minix中有关文件模块的调用主线,并写出分析报告,包括●文件建立模块,即系统调用create()●文件删除模块,即系统调用rm()●读/写模块,即read/write3、分析报告示例A. 创建文件模块分析5780 /*creat system call */5781 Creat()5782 {5783 resister *ip;5784 extern uchar;57855786 ip = namei(&uchar,1);5787 if(ip == NULL){5788 if(u.u_error)5789 return;5790 ip = maknode(u.u_arg[1]&07777&(~ISVTX));5791if (ip == NULL)5792 return;5793 open1(ip,FWRITE,2);5794 }else5795open1(ip,FWRITE,1);5796 }第5 7 8 6:“namei”( 7 5 1 8 )将一路径名变换成一个“inode”指针。
“uchar”是一个过程的名字,它从用户程序数据区一个字符一个字符地取得文件路径名。
5 7 8 7:一个空“inode”指针表示出了一个错,或者并没有具有给定路径名的文件存在。
5 7 8 8:对于出错的各种条件,请见U P M的C R E AT ( I I )。
5 7 9 0:“maknode”( 7 4 5 5 )调用“ialloc”创建一内存“inode”,然后对其赋初值,并使其进入适当的目录。
注意,显式地清除了“粘住”位( I S V T X )。
B. 删除文件rm模块分析3510 unlink()3511 {3512 resister *ip,*pp;3513 extern uchar;35143515 pp = namei(&uchar,2);3516 if (pp ==NULL)3517 return;3518 prele(pp);3519 ip = iset(pp ->dev,u.u_dent.u_ino);3520 if (ip == NULL)3521 panic (*unlink – iset *);3522 if ((ip ->i_mode%IFMT) == IFDIR && !suser())3523 goto out;3524 u.u_offset[1] = - DIRSIZ+2;3525 u.ubase = &u.u_dent;3526 u.ucount = DIRSIZE +2;3527 u.u_dent.u_ino = 0;3528 writei(pp);3529 ip ->i_nlink--;3530 ip->i_flag =! IUPD;35313532 out:3533 iput(pp);3534 iput(ip);3535 }新文件作为永久文件自动进入文件目录。
关闭文件不会自动地造成文件被删除。
当内存“inode”项中的“i _ nlink”字段值为0并且相应文件未被打开时,将删除该文件。
在创建文件时,该字段由“m a k n o d e”赋初值为1。
系统调用“link”( 5 9 4 1 )可将其值加1,系统调用“unlink”( 3 5 2 9 )则可将其值减1。
创建临时“工作文件”的程序应当在其终止前执行“unlink”系统调用将这些文件删除。
注意,“unlink”系统调用本身并没有删除文件。
当引用计数( i _ count )被减为0时( 7 3 5 0、7 3 6 2 ),才删除该文件。
为了减少在程序或系统崩溃时遗留下来的临时文件所带来的问题,程序员应当遵守下列约定:(1) 在打开临时文件后立即对其执行“unlink”操作。
(2) 应在“tmp”目录下创建临时文件。
在文件名中包括进程标识数就可构成一惟一文件名C 读/写模块,即read/write 分析/** linux/fs/minix/file.c** Copyright (C) 1991, 1992 Linus Torvalds** minix regular file handling primitives*/#include <asm/segment.h>#include <asm/system.h>#include <linux/sched.h>#include <linux/minix_fs.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/fcntl.h>#include <linux/stat.h>#include <linux/locks.h>#define NBUF 32#define MIN(a,b) (((a)(b))?(a):(b))#include#includestatic int ext2_file_read (struct inode *, struct file *, char *, int); static int ext2_file_write (struct inode *, struct file *, char *, int); static void ext2_release_file (struct inode *, struct file *);/** We have mostly NULL's here: the current defaults are ok for * the ext2 filesystem.*/static struct file_operations ext2_file_operations = {NULL, /* lseek - default */ext2_file_read, /* read */ext2_file_write, /* write */NULL, /* readdir - bad */NULL, /* select - default */ext2_ioctl, /* ioctl */generic_mmap, /* mmap */NULL, /* no special open is needed */ext2_release_file, /* release */ext2_sync_file /* fsync */};struct inode_operations ext2_file_inode_operations = {&ext2_file_operations,/* default file operations */NULL, /* create */NULL, /* lookup */NULL, /* link */NULL, /* unlink */NULL, /* symlink */NULL, /* mkdir */NULL, /* rmdir */NULL, /* mknod */NULL, /* rename */NULL, /* readlink */NULL, /* follow_link */ext2_bmap, /* bmap */ext2_truncate, /* truncate */ext2_permission /* permission */};static int ext2_file_read (struct inode * inode, struct file * filp,char * buf, int count){int read, left, chars;int block, blocks, offset;int bhrequest, uptodate;struct buffer_head ** bhb, ** bhe;struct buffer_head * bhreq[NBUF];struct buffer_head * buflist[NBUF];struct super_block * sb;unsigned int size;int err;if (!inode) {printk ("ext2_file_read: inode = NULL\n");return -EINV AL;}sb = inode->i_sb;if (!S_ISREG(inode->i_mode)) {ext2_warning (sb, "ext2_file_read", "mode = %07o",inode->i_mode);return -EINV AL;}offset = filp->f_pos;size = inode->i_size;if (offset > size)left = 0;elseleft = size - offset;if (left > count)left = count;if (left > EXT2_BLOCK_SIZE_BITS(sb);offset &= (sb->s_blocksize - 1);size = (size + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb);blocks = (left + offset + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb); bhb = bhe = buflist;if (filp->f_reada) {// 37 /* This specifies how many sectors to read ahead on the disk. */// 39 int read_ahead[MAX_BLKDEV] = {0, };blocks += read_ahead[MAJOR(inode->i_dev)] >>(EXT2_BLOCK_SIZE_BITS(sb) - 9);if (block + blocks > size)blocks = size - block;}/** We do this in a two stage process. We first try and request* as many blocks as we can, then we wait for the first one to* complete, and then we try and wrap up as many as are actually * done. This routine is rather generic, in that it can be used* in a filesystem by substituting the appropriate function in* for getblk** This routine is optimized to make maximum use of the various * buffers and caches.*/do {bhrequest = 0;uptodate = 1;while (blocks) {--blocks;*bhb = ext2_getblk (inode, block++, 0, &err);if (*bhb && !(*bhb)->b_uptodate) {uptodate = 0;bhreq[bhrequest++] = *bhb;}if (++bhb == &buflist[NBUF])bhb = buflist;/** If the block we have on hand is uptodate, go ahead* and complete processing*/if (uptodate)break;if (bhb == bhe)break;}/** Now request them all*/if (bhrequest)ll_rw_block (READ, bhrequest, bhreq);do {/** Finish off all I/O that has actually completed*/if (*bhe) {wait_on_buffer (*bhe);if (!(*bhe)->b_uptodate) { /* read error? */brelse(*bhe);if (++bhe == &buflist[NBUF])bhe = buflist;left = 0;break;}}if (left s_blocksize - offset)chars = left;elsechars = sb->s_blocksize - offset;filp->f_pos += chars;left -= chars;read += chars;if (*bhe) {memcpy_tofs (buf, offset + (*bhe)->b_data,chars);brelse (*bhe);buf += chars;} else {while (chars-- > 0)put_fs_byte (0, buf++);}offset = 0;if (++bhe == &buflist[NBUF])bhe = buflist;} while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock)); } while (left > 0);/** Release the read-ahead blocks*/while (bhe != bhb) {brelse (*bhe);if (++bhe == &buflist[NBUF])bhe = buflist;}if (!read)return -EIO;filp->f_reada = 1;if (!IS_RDONL Y(inode)) {inode->i_atime = CURRENT_TIME;inode->i_dirt = 1;}return read;}static int ext2_file_write (struct inode * inode, struct file * filp,char * buf, int count){off_t pos;int written, c;struct buffer_head * bh;char * p;struct super_block * sb;int err;if (!inode) {printk("ext2_file_write: inode = NULL\n");return -EINV AL;}sb = inode->i_sb;if (sb->s_flags & MS_RDONL Y)/** This fs has been automatically remounted ro because of errors*/return -ENOSPC;if (!S_ISREG(inode->i_mode)) {ext2_warning (sb, "ext2_file_write", "mode = %07o\n",inode->i_mode);return -EINV AL;}/** ok, append may not work when many processes are writing at the same time * but so what. That way leads to madness anyway.*/if (filp->f_flags & O_APPEND)pos = inode->i_size;elsepos = filp->f_pos;written = 0;while (written s_blocksize, 1, &err);if (!bh) {if (!written)written = err;break;}c = sb->s_blocksize - (pos % sb->s_blocksize);if (c > count-written)c = count - written;if (c != sb->s_blocksize && !bh->b_uptodate) {ll_rw_block (READ, 1, &bh);wait_on_buffer (bh);if (!bh->b_uptodate) {brelse (bh);if (!written)written = -EIO;break;}}p = (pos % sb->s_blocksize) + bh->b_data;pos += c;if (pos > inode->i_size) {inode->i_size = pos;inode->i_dirt = 1;}written += c;memcpy_fromfs (p, buf, c); //写入到缓冲块中buf += c;bh->b_uptodate = 1;bh->b_dirt = 1;brelse (bh);}inode->i_ctime = inode->i_mtime = CURRENT_TIME;filp->f_pos = pos;inode->i_dirt = 1;return written;}分析:对于整个文件的索引操作担,都使用块计算的。