FreeBSD系统调用实现原理

从应用开发者的角度来看系统调用,它是一个具备一定基础功能的库函数,通过输入参数得到结果输出;而系统开发者所要考虑的是如何用程序来操控计算机硬件实现系统调用的功能。

我们就拿getchar()库函数举例说明FreeBSD系统调用实现过程:

首先写出上层应用代码:

 1 #include <stdlib.h>
 2 #include <stdio.h>
 3 #include <unistd.h>
 4 #include <signal.h>
 5 
 6 /*SIGALRM消息处理函数*/
 7 void alarm_handle()   
 8 {   
 9 
10 }
11 
12 int main(int argc, char **argv)
13 {
14     int  x;
15 
16     /*设置定时器消息处理函数*/
17     signal(SIGALRM,handle);   
18 
19     /*设定定时器到期时间*/
20     alarm(1);   
21 
22     if ( ( x = getchar() ) < 0 )  {
23         if ( errno == EINTR) {
24             printf("get EINTR signal\n") ;
25         }        
26     }
27 
28     return 0;
29 
30 }

 

当程序执行到第22行的时候,启动系统调用。下面是getchar()库函数大致实现过程描述:

 

1、系统调用申请INT 80中断,我们的main进程进入系统内核以特权模式执行。 

      在 Unix / Linux 环境下程序可以在“用户态”与“内核态”两种模式下执行,“用户态”模式下程序不能直接访问和控制系统硬件资源,而在“内核态”模式下没有这方面的限制。一般情况下我们编写的应用程序一开始都是在“用户态”模式下运行,当程序需要访问系统硬件资源获取数据时(如:通过getchar()获取用户键盘输入字符),就必须使程序转入“内核态”模式执行。FreeBSD系统环境下程序从“用户态”转入“内核态”有三种方式:

  • 硬件中断(hardware interrupet)
  • 硬件陷阱(hardware trap)
  • 软件初始化陷阱(software initiated trap) 

       硬件中断由外部事件造成,比如发生IO事件、时钟事件等等,在我们的例子里就是用户按下键盘就会导致硬件中断;硬件陷阱的产生是由于程序在执行过程中发生内部错误,比如除0错误,空指针错误等等;软件初始化陷阱的产生是由于有进程内有事件需要及时调度软中断处理函数进行处理,通过设置系统内核数据结构中一个flag标志,每次进程从“内核态”退出之前就会调用软中断处理函数。 

       系统调用就是软件初始化陷阱的一种方式。getchar()申请“INT 80”中断后,产生一个硬件中断,硬件中断处理函数Syscall()将CPU设置成“内核模式”,从而可以执行特权指令了,比如访问一些特殊寄存器什么的,接着中断处理函数要保护现场,将CPU程序计数寄存器、CPU程序状态字寄存器、CPU标志位寄存器的内容压入内核栈保存,然后调用汇编程序再保存其他一些记录程序执行情况的信息,比如CPU通用寄存器、用户栈指针什么的也压入内核栈。硬件中断处理函数不再做多余的事情,而是准备直接退出,但是在退出前还有一件关键的使用要做,就是检查我们上面所说的内核数据结构中标志软件初始化陷阱的flag标志位,因为我们在调用getchar()的时候设置了标志位,所以于getchar()有关的软中断处理函数被执行,结果是: 

 

2、系统调用处理函数调用键盘驱动程序,通过IO接口向键盘控制器发出读取指令,用户进程因等待用户输入而进入“阻塞”状态 

       软件初始化中断处理函数启动键盘控制器,并向键盘设备的工作队列(work queue)中加入一个请求项,然后就让出CPU,导致用户进程进入Sleep状态,直到键盘输入导致的IO中断发生。

 

 

