北京邮电大学操作系统实验 (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。
邮政物流与分拣实验指导书

10004
12
0 00102 0102
10003
20
0 00103 0103
10006
4
0 00103 0103
10003
30
0 00403 0403
10004
12
0 00403 0403
10006
30
0 00501 0501
10001
4
0 00502 0502
10001
20
0 00602 0602
容器流水 物料编
号
码
定单号
0 100013 000040806272
0 100013 000040806275
0 100013 000040806277
0 100020 000040806276
0 100027 000040806275
0 100027 000040806278
0 100207 000040806275
00801
101358 6921617884989 85
1
猫王卫生纸单卷
00802
101387 6923083023961 1064
2
猫王纸巾单长卷
00803
101390 6923083023985 545
3
真心香瓜子 161g
00901
101935 6926396115873 3
1
巴巴脆一块半番茄味 60g 00902
00603
100690 6920698414047 68
3
卡迪那薯片豌豆脆葱烧鸡 00701
101258 6900255207602 104
1
卡迪那薯片脆酷辣味
服务器在线模式下硬件故障诊断的方法

、曲 t 毫 毽 | ; 越 遵 巷 | 罐 《 | 警 8 t罐 靛§ | 疆曦器 照, 《 糍 l 释 臻
Reo reS lcin s u c ee to
#ig— s ut 示 进 行测 试 的特 定 设 备 “ 试 da St t i e s e指 测
组 ” :
H : r wae S : ot r Had r Sf e wa O : rlg rc mma d me sg s E ro e o n sa e
财 2 0 () 0 6 . 6 单 元 格 插 入 公 式 , 式 为 “ I ( D( O 。IO-。 Ⅱ. 经世 界 ,098: — 2 公 =F MO R W03= ,. F 】 ' tI -
E cl 】中 ( DR W03= , 资表 ! ¥ , D X( 资表 ! A¥ , 【】 奎 武 .xe 电 子表 格 在 财 务 管 理 中的 应 用 Ⅱ. 国管 理 信 息 MO (O , 1 ) 工 A 1N E S I E ¥ : 2钟 N
SYS EM HUT_ T S
E RROR L OG-
能。 系统 的问题 和故 障应 该及 早 发现 。 并及 时 进行处 理 I AC0 E E2 7 0 2 1 39 4 6 09 9 和解 决 , 避免 进一 步 的危 害 , 引起 严 重后 果 。及 早 的预 GI TURNED NG OFF
( O + ) ,O UM ) ” R W0 4/ C L N0) 。就是 说 行号 除 3余数 为 0 3 ) 【】 旮 . 子 表 格 软 件 E cl 财 务 报 表 核 算 中 的应 用 Ⅱ_ 脑 3张 电 xe 在 ] 电 的行 为 空行 ; 号 除 3余 数 为 1的行 为标 题行 . 行 则取 工 知识与技术. 1( : 7— 92 2 04 2 0 2 7 . 0 )9 资表 A1到 N1 为标题 行 , 号除 3余 数为 2 则返 回 作 行 . ( 上接 第 1 9页) 4
北京邮电大学操作系统综合课程设计

北京邮电大学课程设计报告目录实验一 Linux启动优化............................................................... 错误!未指定书签。
一实验目的........................................................................... 错误!未指定书签。
二实验内容与步骤............................................................... 错误!未指定书签。
1内核态启动优化........................................................... 错误!未指定书签。
2 用户态启动优化.......................................................... 错误!未指定书签。
3 测试系统总的启动时间.............................................. 错误!未指定书签。
三实验原理........................................................................... 错误!未指定书签。
四实验结果及分析............................................................... 错误!未指定书签。
1 内核态启动优化.......................................................... 错误!未指定书签。
2开机画面....................................................................... 错误!未指定书签。
操作系统概念(英文)——Syllabus for Operating Systems

Beijing University of Posts and Telecommunications (BUPT)School of Computer Science and TechnologySyllabus for Operating Systems1. OverviewsCourse No.: 313.04103 Course Title: Operating Systems Course Credit: 4 Credits, required courseSemester and Year: Fall 2008 Class: 06406—06410 Teaching hours:z Class teaching: 64 hoursz After-class experiments: 17 hoursz Course design, or professional practice for this course:(操作系统综合课程设计), 30 hours, 1 credits, conducted inthe 3rd semester.Prerequisites:z Data Structurez Computer Organization Principles2. Lecture MeetingsTime: Monday AM: 10:00 – 12:00Wensday AM: 10:00 – 12:00Location: Room 402, 4th Teaching Building3. FacultyInstructorz Name: Dr. Wen YE (叶文)z Office: Room 918, 3rd Teaching Buildingz Office Hours: Wednesday 3:00 to 4:30 PM,I am also available by appointment at a time more convenientfor you, especially at the end of this semesterz Phone: 86-10-62282633 (O)z E-mail: gryew@, yewen@Graduate Teaching Assistant:z Name: Cheng Yan (成艳),chengy352@Ma Haiying(马海印),mahaiyinmhy@ z Responsibility: checking homework, directing experimentsz Office: Room 918, 3rd Teaching Buildingz Office Hours: Wednesday 3:00 to 4:30 PM, or by appointment 4. Text Book1. Abraham Silberschatz, Peter Baer Galvin, Greg Gagne, Operating System Concepts(Seventh Edition), Higher Education Press and McGraw-Hill Companies, Beijing, May, 2007.References1.Andrew S.Tanenbaum, Modern Operating Systems, ChinaMachine Press and Prentice Hall, Beijing, Jan.1999.2.孙钟秀,费翔林,洛斌,谢立,操作系统教程(第3版),高等教育出版社,北京,2003年8月3.曹聪, 范廉明,操作系统原理与分析,科学出版社,北京,2003年9月。
北邮操作系统进程管理实验报告

操作系统实验课程报告课题: 进程管理实验姓名张涛学院计算机学院班级2011211311学号20112114192013年11月10日1.实验目的:(1)加深对进程概念的理解,明确进程和程序的区别;(2)进一步认识并发执行的实质;(3)分析进程争用资源的现象,学习解决进程互斥的方法;(4)了解Linux系统中进程通信的基本原理。
2.实验预备内容(1)阅读Linux的sched.h源码文件,加深对进程管理概念的理解。
这个文件长达2616行,这里截取第1221~1548行抄录在实验报告最后,即结构体task_struct,地位相当于PCB。
下面对几个比较重要的参数,结合本人的了解以及网上查阅的资料做一点解释。
中括号内的数字为代码行号,下同。
volatile long state:【1222】进程状态字,表示进程当前的状态(运行、就绪、等待、僵死、暂停、交换),分别对应已定义好的常量;TASK_RUNING:正在运行或可运行状态;TASK_INTERRUPTIBLE:可打断睡眠状态;TASK_UNINTERRUPTIBLE:不可打断睡眠状态;TASK_ZOMBLE:僵死状态;TASK_STOPPED:暂停状态;交换状态。
void *stack:【1223】进程所使用的栈空间;unsigned int flags:【1225】进程标志(创建、关闭、跟踪、被跟踪、内核dump等),同样对应已定义好的常量;unsigned int rt_priority:【1237】表示本进程的实时优先级;const struct sched_class *sched_class、struct sched_entity se:【1239,1240】分别是调度类和调度实体,这两个结构包含了用于任务调度的完整的信息(进程信息、调度策略等);unsigned int policy:【1260】进程的调度策略标志,有三种调度标志:SCHED_OTHER :普通进程的调度策略,基于优先权的轮转法;SCHED_FIFO:实时进程的调度策略,基于先进先出的算法;SCHED_RR:实时进程的调度策略,基于优先权的轮询法。
北邮操作系统 第一次实验报告

内部命令、外部命令实验报告一.内部命令和外部命令的区别命令行程序分为内部命令和外部命令,内部命令是随装入内存的,而外部命令是一条一条单独的可执行文件。
内部命令都集中在根目录下的文件里,电脑每次启动时都会将这个文件读入内存,也就是说在电脑运行时,这些内部命令都驻留在内存中,用dir命令是看不到这些内部命令的。
外部命令都是以一个个独立的文件存放在磁盘上的,它们都是以com和exe 为后缀的文件,它们并不常驻内存,只有在电脑需要时,才会被调入内存。
二.内部命令演示1. dirdir是英文单词directory(目录)的缩写,主要用来显示一个目录下的文件和子目录。
[功能] 显示指定磁盘、目录中的文件和子目录信息,包括文件及子目录所在磁盘的卷标、文件与子目录的名称、每个文件的大小、文件及目录建立的日期时间,以及文件子目录的个数、所占用总字节数以及磁盘上的剩余总空间等信息。
[格式] dir [C:][path][filename][.ext][/o][/s][/p][/w][/a][说明] dir是DOS命令中最常用的一个。
斜杠表示后面的内容是参数。
DOS参数最常用的是以下四个:参数意义/p 显示信息满一屏时,暂停显示,按任意键后显示下一屏/o 排序显示。
o后面可以接不同意义的字母/w 只显示文件名目录名,每行五个文件名。
即宽行显示/s 将目录及子目录的全部目录文件都显示dir. 和 dir 相同。
dir..显示上一层目录。
实验结果显示程序:Microsoft Windows [版本6.1.7601]版权所有(c) 2009 Microsoft Corporation。
保留所有权利。
C:\Users\1>md d:\在大学/p命令语法不正确。
C:\Users\1>dir d:驱动器D 中的卷没有标签。
卷的序列号是0001-4AA1D:\ 的目录2013/10/13 23:43 <DIR> a2013/04/23 23:10 <DIR> BaiduReaderDownload 2013/10/13 23:56 <DIR> bb2013/10/01 11:40 <DIR> meimei下载2013/10/01 11:41 <DIR> Program Files2013/04/23 15:59 <DIR> Program Files (x86) 2013/07/18 12:57 <DIR> ut下载2013/04/23 15:24 <DIR> 删不掉你死东西2013/06/08 12:06 <DIR> 在大学0 个文件0 字节9 个目录107,188,031,488 可用字节C:\Users\1>dir d:\在大学驱动器D 中的卷没有标签。
北邮-大三-操作系统-进程管理实验报告

北邮-大三-操作系统-进程管理实验报告实验一进程管理1.实验目的:(1)加深对进程概念的理解,明确进程和程序的区别;(2)进一步认识并发执行的实质;(3)分析进程争用资源的现象,学习解决进程互斥的方法;(4)了解Linux系统中进程通信的基本原理。
2.实验预备内容(1)阅读Linux的sched.h源码文件,加深对进程管理概念的理解;(2)阅读Linux的fork()源码文件,分析进程的创建过程。
3.实验内容(1)进程的创建:编写一段程序,使用系统调用fork() 创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示字符“a”,子进程分别显示字符“b”和“c”。
试观察记录屏幕上2/323/32printf("b\n");}else{pid2 = fork();if(pid2<0){fprintf(stderr,"childprocess1 failed");exit(-1);}else if(pid2 == 0){printf("c\n");}else{printf("a\n");sleep(2);4/32exit(0);}}return 0;}结果如下:分析原因:pid=fork();操作系统创建一个新的进程(子进程),并且在进程表中相应为它建立一个新的表项。
新进程和原有进程的可执行程序是同一个程序;上下文和数据,绝大部分就是原进程(父进程)的拷贝,但它们是两个相互独立的进程!因此,这三个进程哪个先执行,哪个后执行,完全取决于操作系统的调度,没有固定的顺序。
(2)进程的控制修改已经编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。
5/32将父进程的输出改为father process completed输出b的子进程改为输出child process1 completed输出c的子进程改为输出child process2 completed运行的结果如下:理由同(1)如果在程序中使用系统调用lockf () 来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。
【实验】北京邮电大学网络管理实验报告一

