Linux内核学习2:内核模块的开发
2014-09-11 11:08
330 查看
1:关于内核模块开发的问题之前要知道Linux内核模块是怎么来的?是怎么一回事?
Linux内核的整体结构非常庞大,包括的组件非常多,如何使用需要的组件?
方法一:把所有的组件都编译进内核文件,即:zlmage或bzlmage
但是会出现两个问题:一是:生成内核文件过大
二是:如果要添加或删除某个组件,需要重新编译整个内核
方法二:我们希望的是有一种机制让内核文件本身不包含某组件,而是在该组件需要使用的时候,动态的添加到正在运行的内核中?
这就是我们提到的内核模块的概念。
2:什么是内核模块?
内核模块是具有独立功能的程序。它可以被单独编译,但是不能单独运行,它的运行必须被链接到内核,并作为内核的一部分在内核空间中运行。
模块编程和内核版本密切相连,因为不同的内核版本中某些函数的函数名会发生变化,因此模块编程也可以说是内核编程
3:内核模块的特点
模块本身并不被编译进内核文件,可以根据需要,在内核运行期间动态的安装或卸载
分析一段内核模块程序:
相对于用户空间应用程序的开发,内核开发有一些其独特之处。最主要的差异有如下几种:
1)内核编程时候既不能访问C库也不能访问标准的C头文件
2)内核编程必须使用CUN C。
3)内核编程缺乏像用户空间那样的内存保护机制
4)内核给每一个进程只有一个很小的定长栈
5)由于内核支持异步中断、抢占和SMP。因此必须时刻注意同步和并发。
继续上面的几点,我们首先有疑问,既然内核编程不能访问C库也不能访问标准的C头文件,且编程必须使用GNU C。那么GNU C到底是什么,和标准C有什么区别?
△
首选回答第一个问题:为什么不能访问C库和访问标准C头文件?
这个问题其实就是涉及到了先有蛋还是先有鸡的问题,但是最主要的还是对内核而言,完整的C库,哪怕是一个子集,都太大且效率太低。
既然不能够使用,那么C库函数带来的方便就不能够被我们所用,其实大部分C库函数都已经在内核中实现了。比如操作字符串的函数就位于lib/string.c文件中,只要包含<linux/string.h>头文件就可以了。
△
上面还提到了一个关于GNU C的问题,那什么是GNU C呢?
在说GNU C之前,先了解下gcc,gcc其实就是多种GNU编译器的集合,它包含的C编译器既可以编译内核,也可以编译Linux系统上用C语言写的其他代码。而GCC之前就叫做GNU C
△
内核开发中无libc库或无标准头文件
所以在内核开发中所提到的头文件,都指的是组成内核代码树的内核头文件(之前提到的lib目录)。
内核源代码不能包括外部头文件,就像它们不能用外部库一样
基本的头文件集位于内核源代码树顶级目录下的include目录中。
例如头文件<linux/inotify.h>位于include/linux/inotify.h
Linux内核的整体结构非常庞大,包括的组件非常多,如何使用需要的组件?
方法一:把所有的组件都编译进内核文件,即:zlmage或bzlmage
但是会出现两个问题:一是:生成内核文件过大
二是:如果要添加或删除某个组件,需要重新编译整个内核
方法二:我们希望的是有一种机制让内核文件本身不包含某组件,而是在该组件需要使用的时候,动态的添加到正在运行的内核中?
这就是我们提到的内核模块的概念。
2:什么是内核模块?
内核模块是具有独立功能的程序。它可以被单独编译,但是不能单独运行,它的运行必须被链接到内核,并作为内核的一部分在内核空间中运行。
模块编程和内核版本密切相连,因为不同的内核版本中某些函数的函数名会发生变化,因此模块编程也可以说是内核编程
3:内核模块的特点
模块本身并不被编译进内核文件,可以根据需要,在内核运行期间动态的安装或卸载
分析一段内核模块程序:
#include <linux/init.h> #include <linux/module.h> static int hello_init(void) { printk(KERN_WARNING"hello world!\n"); rerurn 0; } static void hello_exit(void) { pintk(KERN_INFO"goodbye,world\n"); } module_init(hello_init);//模块加载函数 module_exit(hello_exit);//模块卸载函数就上面简单的内核模块程序中出现了与我们传统所见的C不同的代码,这地方非常有必要的了解一下内核开发的特点:
相对于用户空间应用程序的开发,内核开发有一些其独特之处。最主要的差异有如下几种:
1)内核编程时候既不能访问C库也不能访问标准的C头文件
2)内核编程必须使用CUN C。
3)内核编程缺乏像用户空间那样的内存保护机制
4)内核给每一个进程只有一个很小的定长栈
5)由于内核支持异步中断、抢占和SMP。因此必须时刻注意同步和并发。
继续上面的几点,我们首先有疑问,既然内核编程不能访问C库也不能访问标准的C头文件,且编程必须使用GNU C。那么GNU C到底是什么,和标准C有什么区别?
△
首选回答第一个问题:为什么不能访问C库和访问标准C头文件?
这个问题其实就是涉及到了先有蛋还是先有鸡的问题,但是最主要的还是对内核而言,完整的C库,哪怕是一个子集,都太大且效率太低。
既然不能够使用,那么C库函数带来的方便就不能够被我们所用,其实大部分C库函数都已经在内核中实现了。比如操作字符串的函数就位于lib/string.c文件中,只要包含<linux/string.h>头文件就可以了。
△
上面还提到了一个关于GNU C的问题,那什么是GNU C呢?
在说GNU C之前,先了解下gcc,gcc其实就是多种GNU编译器的集合,它包含的C编译器既可以编译内核,也可以编译Linux系统上用C语言写的其他代码。而GCC之前就叫做GNU C
△
内核开发中无libc库或无标准头文件
所以在内核开发中所提到的头文件,都指的是组成内核代码树的内核头文件(之前提到的lib目录)。
内核源代码不能包括外部头文件,就像它们不能用外部库一样
基本的头文件集位于内核源代码树顶级目录下的include目录中。
例如头文件<linux/inotify.h>位于include/linux/inotify.h
相关文章推荐
- Linux内核驱动学习(三)----内核模块基础 | 设计 | 可选项
- Linux学习之内核模块开发详解
- linux 学习- 编程基础之内核模块开发
- Linux内核与驱动开发学习总结:内核访问外设IO.map_desc和ioremap(七)
- 嵌入式学习-驱动开发前奏-lesson1-内核模块相关知识
- linux 设备驱动开发学习笔记(一):最简单的内核模块
- linux内核学习第三天——内核模块的加载
- Linux内核驱动学习1-模块开发
- ARM学习笔记——内核模块开发
- Ubuntu 14.04 Linux内核版本3.16.0内核模块开发Makefile文件样板
- [树莓派内核学习]内核模块开发
- Linux学习之内核模块开发详解
- Linux内核学习-内核模块参数module_param
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】全面解析Linux内核的同步与互斥机制--互斥篇
- 开发内核模块过程中的问题总结
- 驱动编程学习----内核模块与应用程序区别
- Linux2.6下开发简单的可加载内核模块
- Ubuntu/Debian 之内核模块开发准备
- [zz]Ubuntu/Debian 之内核模块开发准备
- 有关 Linux 下内核模块的开发方式的记录