103
Linux 操操操 操操 主主 主主主 主主 主主主主 主主主 :、 [email protected] 3606864-83 主主主 (西 421 Autumn 2007

Linux 操作系统分析

  • Upload
    ocean

  • View
    123

  • Download
    0

Embed Size (px)

DESCRIPTION

Linux 操作系统分析. 主讲:陈香兰 助教:贾永泉、毛熠璐 [email protected] 3606864-83 (西区电三 421 ) Autumn 2007. 文件系统相关. Unix 文件系统概述 Linux 的虚拟文件系统 I/O 设备管理 存储相关 磁盘高速缓存 文件访问 对换 Ext2 、 ext3. Unix 文件系统概述. [email protected]. 提纲. 文件 硬链接和软链接 文件类型 文件描述符与索引节点 访问权限和文件模式 文件操作的系统调用. 文件. - PowerPoint PPT Presentation

Citation preview

Page 1: Linux 操作系统分析

Linux操作系统分析主讲:陈香兰

助教:贾永泉、毛熠璐[email protected]

3606864-83 (西区电三 421 )Autumn 2007

Page 2: Linux 操作系统分析

[email protected] Embedded Operating Systems 2

文件系统相关 Unix 文件系统概述 Linux 的虚拟文件系统 I/O 设备管理

存储相关 磁盘高速缓存 文件访问 对换 Ext2 、 ext3

Page 3: Linux 操作系统分析

Unix文件系统概述[email protected]

Page 4: Linux 操作系统分析

[email protected] Embedded Operating Systems 4

提纲 文件 硬链接和软链接 文件类型 文件描述符与索引节点 访问权限和文件模式 文件操作的系统调用

Page 5: Linux 操作系统分析

[email protected] Embedded Operating Systems 5

文件 Unix 文件是以字节序列组成的信息载体 内核不解释文件的内容 文件的组织

Page 6: Linux 操作系统分析

[email protected] Embedded Operating Systems 6

文件、目录和目录树 文件被组织成一个树状的命名空间

文件:叶结点 目录:根节点(根目录“ /” )和中间节点

目录使用一个目录名标识。 目录节点包含它下面的文件及子目录的所有信息

文件名和目录名 不能使用“ /” 和字符“ \0” ,其他 ASCII 字符都 OK 长度:不同的文件系统有不同的限制,

通常 <256 个字符 同一个目录下,不允许文件重名;不同目录下无妨

Page 7: Linux 操作系统分析

[email protected] Embedded Operating Systems 7

当前工作目录 Unix 的每个进程都有一个当前工作目录, current

working directory ,属于进程的执行上下文 绝对路径:用来在命名空间中指定一个特定的

文件,以“ /” 打头,表示以根目录作为起点,形如 “/home/chenxl/sample/test.c”

相对路径:以当前工作目录作为起点 例如当前目录为“ /home/chenxl” ,则上述文件的

相对路径可以是“ sample/test.c”

Page 8: Linux 操作系统分析

[email protected] Embedded Operating Systems 8

“.” 和“ ..” 前者表示当前工作目录 后者表示当前工作目录的父目录 若当前工作目录是根目录“ /” ,那么“ .” 和“ ..”

相等 例如,当前目录是“ /home/chenxl” ,则上述文件

的相对路径还可以表示为 “./sample/test.c” “./../chenxl/sample/test.c” “../../home/chenxl/sample/test.c”

Page 9: Linux 操作系统分析

[email protected] Embedded Operating Systems 9

硬链接和软链接 硬链接( hard link )

一般情况下,一个常见的文件名代表了到对应文件的一个硬链接

一个文件可以有不同的硬链接,他们可以在同一个目录下,也可以在不同的目录下,因此一个文件可以有不同的文件名

下面的命令可以创建一个硬链接$ ln p1 p2

其中 p1 指明一个现有的文件的路径名 p2 指明新建立的硬链接的路径名

Page 10: Linux 操作系统分析

[email protected] Embedded Operating Systems 10

硬链接的限制 不允许用户给目录创建硬链接 只有在同一个文件系统的文件之间才能创建硬链接

软链接( symbolic link ) 符号链接是一种特殊的文件(短文件),它包含另一个文件

的任意一个路径名 可以指向任意一个文件系统的任意文件,甚至一个不存在的

文件 下面的命令可以创建一个软链接

$ ln -s p1 p2 p2 指明新建立的软连接的路径名。在实现上,文件系统抽出

p2 的目录部分,在此目录下创建一个符号链接文件

Page 11: Linux 操作系统分析

[email protected] Embedded Operating Systems 11

文件类型 Unix 文件的类型可以是

常规文件( regular file ) 目录 符号链接 面向块的设备文件 面向字符的设备文件 管道和命名管道 套接字

基本类型

设备和驱动相关

用于进程间通信

Page 12: Linux 操作系统分析

[email protected] Embedded Operating Systems 12

文件描述符和索引节点 文件系统处理文件所需要的所有信息都包含在索引节点 inode 中 每个文件都有自己的 inode 一般而言, inode 应当包含如下信息

文件类型 与文件相关的硬链接的个数 以字节为单位的文件的长度 设备标识符(即包含文件的设备的标识符) 在文件系统中标识文件的 inode 号 文件拥有者的 UID 文件的 GID 一些时间戳: inode 状态的改变时间、文件的最后访问时间、最

后修改时间 访问权限和文件模式

Page 13: Linux 操作系统分析

[email protected] Embedded Operating Systems 13

访问权限和文件模式 文件潜在的用户分为 3 种类型

文件所有者 同组用户 其他用户

访问权限:读、写、执行 每类用户都有这三种权限

文件的访问权限使用 9 个不同的 bit 来表示 此外还有三种附加标记

suid 、 sgid 、 sticky

Page 14: Linux 操作系统分析

[email protected] Embedded Operating Systems 14

文件操作的系统调用 创建 / 删除 打开 / 关闭 读 / 写 定位 更名

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);int creat(const char *pathname, mode_t mode);

