嵌入式Linux驱动程序设计(二)

[ 998 查看 / 1 回复 ]

内核下一个数据采集卡设备驱动的具体实现

3.1 背景知识

前面提到过linux是基于文件的系统,其设备驱动也是做为一个文件的形式存在的,也就是说我们对设备的操作就象对文件的操作那样,甚至它们还具有完全一致的接口。在具体介绍这个接口之前,我们首先来了解点背景知识:
3.1.1用户空间和内核空间
我们知道模块运行在所谓的内核空间,而应用程序运行在所谓的用户空间里,这个是操作系统的基本理念之一。 实际上,操作系统的是为程序提供一个计算机硬件的一致视图。但除此以外,操作系统还必须负责程序的独立操作以及资源不受非法访问,这些都是在现在CPU的基础下得以实现的。CPU通过门来实现这种保护,也让我们的进程从在不同的状态见切换。在linux下,只使用了CPU的两种级别,即最高级和最低级。内核运行在最高级也称做管理员模式,在这一级的程序具有任何权利,可以享受系统的所有操作;而应用程序运行在最低级即所谓的用户模式,这一级别的程序运行受到某些限制。而内核空间和用户空间就是上面所提到的两种执行模式。
3.1.2驱动程序与内核模块
    Linux内核是作为Monolithic architecture (单内核体系结构) 而实现的,为了获得 Microkernel architecture (微内核体系结构) 带来的可扩展性和可维护性,Linux 引入了模块 (module) 机制,(比较准确的说法是 Loadable Kernel Module, 可装载内核模块),藉此来保证内核的紧凑性和Linux本身固有的单一体系结构的优点——上下文切换速度快。
在Linux中,用户(通常需要root权限)通过modutils软件包中提供的工具,动态地将模块(如网络驱动等)插入、移出内核。这样,内核的功能可以动态地添加和删除,却不需要每次都经过冗长的关机/重启过程。因为模块运行的环境是内核,因而它具有内核特权,模块编程也就是内核编程,它是Linux Kernel Hacking 的主要工具。我们也知道设备驱动一般都需要直接的访问设备,访问系统资源,因而通常工作在内核空间,故在 linux下驱动程序的开发通常也就是进行内核模块编程,它们具有同样的技巧。
3.1.3核心模块与应用程序

应用程序从头到尾执行单个任务,而模块确只是预先注册自己以便服务与将来的某个请求,然后,它的“main”函数就立即结束。换句话说,函数init_moudule(模块的入口点)的任务就是为以后调用模块函数做准备,而模块的第二个入口点,clean_moudule就是在模块即将卸载前调用它,告诉内核“我要离开了,不要再让我做任何事情了”。还有一个较大的区别就是,模块不和函数库连接,因此在源文件中不能包含通常的头文件,内核模块只能使用作为内核一部分的函数。将模块链接到内核的过程如下图:


    

图3.1.3 将模块链接到内核


还有一个较大且该引起我们注意的就是:他们处理错误的方式不一样,在应用程序中段错误是无害的,而且总可以使用调试程序跟中这个错误所在,而在内核编程中这个是不可以想象的,而且这通常都会导致致命的错误---系统死掉,这个在我们的模块调试一节中将有所介绍
TOP
凌阳教育嵌入式培训