操作系统 read源代码分析
解决系统内存不能为 Read 的方法(新添附件,不断收集中……)

运行某些程序的时候,有时会出现内存错误的提示,然后该程序就关闭。
“0x????????”指令引用的“0x????????”内存。
该内存不能为“read”。
“0x????????”指令引用的“0x????????”内存,该内存不能为“written”。
总结我见过的内存不能为Read 问题,问题原因可以归纳为以下几点:1、驱动不稳定,与系统不兼容,这最容易出现内存不能为Read 或者文件保护2、系统安装了一个或者多个流氓软件,这出现IE 或者系统崩溃的机会也比较大,也有可能出现文件保护3、系统加载的程序或者系统正在运行的程序之前有冲突,尤其是部分杀毒软件监控程序4、系统本身存在漏洞,导致容易受到网络攻击。
5、病毒问题也是主要导致内存不能为Read、文件保护、Explorer.exe 错误……6、如果在玩游戏时候出现内存不能为Read,则很大可能是显卡驱动不适合(这里的不适合有不适合该游戏、不适合电脑的显卡),也有可能是DX9.0C 版本不够新或者不符合该游戏、显卡驱动7、部分软件本身自身不足的问题8、电脑硬件过热,也是导致内存不能为Read 的原因之一。
9、电脑内存与主板兼容性不好也是导致内存不能为Read 的致命原因!希望以上总结能够对大家判断导致内存不能为Read 问题的原因有帮助。
分析:一般来说,电脑硬件是很不容易坏的。
内存出现问题的可能性并不大(除非你的内存真的是杂牌的一塌徒地),主要方面是:1。
内存条坏了(二手内存情况居多)、2。
使用了有质量问题的内存,3。
内存插在主板上的金手指部分灰尘太多。
4。
使用不同品牌不同容量的内存,从而出现不兼容的情况。
5。
超频带来的散热问题。
你可以使用MemT est 这个软件来检测一下内存,它可以彻底的检测出内存的稳定度。
二、如果都没有,那就从软件方面排除故障了。
先说原理:内存有个存放数据的地方叫缓冲区,当程序把数据放在缓冲区,需要操作系统提供的“功能函数”来申请,如果内存分配成功,函数就会将所新开辟的内存区地址返回给应用程序,应用程序就可以通过这个地址使用这块内存。
北京邮电大学计算机学院 - 操作系统实验报告(含源代码)

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
程序员如何快速阅读源代码

程序员如何快速阅读源代码一1、阅读源代码的说明文档,比方本例中的README, 写的特别的具体,认真读过之后,在阅读程序的时候往往能够从README文件中找到相应的说明,从而简化了源程序的阅读工作。
2、假如源代码有文档名目,一般为doc或者docs,最好也在阅读源程序之前认真阅读,因为这些文档同样起了很好的说明注释作用。
3、在阅读程序的同时,最好能够把程序存入到cvs之类的版本操纵器中去,在需要的时候可以对源代码做一些修改试验,因为动手修改是比仅仅是阅读要好得多的读程序的方法。
在你修改运行程序的时候,可以从cvs中把原来的代码调出来与你改动的部分进行比较(diff指令), 可以看出一些源代码的优缺点并且能够实际的练习自己的编程技术。
4、从makefile文件入手,分析源代码的层次结构,找出哪个是主程序,哪些是函数包。
这对于快速把握程序结构有很大关心。
5、分析函数包(针对C程序),要留意哪些是全局函数,哪些是内部使用的函数,留意extern关键字。
对于变量,也需要同样留意。
先分析清晰内部函数,再来分析外部函数,因为内部函数确定是在外部函数中被调用的。
6、需要说明的是数据结构的重要性:对于一个C程序来说,全部的函数都是在操作同一些数据,而由于没有较好的封装性,这些数据可能出如今程序的任何地方,被任何函数修改,所以肯定要留意这些数据的定义和意义,也要留意是哪些函数在对它们进行操作,做了哪些转变。
7、从main函数入手,一步一步往下阅读,遇到可以推想出意思来的简洁的函数,可以跳过。
但是肯定要留意程序中使用的全局变量(假如是C程序),可以把关键的数据结构说明拷贝到一个文本编辑器中以便随时查找。
8、阅读程序的同时,要留意一些小工具的使用,能够提高速度,比方vi中的查找功能,模式匹配查找,做标记,还有grep,find这两个最强大最常用的文本搜寻工具的使用。
二1、弄清晰模块作用:能够一句话描述首先要知道模块是做什么的,有什么作用,能够用一句话描述就够了。
c语言学籍管理系统源代码