#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count); int unlink(const char *pathname);

#include <sys/types.h>#include <unistd.h>off_t lseek(int fildes, off_t offset, int whence);

#include <stdio.h>int rename(const char *oldpath, const char *newpath);

Page 15: Linux 操作系统分析

Linux的虚拟文件系统[email protected]

Page 16: Linux 操作系统分析

[email protected] Embedded Operating Systems 16

提纲 虚拟文件系统 VFS 的作用 VFS 的数据结构 文件系统类型 文件系统安装 路径名查找 VFS 系统调用的实现 文件加锁

Page 17: Linux 操作系统分析

[email protected] Embedded Operating Systems 17

虚拟文件系统 VFS的作用 虚拟文件系统

Virtual Filesystem Virtual Filesystem Switch VFS 是一个软件层,用来处理与 Unix 标准文件系统

相关的所有系统调用。 是用户应用程序与文件系统实现之间的抽象层

能为各种文件系统提供一个通用的、统一的接口 Linux 与其他类 Unix 系统一样,采用虚拟文件系

统 VFS 来达到支持多种文件系统格式的目标

Page 18: Linux 操作系统分析

[email protected] Embedded Operating Systems 18

VFS在一个简单文件复制操作中的作用假设用户输入以下 shell 命令

$ cp /floppy/TEST /tmp/test 其中,

/floppy 是 MS-DOS 的磁盘的一个挂载点(安装点) /tmp 是 Ext2 文件系统中的一个目录

对于 cp 命令而言,它不需要知道 /floppy/TEST和 /tmp/test 分别是什么文件系统类型 在 cp 命令中,它通过 VFS提供的系统调用接口进

行文件操作

Page 19: Linux 操作系统分析

[email protected] Embedded Operating Systems 19

Page 20: Linux 操作系统分析

[email protected] Embedded Operating Systems 20

VFS支持的文件系统类型 VFS支持的文件系统可以划分为三种主要类型

基于磁盘的文件系统:它们管理在本地磁盘分区中可用的存储空间 Linux 使用的文件系统: ext2 、 ext3 、 ReiserFS Unix家族的文件系统: SYSV 文件系统, UFS , MINIX 文

件系统以及 VERITAS VxFS 微软公司的文件系统: MS-DOS 、 VFAT 以及 NTFS ISO9660CD-ROM 文件系统和通用磁盘格式的 DVD 文件系

统 其他有专利权的文件系统,如 HPFS 、 HFS 、 AFFS 、 AD

FS 起源于非 Linux 系统的其他日志文件系统, JFS , XFS

Page 21: Linux 操作系统分析

[email protected] Embedded Operating Systems 21

网络文件系统:用于访问属于其他网络计算机的文件系统所包含的文件 NFS 、 Coda 、 AFS 、 SMB 、 NCP

特殊文件系统 不同于上述两大类 不管理具体的磁盘空间 /proc

各种不同的文件系统通过mount (挂载、安装)到根文件系统中 在 Linux 中,根文件系统即根目录所代表的文件系统 通常是 ext2 文件系统

Page 22: Linux 操作系统分析

[email protected] Embedded Operating Systems 22

VFS中通用文件模型概念 VFS 的基本思想:引入一个通用文件模型,这

个模型能够表示所有支持的文件系统 对于一个具体实现的文件系统,在处理时,需要将

其进行概念上的转换 例如,在通用文件模型中,目录被看成是普通文件

在实现上, read()sys_readfile 数据结构 f_opMS_DOS 文

件操作指针(其中的 read 操作) 类似面向对象的概念