3、系统调用处理函数执行过程中一种情况是:用户正常键入字符,键盘中断处理函数启动,唤醒用户进程,系统调用处理函数返回输入字符 

       键盘IO输入完成,键盘IO中断处理函数将输入字符放回工作队列(work queue),标志键盘IO事件完成,唤醒main进程进入“就绪”状态最终进入“运行”态,从而使getchar()软件初始化中断处理函数继续开始执行,将用户键盘数据字符从内核缓存空间中考入用户缓存空间,最后在函数结束前恢复main进程上下文环境,从而使main进程重新回到“用户”态。  

 

 

4、系统调用处理函数执行过程中另一种情况是:用户不做任何操作,而此时用户进程恰巧收到系统消息,结果getchar()终止执行,系统调用处理函数返回EINT错误 

       当发生硬件异常或者软件异常(Trap)时,比如我们例子中的alarm时间到期,trap()处理函数会调用psignal()函数将对应的信号(SIGALRM) 提交给用户进程,直接导致该信号被记录在用户进程中线程集合内的某个线程的td_siglist数据结构中,因为此时用户进程处于“阻塞”态,则处理函数调用setrunnable()将线程唤醒,使用户进程状态改为"就绪"态,程序接着流程1中的系统调用处理函数继续执行,这时系统调用处理函数该退出内核态了,在退出之前,它会调用cursig()函数从td_siglist中获取消息,如果存在未处理的消息,则调用用户定义的消息处理函数(本例中的alarm_handle()),待消息处理函数返回以后,系统调用处理函数在用户函数调用栈中设定getchar()返回值-1,并设定全局变量errno的值为"EINTR", 最后才退出内核态返回用户态。

 

 

 

 
posted on 2012-07-14 20:09 大曦哥 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/luohansy/archive/2012/07/14/2591743.html