c语言学籍管理系统源代码学籍管理系统的背景及意义随着社会的不断发展和教育的普及,学籍管理工作日益被重视。
传统的手工管理学籍的方式效率低下,存在着各种弊端,以致无法满足现代学校管理的需求。
因此,开发一款高效、便捷、可靠的学籍管理系统成为普遍需求,为了提高管理效率、减少工作难度,学籍管理系统被越来越广泛地使用。
本文将介绍一款基于C语言开发的学籍管理系统的源代码。
基本功能该学籍管理系统可以实现学生信息的录入、删除、修改和查询,以及学生的成绩录入、修改和查询。
此外,该系统还具备数据存储和文件读写的功能,能够自动保存学生信息和成绩数据,保障数据的安全性和可靠性。
模块设计该系统按照功能模块划分,主要分为三个模块:学生信息管理模块、学生成绩管理模块和数据存储与文件读写模块。
学生信息管理模块该模块主要实现学生信息的录入、删除、修改和查询等基本功能。
以下为该模块的主要源代码:```struct student {char name[20]; // 姓名int id; // 学号char sex[5]; // 性别char major[20]; // 专业};struct student stu[1000]; // 学生信息结构体数组int num_of_stu = 0; // 学生总数void add_student() { // 添加学生信息printf("请输入学生姓名:");scanf("%s", stu[num_of_stu].name);printf("请输入学生学号:");scanf("%d", &stu[num_of_stu].id);printf("请输入学生性别:");scanf("%s", stu[num_of_stu].sex);printf("请输入学生专业:");scanf("%s", stu[num_of_stu].major);num_of_stu++;printf("添加成功!\n");}void delete_student() { // 删除学生信息int delete_id;printf("请输入要删除的学生学号:");scanf("%d", &delete_id);int index = search_student_by_id(delete_id); if (index == -1) {printf("该学号不存在!\n");return;}for (int i = index; i < num_of_stu - 1; i++) { stu[i] = stu[i + 1];}num_of_stu--;printf("删除成功!\n");}void modify_student() { // 修改学生信息int modify_id;printf("请输入要修改的学生学号:");scanf("%d", &modify_id);int index = search_student_by_id(modify_id); if (index == -1) {printf("该学号不存在!\n");return;}printf("请输入学生姓名:");scanf("%s", stu[index].name);printf("请输入学生学号:");scanf("%d", &stu[index].id);printf("请输入学生性别:");scanf("%s", stu[index].sex);printf("请输入学生专业:");scanf("%s", stu[index].major);printf("修改成功!\n");}int search_student_by_id(int id) { // 根据学号查询学生信息for (int i = 0; i < num_of_stu; i++) {if (stu[i].id == id) {return i;}}return -1;}void query_student() { // 查询学生信息int query_id;printf("请输入要查询的学生学号:");scanf("%d", &query_id);int index = search_student_by_id(query_id);if (index == -1) {printf("该学号不存在!\n");return;}printf("姓名\t学号\t性别\t专业\n");printf("%s\t%d\t%s\t%s\n", stu[index].name,stu[index].id, stu[index].sex, stu[index].major);}```学生成绩管理模块该模块主要实现学生成绩信息的录入、修改和查询等功能。
osc指标源代码

OSC指标源代码
Osc指标通常指的是振荡器指标,用于分析股票、期货或外汇市场的价格波动。
以下是一个简单的Osc指标的源代码示例,使用Python编程语言编写:python
import pandas as pd
import numpy as np
# 读取数据
data = pd.read_csv('your_data.csv')
# 计算短期和长期移动平均线
short_mavg = data['Close'].rolling(window=20).mean()
long_mavg = data['Close'].rolling(window=50).mean()
# 计算Osc指标
osc = short_mavg - long_mavg
# 绘制Osc指标
import matplotlib.pyplot as plt
plt.plot(osc)
plt.show()
在这个示例中,我们首先使用Pandas库读取数据,然后计算短期和长期移动平均线。
接下来,我们通过从短期移动平均线中减去长期移动平均线来计算Osc指标。
最后,我们使用Matplotlib库绘制Osc指标的图形。
请注意,这只是一个简单的示例,实际应用中可能需要进行更多的数据处理和参数调整。
此外,还可以根据需要使用其他技术指标和算法来进一步完善分析。
北邮操作系统进程管理实验报告及源代码