Page 23: Linux 操作系统分析

[email protected] Embedded Operating Systems 23

通用文件模型有下列对象类型组成 超级块对象( superblock object )

存放文件系统相关信息:例如文件系统控制块 索引节点对象( inode object )

存放具体文件的一般信息:文件控制块 /inode 文件对象( file object )

存放已打开的文件和进程之间交互的信息 目录项对象( dentry object )

存放目录项与文件的链接信息

Page 24: Linux 操作系统分析

[email protected] Embedded Operating Systems 24

三个不同的进程打开同一个文件

两个不同的硬链接

同一个硬链接

Page 25: Linux 操作系统分析

[email protected] Embedded Operating Systems 25

VFS所处理的系统调用 mount 、 umount :挂载 /卸载文件系统 sysfs :获取文件系统信息 statfs 、 fstatfs 、 ustat :获取文件系统统计信息 chroot :更改根目录 chdir 、 fchdir 、 getcwd :操纵当前工作目录 mkdir 、 rmdir :创建 / 删除目录 getdents 、 readdir 、 link 、 unlink 、 rename :对目录项进行

操作 readlink 、 symlink :对软链接进行操作 chown 、 fchown 、 lchown :更改文件所有者 chmod 、 fchmod 、 utime :更改文件属性 open 、 close 、 create …

Page 26: Linux 操作系统分析

[email protected] Embedded Operating Systems 26

上述大部分操作之需要与通用文件模型中的一些对象打交道,而不需要真正操作具体的文件系统和文件,因此可以把 VFS看成是一个“通用”的文件系统,在必要时依赖某种具体的文件系统

Page 27: Linux 操作系统分析

[email protected] Embedded Operating Systems 27

VFS的数据结构 每个 VFS 对象都对应一定的数据结构,在这

个数据结构中包含对象的属性及其方法 一个具体的文件系统:超级块对象: super_bl

ock 一个具体的文件: Inode 对象: inode 一个打开文件:文件对象: file 目录项对象: dentry

Page 28: Linux 操作系统分析

[email protected] Embedded Operating Systems 28

与进程相关的文件 文件系统相关信息 fs_struct 打开文件相关信息 files_struct

Page 29: Linux 操作系统分析

[email protected] Embedded Operating Systems 29

文件系统类型 特殊文件系统

用来为系统程序员、系统管理员等提供一种容易的方式来操作内核的数据结构并实现操作系统的特殊特征

常用的特殊文件系统

Page 30: Linux 操作系统分析

[email protected] Embedded Operating Systems 30

Page 31: Linux 操作系统分析

[email protected] Embedded Operating Systems 31

文件系统类型的注册 文件系统类型: file_system_type

在系统初始化期间, register_filesystem() 用来注册编译时指定的每个文件系统 相应的文件系统对象被插入到 file_systems 链表中

unregister_filesystem()

Page 32: Linux 操作系统分析

[email protected] Embedded Operating Systems 32

文件系统的挂载 每个文件系统都有自己的根目录 如果一个文件系统的根目录是系统目录树的根

目录,那个这个文件系统就是根文件系统 其他文件系统可以挂载到系统的目录树上

这样的目录称为挂载点( mount 点,安装点) 文件系统之间的挂载关系对应文件系统之间的

父子关系

Page 33: Linux 操作系统分析

[email protected] Embedded Operating Systems 33

例如,放在软盘 /dev/fd0 上的 ext2 文件系统,可通过下列命令安装在 /flp 上

mount -t ext2 /dev/fd0 /flp 一般情况下,只允许挂载一次

在 umount 之前,其他对 /dev/fd0 的挂载命令会失败

在 2.4 中,可以挂载多次 不管被挂载多少次,只有一个真实的文件系统,因

此只有一个超级块对象

Page 34: Linux 操作系统分析

[email protected] Embedded Operating Systems 34

已挂载文件系统描述符 vfsmount

挂载根文件系统 第一阶段:安装一个特殊的文件系统,该文件系统仅提供一

个作为初始安装点的空目录: init_mount_tree 第二阶段: mount_root

挂载一个文件系统 sys_mount

卸载一个文件系统 sys_umount

Page 35: Linux 操作系统分析

[email protected] Embedded Operating Systems 35

Project 6

分析 Linux 的 VFS 相关的数据结构、文件系统的挂载操作,了解 VFS 中的各种操作(例如 read )是如何与一个具体的文件系统相关的。

Page 36: Linux 操作系统分析

[email protected] Embedded Operating Systems 36

路径名查找 VFS 是如何从文件路径名找到相应的索引节点

的? 分析路径名,将它拆分成一个文件名序列 除了最后一个文件名之外,其他所有文件名必定都

是目录名

搜索的起点: 绝对路径: currentfsroot 初始化 更改 相对路径: currentfspwd 更改