【关键字】实验信息与通信工程学院网络管理实验报告专业:班级:姓名:学号:实验一基于Windows 平台的基本网络测试工具实验一、实验目的本实验的主要目的是熟练掌握操作系统自带的基本网络测试工具,包括状态监视、流量监视和路由监视。
熟练掌握Windows操作系统自带的基本网络测试工具,包括IP地址查询、MAC地址解析、网络状态测试、网络安全测试等工具。
二、实验内容1、Windows NT(2000)环境下网络状态监视工具的使用,包括Ipconfig、ping;2、Windows NT(2000)环境下网络流量监视工具的使用,包括ping;3、Windows NT(2000)环境下网络路由监视工具的使用,包括netstat、arp、traceroute/tracert。
三、实验环境Microsoft Windows XP操作系统四、实验步骤1.测试并总结ipconfig、arp、ping、tracert、netstat的作用。
ipconfig显示所有当前的TCP/IP网络配置值、动态主机配置协议(DHCP)和域名系统(DNS)设置。
使用不带参数的ipconfig,将只显示简单的IP配置信息,包括IP 地址、子网掩码、默认网关。
ARP协议即地址解析协议,是TCP/IP协议族中的一个重要协议,用来确定对应IP地址的物理地址,即MAC地址。
用arp命令可以查看本地计算机或另一台计算机的ARP高速缓存中的当前内容,以及用来将IP地址和网卡MAC地址进行绑定等。
ping命令是网络中广泛应用的命令,在网络不通或传输不稳定时,管理员都会使用ping 命令测试网络的连通性。
Ping命令内置于Windows系统的TCP/P协议中,它使ICMP会送请求与会送应答报文。
通过ping可以获得每个数据包的发送和接收的往返时间,并报告无响应数据包的百分比,对确定网络是否正确连接、网络连接的状况非常有用。
(1)tracert 命令用来显示数据包到达目标主机所经过的路径,当网络出现故障时,可以用来确定出现故障的具体位置,找出在经过哪个路由时出现了问题,从而使网络管理人员缩小排查范围。
北邮操作系统第二次实验