进程管理实验报告1. 实验目的:(1)加深对进程概念的理解, 明确进程和程序的区别;(2)进一步认识并发执行的实质;(3)分析进程争用资源的现象, 学习解决进程互斥的方法;(4)了解Linux系统中进程通信的基本原理。
2. 实验预备内容(1)阅读Linux的sched.h源码文件, 加深对进程管理概念的理解;(2)阅读Linux的fork()源码文件, 分析进程的创建过程。
3.环境说明本次实验使用的是win7下的VMWare workstation虚拟机, 安装了ubuntu系统在ubuntu系统下使用code::blocks IDE编写代码并执行程序的4.实验内容:1.进程的创建:(1)实验题目和要求:编写一段程序, 使用系统调用fork() 创建两个子进程。
当此程序运行时, 在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示字符“a”, 子进程分别显示字符“b”和“c”。
试观察记录屏幕上的显示结果, 并分析原因。
(2)程序设计说明:参照书上的例子进行设计, 详见源代码(3)程序运行结果截图:(4)程序分析:a,b,c随机出现, 因为父进程与两个子进程之间并没有同步措施, 所以a,b,c随机打印出来, 也就是三个进程的活动次序是随机进行的, 不同的系统可能有不同的进程调度方式。
(5)源程序:#include<sys/types.h>#include<stdio.h>#include<unistd.h>int main(){pid_t pid1,pid2;if((pid1=fork())<0){printf("Fork Failed.\n");exit(-1);}else if((pid1=fork())==0)printf("b\n");else{if((pid2=fork())<0){printf("Fork Failed.\n");exit(-1);}else if((pid2=fork())==0)printf("c\n");else{wait(NULL);printf("a\n");exit(0);}}return 0;}2.进程的控制:要求一:(1)实验题目和要求:修改已经编写的程序, 将每个进程输出一个字符改为每个进程输出一句话, 再观察程序执行时屏幕上出现的现象, 并分析原因。
Linux 内核2.4版源代码分析大全

4.4.4 如何使传统管理方式依然有效
4.4.5 内核实现综述
4.4.6 核心结构与变量
4.4.7 devfs节点注册函数
4.4.8 编写采用devfs的设备驱动程序
4,5 块设备的请求队列
4.5.1 相关结构及请求队列的初始化
4.6.1 构造ioctl命令字
4.6.2 ioctl的实现过程
4.6.3 ioctl的上层处理函数
4.6.4 ioctl的底层处理函数
4.7 I/O端口的资源分配与操作
4.7.1 I/O端口概述
4.7.2 Linux系统中的I/O空间分配
4.7.3 端口操作函数
4.9.4 设备的使用
4.9.5 驱动程序编写实例
4.10 块设备驱动程序的实现
4.10.1 设备功能
4.10.2 编写块设备的函数接口fops
4.10.3 设备接口注册与初始化
第5章 Linux系统初始化
5.1 系统引导
1,13 系统调用
1.13.1 与系统调用有关的数据结构和
函数
1.13.2 进程的系统调用命令是如何转换为
INT0x80中断请求的
1.13.3 系统调用功能模块的初始化
1.13.4 Linux内部是如何分别为各种系统
调用服务的
4.1.2 与外设的数据交流方
4.1.3 字符设备与块设备
4.1.4 主设备号和次设备号
4.1.5 本章内容分配
4.2 设备文件
4.2.1 基本设备文件的设备访问流程
4.2.2 设备驱动程序接口
4.2.3 块设备文件接口
模块(源代码)