Page 37: Linux 操作系统分析

[email protected] Embedded Operating Systems 37

首先找到起点目录的索引节点 在这个索引节点的目录文件中,找到第一个目

录名(文件名)所对应的索引节点 在第一个目录名的索引节点的目录文件中找到第二个目录名(文件名)所对应的索引节点

…反复,直到文件名序列的最后一项

Page 38: Linux 操作系统分析

[email protected] Embedded Operating Systems 38

在上述查找过程中要处理的其他问题: 对每个目录的访问权限必须进行检查 若是符号链接,需要进行扩展 要考虑符号链接的循环引用(进行处理) 目录名可能是一个文件系统的安装点,必须扩展到

一个新的文件系统中

路径名查找 数据结构: struct nameidata 函数: path_init, path_walk, path_release

Page 39: Linux 操作系统分析

[email protected] Embedded Operating Systems 39

查找操作的标志

Page 40: Linux 操作系统分析

[email protected] Embedded Operating Systems 40

标准查找操作 要处理的问题

跳过第一个路径名分量前的任何 / 考虑符号链接的查找 检查权限 考虑“ .” 考虑“ ..” 考虑普通目录,要在目录项高速缓存中查找 …

Page 41: Linux 操作系统分析

[email protected] Embedded Operating Systems 41

父路径名的查找 在很多情况下,查找操作的真正目的不是路径

名的最后一个分量,而是最后分量的前一个分量 例如创建一个文件时 此时,路径解析的结果中存放最后一个分量所在目

录对应的对象

Page 42: Linux 操作系统分析

[email protected] Embedded Operating Systems 42

符号链接的查找 关于符号链接的解析由内核来完成

如何识别这是一个符号链接? 如何处理符号链接的循环情况?

Page 43: Linux 操作系统分析

[email protected] Embedded Operating Systems 43

VFS系统调用的实现 仍然考虑

$ cp /floppy/TEST /tmp/test 假定 cp 执行下列代码片段(实际要更复杂)

inf = open("/floppy/TEST", O_RDONLY, 0); outf = open("/tmp/test", O_WRONLY | O_CREAT | O_TRUNC, 0600); do {

len = read(inf, buf, 4096); write(outf, buf, len);

} while (len); close(outf); close(inf);

Page 44: Linux 操作系统分析

[email protected] Embedded Operating Systems 44

open()系统调用1 、读取文件名到内核中2 、分配一个新的文件描述符 fd3 、调用 filp_open 打开文件,返回文件对象指针4 、建立 fd 与文件对象指针的联系

Page 45: Linux 操作系统分析

[email protected] Embedded Operating Systems 45

1 、设置访问模式标志2 、调用 open_namei3 、调用 dentry_open

Page 46: Linux 操作系统分析

[email protected] Embedded Operating Systems 46

read和 write系统调用

1 、获得文件对象指针2 、判断是否有允许所请求的访问3 、是否有强制锁4 、调用具体读操作5 、释放文件对象指针

Read 和 write几乎相同,区别在于是读还是写

Page 47: Linux 操作系统分析

[email protected] Embedded Operating Systems 47

close系统调用

1 、检查 fd 的正确性和有效性

2 、释放文件描述符

3 、调用 filp_close

Page 48: Linux 操作系统分析

[email protected] Embedded Operating Systems 48

1 、调用文件操作的 flush方法

2 、释放文件上的任何强制锁

3 、调用 fput 释放文件对象

Page 49: Linux 操作系统分析

[email protected] Embedded Operating Systems 49

文件加锁 当多个进程访问同一个文件时,会出现同步问题 写同一个文件的同一个位置 对同一个文件的同一个位置, 1 读 1 写 或者更复杂的情况

Unix 系统提供对文件的加锁机制,可以避免上述冲突 POSIX 标准规定了基于 fcntl() 系统调用的文件加锁机制

Page 50: Linux 操作系统分析

[email protected] Embedded Operating Systems 50

强制锁 vs 劝告锁 劝告锁( advisory lock ):需要进程主动参与

Fcntl 、 flock 、 lockf 强制锁( mandatory lock ):内核强制检查

读锁 vs 写锁 读锁:多个进程可以读共享 写锁:只能一个进程写,并且与读锁互斥

Page 51: Linux 操作系统分析

[email protected] Embedded Operating Systems 51

Linux文件加锁 Linux支持所有的文件加锁方式

强制锁、劝告锁 fcntl 、 flock 、 lockf (库接口)

利用 mount 系统调用的 MS_MANDLOCK 标志, fcntl 可以在每个文件系统的基础上打开或者关闭强制锁(缺省) 关闭情况下, fcntl产生劝告锁 否则根据文件的组信息