北京邮电大学操作系统实验实验报告班号:14 姓名: oneseven学号:实验日期:实验名称:操作系统实验一、实验目的通过模拟实现内存分配的伙伴算法和请求页式存储管理的几种基本页面置换算法,了解存储技术的特点。
掌握虚拟存储请求页式存储管理中几种基本页面置换算法的基本思想和实现过程,并比较它们的效率。
二、实验内容1.实现一个内存管理的伙伴算法,实现内存块申请时的分配和释放后的回收。
实验准备用随机函数仿真进程进行内存申请,并且以较为随机的次序进行释放。
对其碎片进行统计,当申请分配内存失败时区分实际空间不足和由于碎片而不能满足。
2.设计一个虚拟存储区和内存工作区,并使用下述算法计算访问命中率。
1) 最佳置换算法(Optimal)2) 先进先出法(Fisrt In First Out)3) 最近最久未使用(Least Recently Used)4) 最不经常使用法(Least Frequently Used)其中,命中率=1-页面失效次数/页地址流长度。
试对上述算法的性能加以较各:页面个数和命中率间的关系;同样情况下的命中率比较。
实验准备本实验中主要的流程:首先用srand( )和rand( )函数定义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法计算出相应的命中率。
实验可先从一个具体的例子出发。
(1)通过随机数产生一个指令序列,共2048条指令。
指令的地址按下述原则生成:A:50%的指令是顺序执行的B:25%的指令是均匀分布在前地址部分C:25%的指令是均匀分布在后地址部分具体的实施方法是:A:在[0,1023]的指令地址之间随机选取一起点mB:顺序执行一条指令,即执行地址为m+1的指令C:在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’D:顺序执行一条指令,其地址为m’+1E:在后地址[m’+2,2047]中随机选取一条指令并执行F:重复步骤A-E,直到2048次指令(2)将指令序列变换为页地址流设:页面大小为4K;用户内存容量4页到32页;用户虚存容量为32K。
- 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;}分析:对于整个文件的索引操作担,都使用块计算的。