模块(源代码)模块,⽤⼀砣代码实现了某个功能的代码集合。
类似于函数式编程和⾯向过程编程,函数式编程则完成⼀个功能,其他代码⽤来调⽤即可,提供了代码的重⽤性和代码间的耦合。
⽽对于⼀个复杂的功能来,可能需要多个函数才能完成(函数⼜可以在不同的.py ⽂件中),n 个 .py ⽂件组成的代码集合就称为模块。
如:os 是系统相关的模块;file 是⽂件操作相关的模块模块分为三种:⾃定义模块内置模块开源模块⾃定义模块1、定义模块情景⼀:情景⼆:情景三:2、导⼊模块Python 之所以应⽤越来越⼴泛,在⼀定程度上也依赖于其为程序员提供了⼤量的模块以供使⽤,如果想要使⽤模块,则需要导⼊。
导⼊模块有⼀下⼏种⽅法:1234import modulefrom module.xx.xx import xxfrom module.xx.xx import xx as renamefrom module.xx.xx import *导⼊模块其实就是告诉Python 解释器去解释那个py ⽂件导⼊⼀个py ⽂件,解释器解释该py ⽂件导⼊⼀个包,解释器解释该包下的 __init__.py ⽂件那么问题来了,导⼊模块时是根据那个路径作为基准来进⾏的呢?即:sys.path12345import sysprint sys.path结果:['/Users/wupeiqi/PycharmProjects/calculator/p1/pp1', '/usr/local/lib/python2.7/site-packages/setuptools-15.2-py2.7.egg', '/usr/local/lib/python2.7/site-packages/distribute-0.6.28-py2.7.egg', '/usr/local/lib/python2.7/site-packages/MySQL_python-1.21.7.1-py2.7.egg', '/usr/local/lib/python2.7/site-packages/xlwt-1.0.0-py2.7.egg', '/usr/local/lib/python2.7/site-packages/xlrd-0.9.3-py2.7.egg', '/usr/local/lib/python2.7/site-packages/tornado-4.1-py2.7-macosx-10.10-x86_64.egg', '/usr/local/lib/python2py2.7.egg', '/usr/local/lib/python2.7/site-packages/certifi-2015.4.28-py2.7.egg', '/usr/local/lib/python2.7/site-packages/pyOpenSSL-0.15.1-py2.7.egg', '/usr/local/lib/python2.7/site-packages/six-1.9.0-py2.7.egg', '/usr/local/lib/python2.7/site-package packages/cffi-1.1.1-py2.7-macosx-10.10-x86_64.egg', '/usr/local/lib/python2.7/site-packages/ipaddress-1.0.7-py2.7.egg', '/usr/local/lib/python2.7/site-packages/enum34-1.0.4-py2.7.egg', '/usr/local/lib/python2.7/site-packages/pyasn1-0.1.7-py2.7.py2.7.egg', '/usr/local/lib/python2.7/site-packages/pycparser-2.13-py2.7.egg', '/usr/local/lib/python2.7/site-packages/Django-1.7.8-py2.7.egg', '/usr/local/lib/python2.7/site-packages/paramiko-1.10.1-py2.7.egg', '/usr/local/lib/python2.7/site-package packages/greenlet-0.4.7-py2.7-macosx-10.10-x86_64.egg', '/Users/wupeiqi/PycharmProjects/calculator', '/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python27.zip', '/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7'darwin', '/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac', '/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages', '/usr/local/Cellar/py tk', '/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old', '/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/site-packages'如果sys.path 路径列表没有你想要的路径,可以通过 sys.path.append('路径') 添加。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Read 源代码 源代码分析
向 fs 发消息(2)
• Sys_call 为 c 源码,在 book 7000 从堆栈接收调用者传来的参数, 源码, 从堆栈接收调用者传来的参数, 包括功能、通信对象、消息指针, 包括功能、通信对象、消息指针,所做的工作是进行收发双方的 合法性检查,区别功能( 当前进程),通信对 合法性检查,区别功能(send,rec,both)以 rp(当前进程 通信对 ) 当前进程 消息指针为参数调用mini_send, mini_rec,返回值在消息中 象,消息指针为参数调用 , • Mini_send, mini_rec 为 c 源码 在 book 7042, 所做工作不少,需 源码, 所做工作不少, 进行一系列检查,包括:双方身份合法性,互相收发的死锁检查, 进行一系列检查,包括:双方身份合法性,互相收发的死锁检查, 关键的检查是通信对方是否阻塞在收发上, 关键的检查是通信对方是否阻塞在收发上,是则调用 CopyMess 复制消息, 将对方转变为就绪; 复制消息,调用 ready 将对方转变为就绪;否则调用 unready当 当 前进程阻塞, 前进程阻塞,并排队 • CopyMess 宏,定义为过程 cp_mess, 在 book 8227, 汇编源码,自 汇编源码, 然是做消息复制工作,从消息源复制到目标, 然是做消息复制工作,从消息源复制到目标,通信双方都有消息 地址, 地址,需转换为统一的核心段基地址 • Ready 是 c 函数,在 book 71??, 使进程就绪 函数, • Unready 也是 c 函数,使进程阻塞 函数,
读文件
• Do_read 设置READING 标志调用 read_write 设置READING • Read_write 最初的几行代码在 fs 将 mm装入内存时运行,正常 mm装入内存时运行 装入内存时运行, 调用先进行有效性检查,变量初始化, 调用先进行有效性检查,变量初始化,读字符设备文件不经过高 速缓存,其后几行代码专用于写操作,检查是否超出设备容量, 速缓存,其后几行代码专用于写操作,检查是否超出设备容量, 或超出文件尾 • 读文件的关键是 23530 行开始的循环,它将读请求分为若干小 行开始的循环, 每段一块不跨块,每小块分别读, 段,每段一块不跨块,每小块分别读,循环直到所有字节读完或 已到文件尾为止 • 读取小块由过程 rw_chunk 完成,每读一块,各计数器和指针相 完成,每读一块, 应修改,循环结束后修改文件位置,若是管道文件, 应修改,循环结束后修改文件位置,若是管道文件,则修改指针 • 如果需要预度,则将相应的 I-节点和位置保存在全局变量中, 如果需要预度, 节点和位置保存在全局变量中, 以便在向用户发应答后,文件系统继续读下一块 以便在向用户发应答后,
Read 源代码分析
fs 接收消息
• Fs 的 main 函数,在book 22??? ,主函数只有两件事,初始化 函数, ,主函数只有两件事 主函数只有两件事, 文件系统, 文件系统,主循环 • 主循环在 fs 运行期间循环不停,做三件事,调用 get_work 接 运行期间循环不停,做三件事, 收消息, who, fs_call; 收消息,从中析出通信对方 who,请求 fs_call;调用 执行请求, *call_vector 执行请求,调用 reply 发应答 • get_work 检查是否有苏醒请求,若有则从进程表项中取进程号, 检查是否有苏醒请求,若有则从进程表项中取进程号, 请求,解除挂起和苏醒,苏醒数减,返回到主循环,处理请求; 请求,解除挂起和苏醒,苏醒数减,返回到主循环,处理请求; 若没有则调用 receive 接收消息 • receive 在 lib386,是汇编代码,其中执行 int SYSVEC 陷入 lib386,是汇编代码, 核心, _s_call, 核心,执行代码段 _s_call,其中调用 sys_call ,调用 mini_rec接收消息 接收消息, mini_rec接收消息,没有消息则调用者 unready ,调用 选择进程运行; 有则复制消息,发信者ready pick_proc ,选择进程运行; 有则复制消息,发信者ready ,逐 层返回, 层返回,receive 调用者继续 • 情景是 fs 接收来自用户进程的 READ 消息
Read 源代码 源代码分析
向fs发消息(1)
• read(fd,buffer,nbytes),标准库函数,在文件lib,43400行, read(fd,buffer,nbytes),标准库函数,在文件lib,43400行 (fd,buffer,nbytes) lib 的三个域赋值, 为消息 m 的三个域赋值,以 FS, READ, &m 为参数调用 _syscall, _syscall,返回读到的字节数 • _syscall, 也在文件 lib 中,37600行,在讨论 fork 时提到 37600行 过,主要工作是以 who, msgptr 为参数调用 _sendrec • _sendrec 在 lib386,07742行,是汇编源程序,是三个系统调 lib386,07742行 是汇编源程序, 用函数之一, 消息对方在堆栈中, 用函数之一,ecx 中存放 BOTH, 消息对方在堆栈中,取来送到 eax, 消息地址送 ebx, 然后执行终端指令 int SYSVEC (int 陷入核心, 21h), 陷入核心,返回值在消息中 • 陷入后的软中断处理过程是_s_call,这是由系统决定的,初始 陷入后的软中断处理过程是_s_call 这是由系统决定的, _s_call, 化时( prot_init, 化时(中断门描述符表的初始化在文件 book 的 prot_init, 07764行 过程_s_call的地址被装入中断门描述符表( _s_call的地址被装入中断门描述符表 07764行。过程_s_call的地址被装入中断门描述符表(中断向量 ),中断指令执行 导致该过程被执行。_s_call所做的工作 中断指令执行, 表),中断指令执行,导致该过程被执行。_s_call所做的工作 与中断处理程序类似,主要是保存现场, 与中断处理程序类似,主要是保存现场,调用过程 sys_call 构 造消息, 造消息,返回后运行 proc_ptr 所指的进程
读块
• Rw_chunk 以i- 节点和文件位置为参数,调用 read_map 把它们 节点和文件位置为参数, 转换为磁盘块号,对于普通文件, 转换为磁盘块号,对于普通文件,变量 b和dev 分别表示物理块 号和设备号, get_block查找块 必要时将块读入内存, 查找块, 号和设备号,然后调用 get_block查找块,必要时将块读入内存, 一旦获得块高速缓存的块指针, 一旦获得块高速缓存的块指针,就可以调用 sys_copy 请求传送 该块到用户空间, 释放该块, 该块到用户空间,随后调用 put_block 释放该块,以便必要时 可以从块高速缓存淘汰 • Read_map 负责将逻辑文件位置转化为物理块号,如果是前7个区 负责将逻辑文件位置转化为物理块号,如果是前7 段中的块,则只需通过I 节点简单计算, 段中的块,则只需通过I-节点简单计算,否则需要调用 rd_indir 读入间接块 • Read_ahead 将逻辑位置转化为物理块号,调用get_block 查找 将逻辑位置转化为物理块号,调用get_block 必要时读入内存,并立即回收, sys_copy, 块,必要时读入内存,并立即回收,不调用 sys_copy,每次只请 求一块 • Rahead 的用意与 read_ahead 相同,只是由于在调用 相同, 之后, rw_scattered, get_block 之后,调用 rw_scattered,使任务成批处理读写块 请求, 请求,以提高读写效率
Read 源代码分析
进程阻塞
• 用户进程只能与 mm, fs 通信,而且必须是 sendrec,因此必然 , 通信, , 阻塞,将导致进程调度 阻塞, • Ready 要求的参数是进程表项指针,作用是将进程转变为就绪, 要求的参数是进程表项指针,作用是将进程转变为就绪, 根据指针判断是 task, server, user ,将该进程排入相应就绪队列 • Unready 作用是将进程转变为阻塞,很可能是当前进程,因此可 作用是将进程转变为阻塞,很可能是当前进程, 能导致进程调度(如果需要调度,调用 pick_proc),转变为阻 能导致进程调度(如果需要调度, ),转变为阻 ), 塞后应修改进程表项,排入等待队列, 塞后应修改进程表项,排入等待队列,在 mini_send, mini_rec 源 码中可以看到这些修改 • pick_proc 为 proc_ptr 赋值,也就是选择一进程投入运行,该函 赋值,也就是选择一进程投入运行, 三级进程就绪队列, 数依次检查 task, server, user 三级进程就绪队列,选中的第一个 如果三个队列都空, 进程表项指针送 proc_ptr, 如果三个队列都空,则选择 IDLE • 注意,这里调用 read 的用户进程在 int SYSVEC 时陷入核心,因 注意, 时陷入核心, 此阻塞也在那里,将来再就绪, 此阻塞也在那里,将来再就绪,投入运行时是从 int SYSVEC 返 回开始, 之后的各个过程,均运行于核心态, 回开始,int SYSVEC 之后的各个过程,均运行于核心态,不存 在阻塞的问题。不是进程的一部分,此乃 MINIX 的独到之处, 在阻塞的问题。不是进程的一部分, 的独到之处, 层fs 执行请求
• Fs 的主循环在 get_work 接收消息之后,取得 who(发信进程), 接收消息之后, (发信进程), fs_call (消息类型,请求),然后调用 *call_vector[fs_call] 执行 消息类型,请求), ),然后调用 请求, 请求,call_vector 是若干函数的入口地址数组 • 宏 READ 的值为 3, *call_vector[3] = do_read ,因此调用 因此调用do_read , 因此调用 • Do_read 很小,它只以参数 READING 调用 很小, • read_write 所做工作很多,需要进行一系列的判断检测,区别 所做工作很多,需要进行一系列的判断检测, mm 请求还是用户进程请求, 请求还是用户进程请求, • 区别字符设备文件、块设备文件、管道文件、普通文件,区别读、 区别字符设备文件、块设备文件、管道文件、普通文件,区别读、 写进行不同处理,还要把请求分解为片断, 写进行不同处理,还要把请求分解为片断,逐片判断是否在块高 速缓存,如果不在需要进行高速缓存调度, 速缓存,如果不在需要进行高速缓存调度,要向相应设备任务发 块读写请求;如果在,则要向系统任务发请求, 块读写请求;如果在,则要向系统任务发请求,将块复制到用户 进程缓冲区。在此, 进程缓冲区。在此,我们关注普通文件的读请求