若组设置位为 1并且组执行位为 0 ,则产生强制锁 否则劝告锁

Page 52: Linux 操作系统分析

管理 I/O设备[email protected]

Page 53: Linux 操作系统分析

[email protected] Embedded Operating Systems 53

I/O体系结构总线: PC 的 CPU 、 RAM 、 I/O 设备之间需

要某些数据通路来保证信息的流动总类:

ISA 、 EISA 、 VESA 、 PCI 以及 MCA 等等 三种基本类型

数据总线( pentium , 64 位) 地址总线( pentium , 32 位) 控制总线

当总线用于 CPU 与 I/O 设备之间的连接时,成为 I/O总线

Page 54: Linux 操作系统分析

[email protected] Embedded Operating Systems 54

在 x86 处理器中,只使用了 32 位地址总线中的 16 位对 I/O 设备进行寻址 寻址范围?

使用 64 位数据总线中的 8 、 16 、 32 位传送数据

I/O 设备与 CPU 之间的连接层次为: CPUI/O端口 I/O 接口设备控制器

Page 55: Linux 操作系统分析

[email protected] Embedded Operating Systems 55

PC的 I/O体系结构

Page 56: Linux 操作系统分析

[email protected] Embedded Operating Systems 56

I/O端口( I/O port) 每个 I/O端口 8 位,由于只使用 16 位地址总线访问,

因此 I/O地址空间一共提供 65536 个 I/O端口 在端口地址对齐的情况下,连续的 I/O端口可以看成

16 位 /32 位端口 特定的指令用来访问 I/O端口: in , ins , out , ou

ts

I/O端口的另外一种访问方法 直接映射到物理地址空间 可以使用存储器操作指令,如 mov , and , or 等等

Page 57: Linux 操作系统分析

[email protected] Embedded Operating Systems 57

I/O端口中的寄存器

命令

状态

输入数据

输出数据

Page 58: Linux 操作系统分析

[email protected] Embedded Operating Systems 58

Linux中访问 I/O端口的操作 inb 、 inw 、 inl inb_p 、 inw_p 、 inl_p outb 、 outw 、 outl outb_p 、 outw_p 、 outl_p

insb 、 insw 、 insl outsb 、 outsw 、 outsl

Page 59: Linux 操作系统分析

[email protected] Embedded Operating Systems 59

I/O端口的分配 不同的设备使用各自不同的端口 内核使用资源信息来记录端口分配信息

一个资源表示 I/O端口地址的一个范围

所有同种资源使用树形结构记录, ioport_resource 。一个较大范围可以进一步划分为子范围,使用兄弟链表表示

Page 60: Linux 操作系统分析

[email protected] Embedded Operating Systems 60

相关的操作

Page 61: Linux 操作系统分析

[email protected] Embedded Operating Systems 61

I/O接口 I/O 接口是出于一组 I/O端口和对应的设备控

制器之间的一种硬件电路 I/O端口设备:将 I/O端口中的值转换成设备所

需要的命令和数据 设备 I/O端口:检测设备状态的变化,更新端口

中相应的状态寄存器 连接到 PIC 上,代表设备发出中断请求

专用 I/O 接口和通用 I/O 接口

Page 62: Linux 操作系统分析

[email protected] Embedded Operating Systems 62

专用 I/O接口专用于一个特定的硬件设备

键盘接口 图形接口 磁盘接口 总线鼠标接口 网络接口

Page 63: Linux 操作系统分析

[email protected] Embedded Operating Systems 63

通用 I/O接口 现代 PC 都包含连接很多外部设备的几个通用

I/O 接口 并口:传输单位 1 个字节 串口:逐位传送 USB口 PCMCIA 接口 SCSI 接口

Page 64: Linux 操作系统分析

[email protected] Embedded Operating Systems 64

设备控制器复杂的设备需要一个设备控制器( device con

troller )来驱动 作用

对 I/O 接口接收到的高级命令进行解释,并控制设备执行特定的操作

对从设备接收到的电信号进行解释和转换,并修改状态寄存器

典型的设备控制器,例如磁盘控制器

Page 65: Linux 操作系统分析

[email protected] Embedded Operating Systems 65

I/O共享存储器很多硬件设备都有自己的存储器,通常称之为

I/O共享存储器( I/O Shared Memory ),例如显存

映射 I/O共享存储器的地址 根据设备和总线类型的不同,可以在三个不同的物

理地址范围之间进行映射 对于连接到 ISA总线上的大多数设备

0xa0000~0xfffff 对于使用 VESA局部总线的一些老设备(图形卡)

0xe00000~0xffffff (现在基本不生产)

Page 66: Linux 操作系统分析

[email protected] Embedded Operating Systems 66

对于连接到 PCI总线的设备 映射到 RAM物理地址的顶端