第一部分 综述 第1章 BSD系统的历史和目标 1.1 UNIX系统的历史 1.1.1 UNIX系统的起源 1.1.2 Research小组的UNIX系统 1.1.3 AT&T UNIX System III和System V 1.1.4 伯克利软件发布(BSD) 1.1.5 UNIX无处不在 1.2 BSD和其他系统 1.3 BSD向开放源代码的转变 1.3.1 Networking Release 2 1.3.2 法律诉讼 1.3.3 4.4BSD 1.3.4 4.4BSD-Lite Release 2 1.4 FreeBSD的开发模式 1.5 参考文献 第2章 FreeBSD设计概述 2.1 FreeBSD的功能和内核 2.2 内核结构 2.3 内核服务 2.4 进程管理 2.4.1 信号 2.4.2 进程组和会话 2.5 内存管理 2.5.1 BSD内存管理设计要点 2.5.2 内核中的内存管理 2.6 I/O系统 2.6.1 描述符与I/O 2.6.2 描述符管理 2.6.3 设备 2.6.4 套接口IPC 2.6.5 分散/聚集I/O 2.6.6 多文件系统支持 2.7 设备 2.8 文件系统 2.9 网络文件系统 2.10 终端 2.11 进程间通信 2.12 网络通信 2.13 网络实现 2.14 系统运行 2.15 复习题 2.16 参考文献 第3章 内核服务 3.1 内核结构 3.1.1 系统进程 3.1.2 系统入口 3.1.3 运行时刻的内核结构 3.1.4 内核的入口 3.1.5 从内核返回 3.2 系统调用 3.2.1 调用结果的处理 3.2.2 从系统调用返回 3.3 陷阱和中断 3.3.1 陷阱 3.3.2 I/O设备中断 3.3.3 软件中断 3.4 时钟中断 3.4.1 统计和进程调度 3.4.2 超时 3.5 内存管理服务 3.6 时间服务 3.6.1 真实时间 3.6.2 外部表示 3.6.3 调整时间 3.6.4 时间间隔 3.7 用户、用户组和其他身份标识 3.7.1 主机标识符 3.7.2 进程组和会话 3.8 资源服务 3.8.1 进程优先级 3.8.2 资源利用 3.8.3 资源限制 3.8.4 文件系统配额 3.9 系统运行服务 3.10 复习题 3.11 参考文献 第二部分 进程 第4章 进程管理 4.1 进程管理概述 4.1.1 多程序机制 4.1.2 调度 4.2 进程状态 4.2.1 进程结构 4.2.2 线程结构 4.3 上下文切换 4.3.1 线程状态 4.3.2 底层上下文切换 4.3.3 主动上下文切换 4.3.4 同步 4.3.5 互斥同步 4.3.6 锁管理器的锁 4.3.7 其他同步 4.4 线程调度 4.4.1 4.4BSD的调度程序 4.4.2 线程调度 4.4.3 线程优先级的计算 4.4.4 线程优先级例程 4.4.5 线程运行队列和上下文切换 4.4.6 ULE调度程序 4.5 创建进程 4.6 终止进程 4.7 信号 4.7.1 信号的历史 4.7.2 发送信号 4.7.3 接收信号 4.8 进程组和会话 4.8.1 会话 4.8.2 作业控制 4.9 监管环境 4.9.1 监管环境的语义 4.9.2 监管环境的实现 4.9.3 监管环境的限制 4.10 进程的调试 4.11 复习题 4.12 参考文献 第5章 存储管理 5.1 术语 5.1.1 进程与内存 5.1.2 调页机制 5.1.3 替换算法 5.1.4 工作集模型 5.1.5 交换机制 5.1.6 虚拟内存的优点 5.1.7 虚拟内存的硬件要求 5.2 FreeBSD虚拟内存系统概述 5.3 内核的存储管理 5.3.1 内核映射和子映射 5.3.2 内核地址空间的分配 5.3.3 内核的存储分配程序 5.3.4 内核的区域存储分配程序 5.4 进程独立拥有的资源 5.4.1 FreeBSD的进程虚拟地址空间 5.4.2 缺页处理 5.4.3 映射到对象 5.4.4 对象 5.4.5 对象到页面 5.5 共享存储 5.5.1 mmap模型 5.5.2 共享映射 5.5.3 私有映射 5.5.4 压缩影子链 5.5.5 私有快照 5.6 创建新进程 5.6.1 保留内核资源 5.6.2 复制用户地址空间 5.6.3 不通过复制创建新进程 5.7 执行一个文件 5.8 进程地址空间的操作 5.8.1 改变进程大小 5.8.2 文件映射 5.8.3 改变保护权限 5.9 终止进程 5.10 调页器接口 5.10.1 vnode调页器 5.10.2 设备调页器 5.10.3 物理内存调页器 5.10.4 交换调页器 5.11 调页机制 5.11.1 硬件高速缓存的设计 5.11.2 页面填色 5.12 页面替换 5.12.1 调页参数 5.12.2 pageout守护进程 5.12.3 交换机制 5.12.4 换入进程 5.13 可移植性 5.13.1 pmap模块的作用 5.13.2 初始化和启动 5.13.3 分配和释放映射 5.13.4 改变映射的访问和固定属性 5.13.5 管理页表的使用信息 5.13.6 初始化物理页面 5.13.7 管理内部数据结构 5.14 复习题 5.15 参考文献 第三部分 I/O系统 第6章 I/O系统概述 6.1 从用户到设备的I/O映射 6.1.1 设备驱动程序 6.1.2 I/O队列 6.1.3 中断处理 6.2 字符设备 6.2.1 原始设备和物理I/O 6.2.2 面向字符的设备 6.2.3 字符设备驱动程序的入口点 6.3 磁盘设备 6.3.1 块设备驱动程序的入口点 6.3.2 磁盘I/O请求的排序 6.3.3 磁盘标签 6.4 描述符的管理和服务 6.4.1 打开文件项 6.4.2 管理描述符 6.4.3 异步I/O 6.4.4 文件描述符的上锁机制 6.4.5 描述符上的多路I/O操作 6.4.6 select调用实现 6.4.7 数据在内核中的转移 6.5 虚拟文件系统的接口 6.5.1 vnode的内容 6.5.2 对vnode的操作 6.5.3 路径名转换 6.5.4 文件系统的导出服务 6.6 与文件系统无关的服务 6.6.1 名字缓存 6.6.2 缓冲区管理 6.6.3 缓冲区管理的实现 6.7 可叠加的文件系统 6.7.1 简单的文件系统层 6.7.2 联合安装的文件系统 6.7.3 其他文件系统 6.8 复习题 6.9 参考文献 第7章 设备 7.1 设备概述 7.1.1 PC的I/O体系结构 7.1.2 FreeBSD海量存储I/O子系统的结构 7.1.3 设备的命名和访问 7.2 GEOM层 7.2.1 术语和拓扑规则 7.2.2 改变拓扑 7.2.3 运行 7.2.4 拓扑的灵活性 7.3 CAM层 7.3.1 SCSI子系统 7.3.2 I/O请求通过CAM子系统的路径 7.4 ATA层 7.5 配置设备 7.5.1 识别设备 7.5.2 自动配置数据结构 7.5.3 资源管理 7.6 复习题 7.7 参考文献 第8章 本地文件系统 8.1 文件系统的分层管理 8.2 inode的结构 8.2.1 inode格式的变化 8.2.2 扩展属性 8.2.3 文件系统的新功能 8.2.4 文件标志 8.2.5 动态的inode 8.2.6 管理inode 8.3 命名 8.3.1 目录 8.3.2 在目录中查找名字 8.3.3 路径名转换 8.3.4 链接 8.4 配额 8.5 文件上锁 8.6 软更新 8.6.1 文件系统中的更新依赖 8.6.2 依赖关系的数据结构 8.6.3 跟踪位映射表的依赖关系 8.6.4 跟踪inode的依赖关系 8.6.5 跟踪直接块的依赖关系 8.6.6 跟踪间接块的依赖关系 8.6.7 跟踪新间接块的依赖关系 8.6.8 跟踪新目录项的依赖关系 8.6.9 跟踪新目录的依赖关系 8.6.10 跟踪删除目录项时的依赖关系 8.6.11 截短文件 8.6.12 回收文件和目录的inode节点 8.6.13 跟踪目录项重命名时的依赖关系 8.6.14 跟踪删除文件时的依赖关系 8.6.15 fsync对软更新的要求 8.6.16 删除文件时对软更新的要求 8.6.17 fsck对软更新的要求 8.6.18 软更新的性能 8.7 文件系统的快照 8.7.1 创建文件系统快照 8.7.2 维护文件系统快照 8.7.3 大型文件系统的快照 8.7.4 快照性能 8.7.5 后台fsck 8.7.6 用户可见的快照 8.7.7 动态的转储 8.8 本地文件库 8.8.1 文件库概述 8.8.2 用户的文件I/O 8.9 伯克利快速文件系统 8.9.1 伯克利快速文件系统的组成 8.9.2 引导块 8.9.3 优化存储空间利用率 8.9.4 读写文件 8.9.5 布局策略 8.9.6 分配机制 8.9.7 将块组成簇 8.9.8 基于扩展的分配 8.10 复习题 8.11 参考文献 第9章 网络文件系统 9.1 历史和概述 9.2 NFS的结构和操作 9.2.1 NFS协议 9.2.2 FreeBSD的NFS实现 9.2.3 客户机/服务器的交互操作 9.2.4 RPC的传输问题 9.2.5 安全问题 9.3 提高性能的技术 9.3.1 租约 9.3.2 崩溃恢复 9.4 复习题 9.5 参考文献 第10章 终端处理 10.1 终端处理模式 10.2 行规程 10.3 用户接口 10.4 tty结构 10.5 进程组、会话和终端控制 10.6 C-list 10.7 RS-232和调制解调器控制 10.8 终端操作 10.8.1 打开终端 10.8.2 输出到行规程 10.8.3 终端的输出 10.8.4 终端的输入 10.8.5 ioctl例程 10.8.6 调制解调器转换 10.8.7 关闭终端设备 10.9 其他行规程 10.10 复习题 10.11 参考文献 第四部分 进程间通信 第11章 进程间通信 11.1 进程间通信的模型 11.2 实现的结构和概述 11.3 内存管理 11.3.1 mbuf 11.3.2 存储管理算法 11.3.3 mbuf工具例程 11.4 数据结构 11.4.1 通信域 11.4.2 套接口 11.4.3 套接口地址 11.4.4 锁 11.5 建立连接 11.6 传送数据 11.6.1 发送数据 11.6.2 接收数据 11.7 关闭套接口 11.8 本地进程间通信 11.8.1 信号量 11.8.2 消息队列 11.8.3 共享内存 11.9 复习题 11.10 参考文献 第12章 网络通信 12.1 内部结构 12.1.1 数据流 12.1.2 通信协议 12.1.3 网络接口 12.2 套接口到协议的接口 12.2.1 协议的用户请求例程 12.2.2 协议的控制输出例程 12.3 协议到协议的接口 12.3.1 pr_output 12.3.2 pr_input 12.3.3 pr_ctlinput 12.4 协议和网络的接口 12.4.1 发送数据包 12.4.2 接收数据包 12.5 路由选择 12.5.1 内核路由选择表 12.5.2 路由选择查找 12.5.3 路由选择重定向 12.5.4 路由选择表接口 12.5.5 用户级的路由选择策略 12.5.6 用户级路由选择接口:路由选择套接口 12.6 缓冲和拥塞控制 12.6.1 协议缓冲策略 12.6.2 队列限制 12.7 原始套接口 12.7.1 控制块 12.7.2 输入处理 12.7.3 输出处理 12.8 网络子系统的其他主题 12.8.1 带外数据 12.8.2 地址解析协议 12.9 复习题 12.10 参考文献 第13章 网络协议 13.1 IPv4网络协议 13.1.1 IPv4地址 13.1.2 广播地址 13.1.3 组播 13.1.4 端口与关联 13.1.5 协议控制块 13.2 UDP协议 13.2.1 初始化 13.2.2 输出 13.2.3 输入 13.2.4 控制操作 13.3 Internet协议(IP) 13.3.1 输出 13.3.2 输入 13.3.3 转发 13.4 TCP协议 13.4.1 TCP连接状态 13.4.2 序号变量 13.5 TCP算法 13.5.1 定时器 13.5.2 往返时间的估计 13.5.3 建立连接 13.5.4 SYN缓存 13.5.5 关闭连接 13.6 TCP输入处理 13.7 TCP输出处理 13.7.1 发送数据 13.7.2 避免糊涂窗口综合症 13.7.3 避免小数据包 13.7.4 确认延迟和窗口更新 13.7.5 重发状态 13.7.6 慢启动 13.7.7 源拥塞的处理 13.7.8 缓冲与窗口大小分配 13.7.9 使用慢启动避免拥塞 13.7.10 快速重发 13.8 ICMP协议 13.9 IPv6 13.9.1 IPv6地址 13.9.2 IPv6数据包格式 13.9.3 套接口API的调整 13.9.4 自动配置 13.10 安全 13.10.1 IPSec概述 13.10.2 安全协议 13.10.3 密钥管理 13.10.4 IPSec实现 13.10.5 密码子系统 13.11 复习题 13.12 参考文献 第五部分 系统运行 第14章 启动和关机 14.1 概述 14.2 引导 14.3 初始化内核 14.4 初始化内核模块 14.4.1 基本服务 14.4.2 初始化内核线程 14.4.3 初始化设备模块 14.4.4 内核的可加载模块 14.4.5 启动进程间通信 14.4.6 启动内核线程 14.5 用户级初始化 14.5.1 /sbin/init 14.5.2 系统的启动脚本 14.5.3 /usr/libexec/getty 14.5.4 /usr/bin/login 14.6 系统运行 14.6.1 内核的配置 14.6.2 系统关机与自动重启 14.6.3 系统调试 14.6.4 同内核传递信息 14.7 复习题 14.8 参考文献 术语表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值