当前课程知识点:操作系统 > 第三讲 启动、中断、异常和系统调用 > 3.5 系统调用示例 > 3.5 系统调用示例
今天我们通过一个实例
来介绍系统调用的使用和实现
在这里我们通常从应用程序的写法上来说这个事
我们说我想写一个程序
能够把一个文件的内容复制出来
写到另一个文件里头改一个名字
这个地方是我把这件事情展开之后
我写程序会是什么样的
首先我会在屏幕上输出一个提示
要求用户输入
你要读的那个文件的名字
然后等待键盘输入
接下来 我会提示用户
在屏幕上给出提示说让它输入输出文件的名字
等待并接受键盘的输入
等到这两个信息都有了
然后说我们就试图去打开相应的文件
首先去打开输入文件
如果输入文件在你的文件系统当中有
那这是成立的 如果说文件不存在
这个时候肯定出错了因为我要复制的源没有了
接下来说我去看看创建输出文件
如果说你有这个文件
这个时候我会把原来东西覆盖掉
这是不对的 这个时候如果文件存在
这个时候我出错退出 这几步都做完了之后
那我就确认我的输入文件是存在的
输出文件是没有的
然后开始循环从文件当中读数据写到输出文件
从输入文件当中读数据
从输出文件当中把数据写到输出文件中
那为什么会在这做循环
有可能这个文件很小我一次就搞完了
如果这个文很大我可能会循环若干次
等所有这些都做完
那么这个时候我关闭输出文件和输入文件
然后屏幕上提示我整个事情做完
整个程序正常退出 那这是我想写的程序
对于这个程序来说
我会用到哪些系统调用
我们会有键盘的输入 有屏幕的输出
有文件的输入和输出
实际上在操作系统内核里
它这个实现键盘 屏幕和文件
都视为是文件系统里的
只是说键盘和屏幕作为特殊的文件来使用
那么在这里头涉及到的系统调用是
open close还有一个应该是create
然后再有一个write read
有了这几个系统调用之后
那么我这件事情在上边
用我的函数库里内容就可以完成
具体怎么来做 我们看到要想在应用程序写
那应用程序会使用到一个库函数read
这和我们用到其他函数是一样的
在我们ucore有这样一个头文件
告诉你他格式什么样子
然后这里头你需要知道这里的参数是什么意思
你读写的文件 你读出来的数据放在什么地方
缓冲区域头指针
然后这个缓冲区域并不是无限大的
它的最大长度你不能超过这个长度
然后我从里头读数据往里放
那我实际读出来的时候
有可能比这短
因为我实际文件里可能没有这么多数据
如果说我实际数据比这个缓冲区大怎么办
这个时候最多读出来是缓冲区长度
因为在多就缓冲区溢出了
然后读完之后返回值 这个地方有个返回值
返回值是你的长度 你在使用的时候怎么做
你打开文件 把这三个参数填上去
返回来的时候
返回的结果就是你实际的程度
这是你在用的时候
对于我们系统的实现来讲
在编译程序的时候
你的应用程序用到相应的库函数
这个库里头在编译系统调用的内容的时候
它就会前面准参数
实际上这段都会往堆栈压栈
压占完之后最后有函数调用
而这个函数调用最后都转到我有一个
你说这不是系统调用 是的
这是一个函数调用
这个函数调用所有的系统调用
它都是通过一个宏展开形成相应的函数
实际上在这里有一段汇编
大家注意这段汇编有可能你现在还不能完全看懂
那你需要值得这个int
是我们前面说到系统调用的指令
后面i实际上是你系统调用的中段向量编号
后面num实际就是系统调用read系统调用编号
然后后面是相应的参数
这些填完之后
实际上最后你在的执行应用程序
执行到这个地方 到这里来的时候
它就会转成系统调用进到内核里去
接下来我们操作系统里是如何实现系统调用read
首先我们刚才说在用户态一个int进到内核里来之后
这实际上是一个软中段
所有这些都会到你最开始一段汇编程序叫alltraps
在这里会获取到中段所需要的
相关信息组成的数据结构
这个时候实际上TF数据结构
那么在这里头我们注意到其中有一条
是其中的中段向量
那么在这里是系统调用对应中段向量
然后依据这个那么在trap函数里头
它就会转到我们系统调用这个函数里头
在这个函数里头它会读其中的EAX
实际上就是你的系统调用编号
这个系统调用编号会看到它是等于read
等于这个实际上相当于这个时候
我们知道进来是系统调用
并且这个系统调用调用是哪个功能
我们还缺什么
我们还缺它参数
这些参数就会转到相应的系统调用实现里头
这个实现里负责去堆占里头SP
获取相应我们当时填进堆占里头那三个参数
这个文件 缓冲区 头指针
然后缓冲区长度 有了这三个之后
实际上这个时候就相当于
已经从用户态转到内核态
如果说我是一个函数调用的话
这个时候就已经转过来
我在继续做相应函数实现就可以了
这个时候我们就看到最后它到sysfile read
这个函数里头去完成相应的文件读取功能
这个文件读取就是直接操作底下的驱动程序
在往下 等到它最后返回的时候
ok 那这个时候我们到这trapret
在这里头我们去看这类代码最后会有ireturn
这个return会把相应的返回值的长度
读到内容长度返回给用户态
整个实现就全部完成
那接下来我们会去看看实际的系统里的代码是什么样子的
-0.1 Piazza讨论区
--html
-0.2 在线实验平台
--实验平台使用帮助
--平台使用帮助
-0.2在线实验平台
--Raw HTML
-1.1 课程概述
--视频
-第一讲 操作系统概述--练习
-1.2 教学安排
--视频
-1.3 什么是操作系统
--Video
-1.4 为什么学习操作系统,如何学习操作系统
--Video
-1.5 操作系统实例
--视频
-1.6 操作系统的演变
--视频
-1.7 操作系统结构
--视频
-2.1 前言和国内外现状
-2.2 OS实验目标
-2.3 8个OS实验概述
-2.4 实验环境搭建
-2.5 x86-32硬件介绍
-2.6 ucore部分编程技巧
-2.7 演示实验操作过程
--Q6
--Q7
--Q10
-3.1 BIOS
--3.1 BIOS
-3.2 系统启动流程
-3.3 中断、异常和系统调用比较
-第三讲 启动、中断、异常和系统调用--3.3 中断、异常和系统调用比较
-3.4 系统调用
--3.4 系统调用
-第三讲 启动、中断、异常和系统调用--3.4 系统调用
-3.5 系统调用示例
-3.6 ucore+系统调用代码
-4.1 启动顺序
--4.1 启动顺序
-4.2 C函数调用的实现
-4.3 GCC内联汇编
-4.4 x86中断处理过程
-4.5 练习一
--4.5 练习一
-4.6 练习二
--4.6 练习二
-4.7 练习三
--4.7 练习三
-4.8 练习四 练习五
-4.9 练习六
--4.9 练习六
-5.1 计算机体系结构和内存层次
-5.2 地址空间和地址生成
-5.3 连续内存分配
-5.4 碎片整理
--5.4 碎片整理
-5.5 伙伴系统
--5.5 伙伴系统
-第五讲 物理内存管理: 连续内存分配--5.6 练习
-6.1 非连续内存分配的需求背景
-6.2 段式存储管理
-- 6.2 段式存储管理
-6.3 页式存储管理
-6.4 页表概述
--6.4 页表概述
-6.5 快表和多级页表
-6.6 反置页表
--6.6 反置页表
-6.7 段页式存储管理
-第六讲 物理内存管理: 非连续内存分配--6.8 练习
-7.1 了解x86保护模式中的特权级
-第七讲 实验二 物理内存管理--7.1 了解x86保护模式中的特权级
-7.2 了解特权级切换过程
-第七讲 实验二 物理内存管理--7.2 了解特权级切换过程
-7.3 了解段/页表
-第七讲 实验二 物理内存管理--7.3 了解段/页表
-7.4 了解UCORE建立段/页表
-第七讲 实验二 物理内存管理--7.4 了解UCORE建立段/页表
-7.5 演示lab2实验环节
-8.1 虚拟存储的需求背景
-8.2 覆盖和交换
-8.3 局部性原理
-8.4 虚拟存储概念
-8.5 虚拟页式存储
-8.6 缺页异常
--8.6 缺页异常
-9.1 页面置换算法的概念
-9.2 最优算法、先进先出算法和最近最久未使用算法
-第九讲 页面置换算法--9.2 最优算法、先进先出算法和最近最久未使用算法
-9.3 时钟置换算法和最不常用算法
-第九讲 页面置换算法--9.3 时钟置换算法和最不常用算法
-9.4 Belady现象和局部置换算法比较
-第九讲 页面置换算法--9.4 Belady现象和局部置换算法比较
-9.5 工作集置换算法
-第九讲 页面置换算法--9.5 工作集置换算法
-9.6 缺页率置换算法
-第九讲 页面置换算法--9.6 缺页率置换算法
-9.7 抖动和负载控制
-10.1 实验目标:虚存管理
-第十讲 实验三 虚拟内存管理--10.1 实验目标:虚存管理
-10.2 回顾历史和了解当下
-第十讲 实验三 虚拟内存管理--10.2 回顾历史和了解当下
-10.3 处理流程、关键数据结构和功能
-第十讲 实验三 虚拟内存管理--10.3 处理流程、关键数据结构和功能
-10.4 页访问异常
-第十讲 实验三 虚拟内存管理--10.4 页访问异常
-10.5 页换入换出机制
-第十讲 实验三 虚拟内存管理--10.5 页换入换出机制
-11.1 进程的概念
-第十一讲 进程和线程--11.1 进程的概念
-11.2 进程控制块
-第十一讲 进程和线程--11.2 进程控制块
-11.3 进程状态
-第十一讲 进程和线程--11.3 进程状态
-11.4 三状态进程模型
-11.5 挂起进程模型
-第十一讲 进程和线程--11.5 挂起进程模型
-11.6 线程的概念
-第十一讲 进程和线程--11.6 线程的概念
-11.7 用户线程
-第十一讲 进程和线程--11.7 用户线程
-11.8 内核线程
-第十一讲 进程和线程--11.8 内核线程
-12.1 进程切换
-第十二讲 进程控制--12.1 进程切换
-12.2 进程创建
-第十二讲 进程控制--12.2 进程创建
-12.3 进程加载
-第十二讲 进程控制--12.3 进程加载
-12.4 进程等待与退出
-第十二讲 进程控制--12.4 进程等待与退出
-13.1 总体介绍
-13.2 关键数据结构
-13.3 执行流程
-13.4 实际操作
-14.1 总体介绍
-14.2 进程的内存布局
-14.3 执行ELF格式的二进制代码-do_execve的实现
--14.3 执行ELF格式的二进制代码-do_execve的实现
-14.4 执行ELF格式的二进制代码-load_icode的实现
--14.4 执行ELF格式的二进制代码-load_icode的实现
-14.5 进程复制
-14.6 内存管理的copy-on-write机制
-15.1 处理机调度概念
-第十五讲 处理机调度--15.1 处理机调度概念
-15.2 调度准则
-15.3 先来先服务、短进程优先和最高响应比优先调度算法
--15.3 先来先服务、短进程优先和最高响应比优先调度算法
-第十五讲 处理机调度--15.3 先来先服务、短进程优先和最高响应比优先调度算法
-15.4 时间片轮转、多级反馈队列、公平共享调度算法和ucore调度框架
--15.4 时间片轮转、多级反馈队列、公平共享调度算法和ucore调度框架
-第十五讲 处理机调度--15.4 时间片轮转、多级反馈队列、公平共享调度算法和uc
-15.5 实时调度和多处理器调度
-第十五讲 处理机调度--15.5 实时调度和多处理器调度
-15.6 优先级反置
-第十五讲 处理机调度--15.6 优先级反置
-16.1 总体介绍和调度过程
-16.2 调度算法支撑框架
-16.3 时间片轮转调度算法
-16.4 Stride调度算法
-17.1 背景
--17.1 背景
-17.2 现实生活中的同步问题
-第十七讲 同步互斥--17.2 现实生活中的同步问题
-17.3 临界区和禁用硬件中断同步方法
-第十七讲 同步互斥--17.3 临界区和禁用硬件中断同步方法
-17.4 基于软件的同步方法
-第十七讲 同步互斥--17.4 基于软件的同步方法
-17.5 高级抽象的同步方法
-第十七讲 同步互斥--17.5 高级抽象的同步方法
-18.1 信号量
--18.1 信号量
-第十八讲 信号量与管程--18.1 信号量
-18.2 信号量使用
-第十八讲 信号量与管程--18.2 信号量使用
-18.3 管程
--18.3 管程
-第十八讲 信号量与管程--18.3 管程
-18.4 哲学家就餐问题
-18.5 读者-写者问题
-19.1 总体介绍
-19.2 底层支撑
-第十九讲 实验七 同步互斥--19.2 底层支撑
-19.3 信号量设计实现
-第十九讲 实验七 同步互斥--19.3 信号量设计实现
-19.4 管程和条件变量设计实现
-第十九讲 实验七 同步互斥--19.4 管程和条件变量设计实现
-19.5 哲学家就餐问题
-20.1 死锁概念
-第二十讲 死锁和进程通信--20.1 死锁概念
-20.2 死锁处理方法
-第二十讲 死锁和进程通信--20.2 死锁处理方法
-20.3 银行家算法
-第二十讲 死锁和进程通信--20.3 银行家算法
-20.4 死锁检测
-第二十讲 死锁和进程通信--20.4 死锁检测
-20.5 进程通信概念
-第二十讲 死锁和进程通信--20.5 进程通信概念
-20.6 信号和管道
-第二十讲 死锁和进程通信--20.6 信号和管道
-20.7 消息队列和共享内存
-第二十讲 死锁和进程通信--20.7 消息队列和共享内存
-21.1 文件系统和文件
-第二十一讲 文件系统--21.1 文件系统和文件
-21.2 文件描述符
-第二十一讲 文件系统--21.2 文件描述符
-21.3 目录、文件别名和文件系统种类
-第二十一讲 文件系统--21.3 目录、文件别名和文件系统种类
-21.4 虚拟文件系统
-第二十一讲 文件系统--21.4 虚拟文件系统
-21.5 文件缓存和打开文件
-第二十一讲 文件系统--21.5 文件缓存和打开文件
-21.6 文件分配
-第二十一讲 文件系统--21.6 文件分配
-21.7 空闲空间管理和冗余磁盘阵列RAID
-第二十一讲 文件系统--21.7 空闲空间管理和冗余磁盘阵列RAID
-22.1 总体介绍
-第二十二讲 实验八 文件系统--22.1 总体介绍
-22.2 ucore 文件系统架构
-第二十二讲 实验八 文件系统--22.2 ucore 文件系统架构
-22.3 Simple File System分析
-第二十二讲 实验八 文件系统--22.3 Simple File System分析
-22.4 Virtual File System分析
-第二十二讲 实验八 文件系统--22.4 Virtual File System分
-22.5 I/O设备接口分析
-第二十二讲 实验八 文件系统--22.5 I/O设备接口分析
-22.6 执行流程分析
-23.1 I/O特点
--视频
-第二十三讲 I/O子系统--23.1 I/O特点
-23.2 I/O结构
--816C80A0F5E3B8809C33DC5901307461
-第二十三讲 I/O子系统--23.2 I/O结构
-23.3 I/O数据传输
--C58221E14388B9DB9C33DC5901307461
-第二十三讲 I/O子系统--23.3 I/O数据传输
-23.4 磁盘调度
--567A3F1FCBFB3F4C9C33DC5901307461
-第二十三讲 I/O子系统--23.4 磁盘调度
-23.5 磁盘缓存
--C327536B80D25CE79C33DC5901307461
-第二十三讲 I/O子系统--23.5 磁盘缓存
-html
--html