关于图形加速端口 AGP ( Accelerated Graphics Port )标准 是高性能图形卡的 PCI增强版 不仅有 I/O共享存储器,还能通过图形地址再映射

表 GART ( Graphics Address Remapping Table )直接对主板的 RAM 部分进行寻址

Page 67: Linux 操作系统分析

[email protected] Embedded Operating Systems 67

I/O共享存储器的访问 对于物理地址 1M 之内的 I/O共享存储器访问

直接访问 3G 以上的对应线性区间 addr+3G

对于高端 I/O共享存储器访问 没有直接映射在 3G 以上的线性区间 需要为其创建一块非连续线性区,并将其映射到高端 I/

O共享存储器的物理地址上 ioremap/iounmap io_mem=ioremap(某个物理起始地址,长度) 访问 io_mem+ 相对于起始地址的偏移处

Page 68: Linux 操作系统分析

[email protected] Embedded Operating Systems 68

DMA(直接存储器访问, Direct Memory Access) 所有的 PC 都包含一个 DMAC ( DMA控制器) 一种辅助处理器 用来控制在 RAM 和 I/O 设备之间传送数据

设置并激活 DMAC DMAC 自行传送数据 数据传送结束后, DMAC发出一个中断请求

当 CPU 和 DMAC并发访问同一个存储单元时,通过存储器仲裁器解决冲突

使用者:慢速设备 例如,磁盘驱动器

Page 69: Linux 操作系统分析

[email protected] Embedded Operating Systems 69

设备文件 Unix 类操作系统都是基于文件概念的 文件是以字符序列而构成的信息载体,因此一

个 I/O 设备也可以当作文件来处理 与普通文件交互的系统调用也可以直接用于 I/O 设

备 例如对 /dev/lp0 设备文件的 write() 可以将数据发往

打印机

Page 70: Linux 操作系统分析

[email protected] Embedded Operating Systems 70

设备文件的分类 根据设备驱动程序的基本特性,设备文件可以

分为: 字符设备 块设备

块设备 数据可以被随机访问 在用户看来,访问任何位置的数据时间大致相同 典型例子:硬盘、软盘、 CD-ROM 、 DVD播放器

Page 71: Linux 操作系统分析

[email protected] Embedded Operating Systems 71

字符设备 要么不可以随机访问,例如声卡 如果可以被随机访问(往往通过顺序访问方式实

现),但随着数据的位置的不同,其访问时间会相差很大,例如磁带

网络 网卡不与文件相关联,使用专门的处理方式

Page 72: Linux 操作系统分析

[email protected] Embedded Operating Systems 72

老式的设备文件 在 Linux2.4 中存在两种设备文件

老式的设备文件 Devfs 设备文件

老式的设备文件 这是存放在文件系统中的实际文件 索引节点不对磁盘上的数据块编址,而是包含硬件

设备的一个标识 每个设备文件包括:

名字、类型(字符 / 块) 设备号(主设备号:次设备号)

同一设备驱动程序 不同设备

Page 73: Linux 操作系统分析

[email protected] Embedded Operating Systems 73

mknod() 系统调用用来创建老式的设备文件

设备文件名

操作权限和设备类型

其中设备类型指定:S_IFCHR或 S_IFBLK

设备号

16 位,主设备号 :次设备号

Page 74: Linux 操作系统分析

[email protected] Embedded Operating Systems 74

设备文件通常包含在 /dev 目录中 一些设备文件的例子

Page 75: Linux 操作系统分析

[email protected] Embedded Operating Systems 75

注意:字符设备与块设备具有独立的编号, 例如,块设备 (3,0) 不同于字符设备 (3,0)

设备文件通常可以表示 一个硬件设备,例如磁盘 /dev/hda 或硬件设备的某一物理或逻辑分区,例如磁盘分区

/dev/hda2 或一个虚拟的逻辑设备(不会与任何硬件设备相关联),例如 /dev/null 代表一个“黑洞”

Page 76: Linux 操作系统分析

[email protected] Embedded Operating Systems 76

对内核而言,一个设备文件的名字是无关紧要的,关键在于设备文件的类型及其主次设备号 例如,建立一个设备文件 /tmp/disk ,其类型为块

设备,设备号为( 3 , 0 ),那么内核认为它与 /dev/hda 等价

Page 77: Linux 操作系统分析

[email protected] Embedded Operating Systems 77

Devfs设备文件 使用主次设备号标识设备存在局限性

在 /dev 中的大多数设备是不存在的 8 位长的主次设备号不够用

上述原因以及其他的一些因素综合起来,促使了 devfs 设备文件的产生

Devfs 虚拟文件系统允许设备驱动程序通过名字而不是主次设备号注册设备,例如 所有的磁盘可以放在 /dev/disks 目录下 /dev/hda/dev/disks/disc0 /dev/hdb/dev/disks/disc1

