c语言 linux sd_Linux内核组成部分(二)

3a87211591e52b8f17e532264d7e4967.png

设备驱动程序、块设备和字符设备

设备驱动程序用于与系统连接的输入/输出装置通信,如硬盘、软驱、各种接口、声卡等。按照经典的UNIX箴言“万物皆文件”(everything is a file),对外设的访问可利用/dev目录下的设备文件来完成,程序对设备的处理完全类似于常规的文件

  • 字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。相反,此类设备支持按字节/字符来读写数据。举例来说,调制解调器是典型的字符设备。
  • 块设备:应用程序可以随机访问设备数据,程序可自行确定读取数据的位置。硬盘是典型的块设备,应用程序可以寻址磁盘上的任何位置,并由此读取数据。此外,数据的读写只能以块(通常是512B)的倍数进行。与字符设备不同,块设备并不支持基于字符的寻址

网络

网卡也可以通过设备驱动程序控制,但在内核中属于特殊状况,因为网卡不能利用设备文件访问。原因在于在网络通信期间,数据打包到了各种协议层中。在接收到数据时,内核必须针对各协议层的
处理,对数据进行拆包与分析,然后才能将有效数据传递给应用程序。在发送数据时,内核必须首先根据各个协议层的要求打包数据,然后才能发送。

为支持通过文件接口处理网络连接(按照应用程序的观点), Linux使用了源于BSD的套接字抽象。套接字可以看作应用程序、文件接口、内核的网络实现之间的代理

文件系统

Linux系统由数以千计乃至百万计的文件组成,其数据存储在硬盘或其他块设备(例如ZIP驱动、软驱、光盘等)。存储使用了层次式文件系统。文件系统使用目录结构组织存储的数据,并将其他元信息(例如所有者、访问权限等)与实际数据关联起来

内核必须提供一个额外的软件层,将各种底层文件系统的具体特性与应用层(和内核自身)隔离开来。该软件层称为VFS(Virtual Filesystem或Virtual Filesystem Switch,虚拟文件系统或虚拟文件系统交换器)。 VFS既是向下的接口(所有文件系统都必须实现该接口),同时也是向上的接口(用户进程通过系统调用最终能够访问文件系统功能)

550394b125e9a4e4dcbefe2ea4d3d987.png

模块和热插拔

模块用于在运行时动态地向内核添加功能,如设备驱动程序、文件系统、网络协议等,实际上内核的任何子系统几乎都可以模块化

模块还可以在运行时从内核卸载,这在开发新的内核组件时很有用。模块在本质上不过是普通的程序,只是在内核空间而不是用户空间执行而已。模块必须提供某些代码段在模块初始化(和终止)时执行,以便向内核注册和注销模块。另外,模块代码与普通内核代码的权利(和义务)都是相同的,可以像编译到内核中的代码一样,访问内核中所有的函数和数据

缓存

内核使用缓存来改进系统性能。从低速的块设备读取的数据会暂时保持在内存中,即使数据在当时已经不再需要了。在应用程序下一次访问该数据时,它可以从访问速度较快的内存中读取,因而绕
过了低速的块设备。由于内核是通过基于页的内存映射来实现访问块设备的,因此缓存也按页组织,也就是说整页都缓存起来,故称为页缓存(page cache)

对象管理和引用计数

内核中很多地方都需要跟踪记录C语言中结构的实例。尽管这些对象的用法大不相同,但各个不同子系统的某些操作非常类似,例如引用计数。这导致了代码复制。由于这是个糟糕的问题,因此在内核版本2.5的开发期间,内核采用了一般性的方法来管理内核对象。所引入的框架并不只是为了防止代码复制,同时也为内核不同部分管理的对象提供了一致的视图,在内核的许多部分可以有效地使用相关信息,如电源管理

一般性的内核对象机制可用于执行下列对象操作:

  • 引用计数
  • 管理对象链表(集合)
  • 集合加锁
  • 将对象属性导出到用户空间(通过sysfs文件系统)

下列数据结构将嵌入其他数据结构中,用作内核对象的基础

bfef1ad711d544f7b3147f4eccc1aa77.png
k_name是对象的文本名称,可利用sysfs导出到用户空间。sysfs是一个虚拟文件系统,可以将系统的各种属性描述导出到用户空间。 sd即用于支持内核对象与sysfs之间的关联
kref类型为struct kref,用于简化引用计数的管理。我会在下文讨论该结构。
entry是一个标准的链表元素,用于将若干kobject放置到一个链表中(在这种情况下称为集合)。
将对象与其他对象放置到一个集合时,则需要kset。
parent是一个指向父对象的指针,可用于在kobject之间建立层次结构。
ktype提供了包含kobject的数据结构的更多详细信息。其中,最重要的是用于释放该数据结构资源的析构器函数

数据类型

内核使用typedef来定义各种数据类型,以避免依赖于体系结构相关的特性,比如,各个处理器上标准数据类型的位长可能都不见得相同。定义的类型名称如sector_t(用于指定块设备上的扇区编号)、 pid_t(表示进程ID)等

内核定义了若干整数数据类型,不仅明确标明了是有符号数还是无符号数,而且还指定了相关类型的精确位数。例如, __s8__u8分别是有符号(__s8)和无符号(__u8)的8位整数。 __u16__s16__u32__s32__u64__s64的定义类似

源代码中的多处指针都标记为__user,该标识符对用户空间程序设计是未知的。内核使用该记号来标识指向用户地址空间中区域的指针,在没有进一步预防措施的情况下,不能轻易访问这些指针指向的区域。这是因为内存是通过页表映射到虚拟地址空间的用户空间部分的,而不是由物理内存直接映射的。因此内核需要确保指针所指向的页帧确实存在于物理内存中。


首先恭喜您,能够认真的阅读到这里,如果对部分理解不太明白,建议先将文章收藏起来,然后对不清楚的知识点进行查阅,然后在进行阅读,相应你会有更深的认知。如果您喜欢这篇文章,就点个赞或者【关注我】吧!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值