不管是Windows还是Linux,驱动程序都扮演着重要的角色。应用程序只能通过驱动程序才能同硬件设备或系统内核通讯。Linux内核对不同的系统定义了标准的接口(API),应用程序就是通过这些标准的接口来操作内核和硬件。驱动可以被编译的内核中(build-in),也可以做为内核模块(Module)存在于内核的外面,需要的时候动态插入到内核中运行。

就像你学习操作系统概念时所了解的那样,Linux内核也分为几个大的部分:进程管理、内存管理、文件系统、设备控制、网络系统等,参考图1-1。

这里就不对Linux系统内核的各个部分做过多的介绍了,在后面的学习中你就会逐渐地对这些概念有个更深入的了解。其实Linux内核的精髓远不止这些,对于一个Linux内核的爱好者或开发者来说,最好详细的浏览内核源代码,订阅Linux内核相关的邮件列表,或是登陆Linux开发社区。更多的信息,请登陆Linux内核官方网站:http://www.kernel.org

一个简单的驱动

下面我们来编写第一个驱动程序,它很简单,在运行时会输出‘Hello World’消息。

// hello.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

static int __init hello_init(void)
{
printk(KERN_ALERT "Hello World!n");
return 0;
}

static void __exit hello_exit(void)
{
printk(KERN_ALERT "Goodbye World!n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

这就是一个简单的驱动程序,它什么也没做,仅仅是输出一些信息,不过对于我们来说这已经足够了。保存这个程序,命名为hello.c。在写一个Makefile文件用来编译它,Makefile和hello.c文件保存在同一个目录下。

##Makefile
ifneq ($(KERNELRELEASE),)
MODULE_NAME = helloworld
$(MODULE_NAME)-objs := hello.o
obj-m := $(MODULE_NAME).o
else
KERNEL_DIR = /lib/modules/`uname -r`/build
MODULEDIR := $(shell pwd)

.PHONY: modules
default: modules

modules:
make -C $(KERNEL_DIR) M=$(MODULEDIR) modules

clean distclean:
rm -f *.o *.mod.c .*.*.cmd *.ko
rm -rf .tmp_versions
endif

编译并运行这个模块:

//需要root权限来运行
make
insmod helloworld.ko
rmmod helloworld.ko

尽管我们对它的一些细节还不够了解,它确实神奇的工作了,这个Hello World信息输出到了屏幕终端上(不是VT),www.britepic.org或者系统的Kenrel log里(/var/log/messages),你可以通过运行dmesg来看到这些信息。

驱动基础
我们通过分析上面的代码来了解一个驱动程序的基本概念。

头文件
就像你写C程序需要包含C库的头文件那样,Linux内核编程也需要包含Kernel头文件,大多的Linux驱动程序需要包含下面三个头文件:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

init.h 定义了驱动的初始化和退出相关的函数,
kernel.h 定义了经常用到的函数原型及宏定义
module.h 定义了内核模块相关的函数、变量及宏。
初始化
任何一个驱动都去需要提供一个初始化函数,当驱动加载到内核中时,这个初始化函数就会被自动执行,初始化的函数原型定义如下:

typedef int (*initcall_t)(void);

驱动程序是通过module_init宏来声明初始化函数的:

static int __init hello_init(void)
{
printk(KERN_ALERT "Hello World!n");
return 0;
}
module_init(hello_init);

__init 宏告诉编译器如果这个模块被编译到内核则把这个函数放到(.init.text)段,这样当函数初始化完成后这个区域可以被清除掉以节约系统内存。Kenrel启动时看到的消息“Freeing unused kernel memory: xxxk freed”同它有关。
初始化函数是有返回值的,只有在初始化成功是才返回0,否则返回错误码(errno)。

卸载
如果驱动程序编译成模块(动态加载)模式,那么它需要一个清理函数。当移除一个内核模块时这个函数被调用执行清理工作。清理函数的函数原型定义为:

typedef void (*exitcall_t)(void);

驱动程序是通过module_exit宏来声明清理函数的:

static void __exit hello_exit(void)
{
printk(KERN_ALERT "Goodbye World!n");
}
module_exit(hello_exit);

同__init类似,如果驱动被编译进内核,则__exit宏会忽略清理函数,因为编译进内核的模块不需要做清理工作。显然,__init和__exit对动态加载的模块是无效的。

版权信息
Linux内核是按照GPL发布的,同样Linux的驱动程序也要提供版权信息,否则当加载到内核中是系统会给出警告信息。Hello World例子中的版权信息是GPL。

MODULE_LICENSE("GPL");

后续
这里你了解了一个驱动程序的基本框架,所有的驱动都会包含这些内容。这里我们没有对Linux 驱动程序的编译系统做详细的介绍,因为它相对C应用程序的编译有些复杂。Linux2.6内核采用Kbuild系统做编译,下一章你会了解到Kbuild的详细内容。

转载于:https://www.cnblogs.com/hnrainll/archive/2011/06/14/2080963.html

linux驱动开发框架相关推荐

  1. 【正点原子MP157连载】第二十章 字符设备驱动开发-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  2. 点亮 Linux 驱动开发路上的第一个灯

    Linux下的任何外设驱动,最终都是要配置相应的硬件寄存器.前面的文章中介绍了新旧字符设备的驱动开发框架,也介绍了IMX6ULL处理器GPIO的工作原理及配置方法,本篇我们将实际操作一个GPIO,点亮 ...

  3. 2021年Linux技术总结(四):Linux 驱动

    一.裸机驱动开发流程 ​ 所谓裸机在这里主要是指系统软件平台没有用到操作系统.在基于ARM处理器平台的软件设计中,如果整个系统只需要完成一个相对简单而且独立的任务,那么可以不使用操作系统,只需要考虑在 ...

  4. linux驱动:音频驱动(六)ASoc之codec设备

    linux驱动:音频驱动(六)ASoc之codec设备

  5. linux驱动:音频驱动(五)ASoc之codec驱动

    linux驱动:音频驱动(五)ASoc之codec驱动

  6. linux驱动:音频驱动(四)ASoc之machine设备

    linux驱动:音频驱动(四)ASoc之machine设备

  7. Linux驱动之LCD驱动编写

    在Linux驱动之内核自带的S3C2440的LCD驱动分析这篇博客中已经分析了编写LCD驱动的步骤,接下来就按照这个步骤来字尝试字节编写LCD驱动.用的LCD屏幕为tft屏,每个像素点为16bit.对 ...

  8. 【Linux 驱动】第九章 与硬件通信

    在学习有关I/O总线的内容时,最好先看看相关的知识:从PC总线到ARM的内部总线 一,I/O 端口和 I/O 内存 每种外设都是通过读写寄存器来进行控制. 大部分外设都有几个寄存器,不管是在内存地址空 ...

  9. 8188无线网卡驱动linux,rtl8188eu linux驱动

    rtl8188eu linux驱动是一款适用于rtl8188eu系列的无线网卡驱动程序,瓜分没有提供的Linux驱动程序,可以下载这个安装,就可以在Linux下上网了. 安装方法 首先请确认你的无线网 ...

最新文章

  1. 【转】ActiveMQ消息传送机制以及ACK机制详解
  2. 7小时44分最佳,睡多睡少都不好,养成习惯也没用
  3. (chap3 数据链路) 介质型网络
  4. 绥化a货翡翠,拉萨a货翡翠
  5. InnoSQL/MySQL并行复制的实现与配置
  6. 程序员35岁辞职后都做了什么工作三位过来人透露了实情,引热议
  7. AR 圈最大收购案 Ubimax 10 亿“卖身”背后:究竟什么才是真正值钱的东西?
  8. 几楼电路精灵——手机端 原理图 PCB
  9. 迅捷PDF虚拟打印机怎么安装和使用
  10. 入门小白不到三个月就学会了用maya软件如何制作动画
  11. cad画流程图的插件_CAD高手教您画工艺流程图设计一些列图
  12. 【马仔创业感悟】公司售前和售后维护制度思考
  13. 年产4000吨果味奶糖生产车间工艺设计
  14. Elasticsearch相关操作梳理
  15. Nuscenes——环视相机下BEV时序融合:前后帧空间对齐操作
  16. 在线绘制函数图像和在线图标绘制网址
  17. 从零到熟悉,带你掌握Python len() 函数的使用
  18. 创意svg+css3相册图文展示
  19. Zero-Shot Learning学习笔记 -- CVPR_2022_MSDN: Mutually Semantic Distillation Network for Zero-Shot Learn
  20. ae怎么设置gpu渲染_AE/PR mac版如何开启GPU加速渲染?

热门文章

  1. Oracle scheduler job管理
  2. class action extends mysql{_java Action 请求封装(二)
  3. Eclipse中设置自动生成的author,date等注释
  4. 如何把include_type_name的值设置为true
  5. 前端制作动画的几种方式(css3,js)
  6. ORA-14402: 更新分区关键字导致分区的更改
  7. python快速入门 数据输出和基本类型 常用的循环遍历等
  8. 工作中常用到的ES6语法
  9. 乐观锁、悲观锁,这一篇就够了!
  10. Lucene就是这么简单