Page 78: Linux 操作系统分析

[email protected] Embedded Operating Systems 78

使用 devfs 文件系统的 I/O 驱动程序通过调用devfs_register()注册设备

一个注册了的设备文件自动出现在 devfs 的虚拟目录下

Page 79: Linux 操作系统分析

[email protected] Embedded Operating Systems 79

设备文件的 VFS处理 进程访问普通文件时,通过文件系统访问磁盘

分区中的数据块 当进程访问设备文件时,却可以驱动硬件设备

例如,进程访问计算机上的温度计对应的设备文件获得温度

HOW?

VFS

Page 80: Linux 操作系统分析

[email protected] Embedded Operating Systems 80

VFS

VFS 在设备文件打开时使用与设备相关的函数调用替换其缺省的文件操作 这些设备相关函数调用对硬件设备进行操作

Page 81: Linux 操作系统分析

[email protected] Embedded Operating Systems 81

设备驱动程序 这是一个软件层,使得硬件设备能够响应预定义好的编程接口,就是一组控制设备的 VFS函数接口 open , read , lseek , ioctl 等

上述函数的具体实现由设备驱动程序提供 此外设备驱动程序必须

首先注册并初始化自己 并在进行数据传送的时候监控 I/O 操作

Page 82: Linux 操作系统分析

[email protected] Embedded Operating Systems 82

注册设备驱动程序注册一个设备驱动程序意味着把它与对应的设

备文件连接起来 使得对设备文件发出的系统调用可以由内核转化为

相应的设备驱动程序对应的函数 访问一个没有注册设备驱动程序的设备文件将会返回错误码 -ENODEV

Page 83: Linux 操作系统分析

[email protected] Embedded Operating Systems 83

注册时机 如果设备驱动程序被静态编译进内核,则注册发生

在内核初始化阶段 如果作为一个内核模块来编译,则在装入模块的时候注册(并在卸载模块时注销)

Page 84: Linux 操作系统分析

[email protected] Embedded Operating Systems 84

设备驱动程序的初始化 对设备驱动程序进行注册与初始化是两件不同

的事情 注册应当尽早:使得用户可以使用设备文件 初始化应当推迟到最后可能的时候

原因:初始化就意味着需要分配系统中的稀缺资源,例如:1 ,中断向量(动态分配的情况下)2 ,用于 DMA传送的缓冲区的页框3 ,包括 DMA 通道本身

Page 85: Linux 操作系统分析

[email protected] Embedded Operating Systems 85

监控 I/O操作 I/O 操作的持续时间通常不可预知,可能与各

种因素相关,例如 机械装置的状态,如对于磁盘来讲,磁头的当前位置

或实际的随机事件,例如数据包何时到达网卡 以及人为因素,例如人对键盘、鼠标的使用,以及发现打印机卡纸时的操作

为此设备驱动程序必须通过某种监控手段监控I/O 操作终止或超时

Page 86: Linux 操作系统分析

[email protected] Embedded Operating Systems 86

两种可用的技术 轮询模式( polling mode )

CPU 重复检查(轮询)设备的状态寄存器,直到寄存器的值表明 I/O 操作已经完成为止

中断模式( interrupt mode )如果 I/O控制器能够通过 IRQ线发出 I/O 操作结束的信号,就可以使用中断模式

Page 87: Linux 操作系统分析

[email protected] Embedded Operating Systems 87

轮询模式的简单例子

Why ”--count”

也可以使用 jiffies 进行超时判断 若时间比较长,比如 ms级,可以在每次轮询

操作之后调用 schedule 主动放弃 CPU ,直到下次被调度再次轮询

可以用来粗略的判断超时

Page 88: Linux 操作系统分析

[email protected] Embedded Operating Systems 88

中断模式的简单例子假定实现一个简单的输入字符设备的驱动程序

当在对应的设备文件上发出 read() 系统调用时,一条输入命令被发往设备的控制寄存器

在一个不可预知的长时间后,设备把一个字节的数据放在输入寄存器

驱动程序然后将这个字节作为 read() 系统调用的结果返回

Page 89: Linux 操作系统分析

[email protected] Embedded Operating Systems 89

这个驱动程序包含两个函数: 实现文件对象 read方法的 foo_read()函数 处理中断的 foo_interrupt()函数

只要用户读设备文件, foo_read()函数就会被触发

对 I/O 设备发出读命令

等待读操作的结束,由中断处理程序唤醒将获得的数据送到用户空间中

Page 90: Linux 操作系统分析

[email protected] Embedded Operating Systems 90

从设备上读入数据

唤醒 read 的剩余部分

Page 91: Linux 操作系统分析

[email protected] Embedded Operating Systems 91

再看 foo_read 的输入参数 Struct file*filp ,在这个数据的私有数据项中, VF

