热门关键字:  ubuntu  分区  Fedora  linux系统进程  函数

当前位置 :| 主页>Linux教程>内核研究>

Linux操作系统内核模块与用户程序对比

来源: 作者: 时间:2007-04-07 Tag: 点击:
代码空间

内存管理是一个非常复杂的课题。O'Reilly的《Understanding The Linux Kernel》绝大部分都在 讨论内存管理!我们 并不准备专注于内存管理,但有一些东西还是得知道的。

如果你没有认真考虑过内存设计缺陷意味着什么,你也许会惊讶的获知一个指针并不指向一个确切的内存区域。当一个进程建立时,内核为它分配一部分确切的实际内存空间并把它交给进程,被进程的代码,变量,堆栈和其它一些计算机学的专家才明白的东西使用[4]。这些内存从$0$ 开始并可以扩展到需要的地方。这些内存空间并不重叠,所以即使进程访问同一个内存地址,例如0xbffff978,真实的物理内存地址其实是不同的。进程实际指向的是一块被分配的内存中以0xbffff978 为偏移量的一块内存区域。绝大多数情况下,一个进程像普通的"Hello, World"不可以访问别的进程的 内存空间,尽管有实现这种机制的方法。我们将在以后讨论。

内核自己也有内存空间。既然一个内核模块可以动态的从内核中加载和卸载,它其实是共享内核的 内存空间而不是自己拥有独立的内存空间。因此,一旦你的模块具有内存设计缺陷,内核就是内存设计缺陷了。如果你在错误的覆盖数据,那么你就在破坏内核的代码。这比现在听起来的还糟。所以尽量小心谨慎。

顺便提一下,以上我所指出的对于任何单整体内核的操作系统都是真实的[5]。 也存在模块化微内核的操作系统,如 GNU Hurd 和 QNX Neutrino。

一种内核模块是设备驱动程序,为使用硬件设备像电视卡和串口而编写。在Unix中,任何设备都被当作路径/dev 的设备文件处理,并通过这些设备文件提供访问硬件的方法。设备驱动为用户程序访问硬件设备。举例来说,声卡设备驱动程序es1370.o将会把设备文件 /dev/sound同声卡硬件Ensoniq IS1370联系起来。这样用户程序像 mp3blaster 就可以通过访问设备文件/dev/sound 运行而不必知道那种声卡硬件安装在系统上。

Major and Minor Numbers

让我们来研究几个设备文件。这里的几个设备文件代表着一块主IDE硬盘上的头三个分区:

# ls -l /dev/hda[1-3]
brw-rw---- 1 root disk 3, 1 Jul 5 2000 /dev/hda1
brw-rw---- 1 root disk 3, 2 Jul 5 2000 /dev/hda2
brw-rw---- 1 root disk 3, 3 Jul 5 2000 /dev/hda3

注意一下被逗号隔开的两列。第一个数字被叫做主设备号,第二个被叫做从设备号。主设备号决定使用何种设备驱动程序。每种不同的设备都被分配了不同的主设备号;所有具有相同主设备号的设备文件都是被同一个驱动程序控制。上面例子中的 主设备号都为3,表示它们都被同一个驱动程序控制。

从设备号用来区别驱动程序控制的多个设备。上面例子中的从设备号不相同是因为它们被识别为几个设备。

设备被大概的分为两类:字符设备和块设备。区别是块设备有缓冲区,所以它们可以对请求进行优化排序。 这对存储设备尤其重要,因为读写相邻的文件总比读写相隔很远的文件要快。另一个区别是块设备输入和输出都是以数据块为单位的,但是字符设备就可以自由读写任意量的字节。大部分硬件设备为字符设备,因为它们不需要缓冲区和数据不是按块来传输的。你可以通过命令ls -l输出的头一个字母识别一个 设备为何种设备。如果是'b' 就是块设备,如果是'c'就是字符设备。以上你看到的是块设备。这儿还有一些字符设备文件(串口):

crw-rw---- 1 root dial 4, 64 Feb 18 23:34 /dev/ttyS0
crw-r----- 1 root dial 4, 65 Nov 17 10:26 /dev/ttyS1
crw-rw---- 1 root dial 4, 66 Jul 5 2000 /dev/ttyS2
crw-rw---- 1 root dial 4, 67 Jul 5 2000 /dev/ttyS3

如果你想看一下已分配的主设备号都是些什么设备可以看一下文件 /usr/src/linux/Documentation/devices.txt。

系统安装时,所有的这些设备文件都是由命令mknod建立的。去建立一个新的名叫 coffee',主设备号为12和从设备号为2的设备文件,只要简单的 执行命令mknod /dev/coffee c 12 2。你并不是必须将设备文件放在目录 /dev中,这只是一个传统。Linus本人是这样做的,所以你最好也不例外。但是,当你测试一个模块时,在工作目录建立一个设备文件也不错。只要保证完成后将它放在驱动程序找得到的地方。

我还想声明在以上讨论中隐含的几点。当系统访问一个系统文件时, 系统内核只使用主设备号来区别设备类型和决定使用何种内核模块。系统 内核并不需要知道从设备号。内核模块驱动本身才关注从设备号,并用之来 区别其操纵的不同设备。

另外,我这儿提到的硬件是比那种可以握在手里的PCI卡稍微抽象一点的东西。看一下下面的两个设备文件:

% ls -l /dev/fd0 /dev/fd0u1680
brwxrwxrwx  1 root floppy  2, 0 Jul 5 2000 /dev/fd0
brw-rw----  1 root floppy  2, 44 Jul 5 2000 /dev/fd0u1680

你现在立即明白这是快设备的设备文件并且它们是有相同的驱动内核模块来操纵(主设备号都为2))。你也许也意识到它们都是你的软盘驱动器,即使你实际上只有一个软盘驱动器。为什么是两个设备文件?因为它们其中的一个代表着你的1.44 MB容量的软驱,另一个代表着你的1.68 MB容量的,被某些人称为“超级格式化”的软驱。这就是一个不同的从设备号代表着相同硬件设备的例子。请清楚的意识到我们提到的硬件有时可能是非常抽象的。




相关文章:
精通initramfs构建step by step
Linux利用kexec迅速切换内核
进程上下文VS中断上下文
内核通知链 学习笔记
linux spi子系统驱动分析
menuconfig 配置选项
《Linux操作系统内核实习》之练习一
udev详解
什么叫微内核,宏内核?
Linux 信号signal处理机制
开发简单的 Linux2.6 内核模块
删除内核的perl脚本
Linux2.6内核usb gadget驱动移植
GCC hacks in the Linux kernel
iomem
kernel学习的想法
让自己的驱动支持udev
linux内核编译步骤
内核的等待队列
Linux内核wait_queue深入分析
升级和删除内核
SD卡驱动分析2
Linux Kernel VDSO本地权限提升漏洞
内核中的TCP的追踪分析-15-TCP(IPV4)的客户端与
linux 2.6内核可加载模块的编译
内核模块HelloWorld
在环回接口上发送一个数据报
ARP初始化
1分钟编译FreeBSD内核
linux设备模型之uart驱动架构分析