S已经将其转换成设备驱动程序的私有的信息foo_dev_t, 被定义为包含如下信息: 一个信号量,互斥 使用 intr 作为标志

0 :没有发生 / 处理中断 1 :处理了中断

一个等待队列,用来给 foo_read睡眠 一个数据区,长度为 1 ,用来存放读到的数据

Page 92: Linux 操作系统分析

[email protected] Embedded Operating Systems 92

char* buf ,用户提供的存放数据的空间 Count 和 ppos 都没有用到

再看看 foo_interrupt() 中,这是通过 foo 一个全局变量获得设备的私有数据结构的,这个数据结构与 foo_read() 中通过 filp 中获得的私有数据一致

foo_interrupt 的输入参数没有得到使用,这是一种很普遍的情况

Page 93: Linux 操作系统分析

[email protected] Embedded Operating Systems 93

块设备驱动程序典型的块设备驱动程序都有很高的平均访问时

间, 例如磁盘的每次操作都需要几个 ms ,主要是为了

定位磁头,一旦定位后,就可以以稳定的高速率传输数据(几十MB/秒)

定义:相邻的数据指当数据以相邻的方式存放在磁表面时,一次单独操作就可以访问它们

Page 94: Linux 操作系统分析

[email protected] Embedded Operating Systems 94

内核对块设备处理程序的支持具有以下特点: 通过 VFS提供统一接口 对磁盘数据进行有效的预读 为数据提供磁盘高速缓存

Page 95: Linux 操作系统分析

[email protected] Embedded Operating Systems 95

用于块设备文件的缺省的文件操作方法

Page 96: Linux 操作系统分析

[email protected] Embedded Operating Systems 96

块设备请求及其优化虽然块设备驱动程序可以一次传送一个单独的

数据块,但是内核并不会为每个要访问的数据块都执行一次 I/O 操作

内核试图把几个块合并在一起,作为一个整体来处理,从而减少磁头的平均移动时间

HOW?

Page 97: Linux 操作系统分析

[email protected] Embedded Operating Systems 97

为读写一个磁盘块的请求生成块设备请求但推迟这个请求执行的时间

这是提高块设备性能的关键机制 当请求发生时,内核检查是否能通过稍微扩展

前一个一直处于等待状态的请求而满足新的请求,从而减少定位的时间,提高效率

Page 98: Linux 操作系统分析

[email protected] Embedded Operating Systems 98

每个块设备驱动程序都维护着自己的请求队列; 每个物理块设备应当有一个请求队列

请求可以以提高磁盘性能的方式进行排序 低级的设备驱动程序一般采用如下策略:

1. 处理请求队列上的第一个请求,并设置设备控制器,以便在数据传送完成时可以产生一个中断,然后就停止

2. 当设备控制器产生中断时,中断处理程序就激活下半部分。3. 下半部分将被处理的请求删除,并继续 1

Page 99: Linux 操作系统分析

[email protected] Embedded Operating Systems 99

驱动程序的编写 有专门的书《 Linux 设备驱动程序》来讲如何

写 Linux 下的驱动程序 中译本有 500多页

我们这里用最简单的例子来尝试驱动程序的编写

Page 100: Linux 操作系统分析

[email protected] Embedded Operating Systems 100

1 ,确定设备名称与主次设备号 ( 动态分配的不指定 )2 ,编写设备文件对内核上层的接口 file_operations

包括 :init, open, release, read, write, ioctl

等3 ,编译并加载设备驱动(两种方法)

3.1 ,静态加载:3.1.1 ,将初始化函数加入内核驱动初始化部分3.1.2 ,修改相应的 Makefile, 增加驱动的目标

文件3.1.3 ,重新编译内核,启用新的内核

Page 101: Linux 操作系统分析

[email protected] Embedded Operating Systems 101

3.2 ,动态加载,先编译成 Linux 模块目标文件,再用 insmod将驱动模块加载 , 还有 rmmod, lsmod 命令,可查看man得知相应的功能。

4 ,在目录 /dev 下建立相应的设备文件。mknod 创建设备对象,参数: 设备名 设备类型 主设备号 次设备号

5 ,在用户态下编写应用程序测试,使用该设备驱动

Page 102: Linux 操作系统分析

[email protected] Embedded Operating Systems 102

一个虚拟的字符驱动程序举例 char_dev.c makefile testchardev.c

设备名定为: char_dev 用命令 insmod char_dev.o 加载 用命令 lsmod察看是否成功加载 使用 dmesg察看主设备号 使用 mknod char_dev c 253 1 在 /dev 目录下创建设

备文件 运行 Testchardev.c测试

Page 103: Linux 操作系统分析

[email protected] Embedded Operating Systems 103

Project7

实现一个虚拟的字符驱动程序