驱动程序的作用:

简单来说 驱动程序就是使计算机与设备通信的特殊的代码,在作单片机时候(无OS)我们自己定义接口及自定义的结构来操作相关硬件,而在有OS的模式下我们操作的硬件是去实现对应的接口(这些接口是已定义好的,我们需要实现这些接口)而无需自己定义接口,这样既能正确的控制设备。又能很好的维护(如果需要升级驱动,上边的应用程序不需要改变)

编写驱动考虑的因素

  1. 提供给用户更多的选项
  2. 保持用户操作的简单性
  3. 编写驱动的时间

驱动分类:

  1. 字符设备:能够像字节流(类似文件)一样被访问的设备(至少实现open, close, read ,write等功能)
  2. 快设备:    用户空间接口与字符设备相同, 内部实与字符设备完全不同(可以被随即访问,一般在类UNIX系统中快设备的读取每次只能读一整块在linux可以操作任意字节)
  3. 网络设备:网络通路通过网络设备形成,能够与主机交换数据的设备

内核功能划分:

  1. 进程管理(PM):进程的创建与撤销,在单个或者多个CPU上实现多进程的抽象
  2. 内存管理(MM):管理内存分配及回收的策略
  3. 文件系统(FS/VFS): Linux 非常依赖于文件系统,内核在没有结构的硬件系统上构造结文件系统,而文件抽象在整个系统中会广泛使用,Linux支持多种文件系统类型
  4. 设备控制:驱动程序,操控硬件以及相应总线设备
  5. 网络(NET): 在网络接口于应用程序之间传输数据。

好了 理论行得东西介绍的差不多了,下边说点有用的,内核的驱动可以做成模块在需要的时候装载,在不需要的时候卸载
我们在编写用户程序的时候总喜欢从编写hello world 写起 , 在内核驱动模块也是一样,下边是一个hello_world的一个模块

  1. //hello_world.c
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. MODULE_LICENSE("GPL");
  5. static int hello_init(void)
  6. {
  7. printk(KERN_ALERT "hello module\n");
  8. return 0;
  9. }
  10. static void hello_exit(void)
  11. {
  12. printk(KERN_ALERT "hello module exit\n");
  13. }
  14. module_init(hello_init);
  15. module_exit(hello_exit);

以及对应的Makefile

  1. ifneq ($(KERNELRELEASE),)
  2. # call from kernel build system
  3. obj-m   := hello_world.o
  4. #if we need more than one source code to build the module
  5. #we should use the variable below:  example: modules-objs := file1.o file2.o
  6. modules-objs :=
  7. else
  8. #kernel PTAH
  9. KERNELDIR ?= /lib/modules/$(shell uname -r)/build
  10. PWD       := $(shell pwd)
  11. modules:
  12. $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
  13. endif
  14. clean:
  15. rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

有几点与用户空间程序不同的地方

  1. 模块程序没有main函数(那么程序入口在哪里?)
  2. 打印函数使用的printk 而不是用户空间的printf 而且使用方式不一样
  3. 模块的编译不是通常的方式
  4. 头文件不是常见的那些头文件
  5. 以及编译之后不会产生可执行文件,而是 .ko 文件
    ...

模块没有main函数,在装载模块 insmod 时会调用module_init注册的函数 此处为hello_init
在模块卸载remod时 会调用module_exit注册的函数 此处为hello_exit
在module_init 注册的函数主要是进行初始化,分配内存, 注册设备等
而module_exit中注册的函数与之相反, 设备注销, 释放内存等
具体的编译模块的Makefile我在另一篇文章中有说到 此处不再赘述
内核的打印函数使用printk去打印信息, printk不支持浮点类型, 在printk中可以加入信息级别有7中

  1. #define KERN_EMERG    "<0>"    /* system is unusable */
  2. #define KERN_ALERT    "<1>"    /* action must be taken immediately */
  3. #define KERN_CRIT     "<2>"    /* critical conditions */
  4. #define KERN_ERR      "<3>"    /* error conditions */
  5. #define KERN_WARNING  "<4>"    /* warning conditions */
  6. #define KERN_NOTICE   "<5>"    /* normal but significant */
  7. #define KERN_INFO     "<6>"    /* informational */
  8. #define KERN_DEBUG    "<7>"    /* debug-level messages */

对应与不同的错误等级 选择不懂的option, 并做不同的处理, 小于一定等级的信息会直接打印到终端(非X-window下的终端),可以使用 dmesg 来查看全部的打印信息
编译内核的头文件是在/lib/modules/$(shell uname -r)/build/include下得,而不是用户模式下得/usr/include
编译后不会生产可执行文件,会生成一个.ko的文件
使用 insmod  xxx .ko去装载模块
使用 lsmod 去查看已装载的模块
使用 rmmod  xxx  去卸载相应模块(卸载是不带.ko)

Linux驱动编程 step-by-step (一)驱动程序的作用相关推荐

  1. Linux驱动编程 step-by-step

    第三次看了LDD3了(虽然现在已经是kernel3.0但从这本书商还是能学到很多) 每次都有一些收获 现在终于能够写一写代码了 驱动程序的作用: 简单来说 驱动程序就是使计算机与设备通信的特殊的代码, ...

  2. Linux驱动编程 step-by-step (二) 简单字符设备驱动

    简单字符设备驱动 1.主次设备号 主设备号标识设备连接的的驱动,此设备好由内核使用,标识在相应驱动下得对应的设备 在linux中设备号是一个32位的dev_t类型 typedef __u32    _ ...

  3. Linux驱动编程 step-by-step (二)

    简单字符设备驱动 1.主次设备号 主设备号标识设备连接的的驱动,此设备好由内核使用,标识在相应驱动下得对应的设备 在linux中设备号是一个32位的dev_t类型 typedef __u32    _ ...

  4. linux驱动编程——ch340x驱动移植

    Linux驱动编程--ch340x驱动移植 主要概念: ​ ch340x驱动移植 ​ 作为通用器件,厂商都有提供适配各种平台的驱动.linux一般会提供驱动源码. ​ 一般所谓驱动移植,就是将厂商的驱 ...

  5. Linux驱动编程视频教程

    本视频教程主要介绍字符驱动.杂项设备.中断.调试驱动的基本方法以及驱动的移植等. Linux驱动编程视频教程: 链接:https://pan.baidu.com/s/1Yn5d4w9uudb4tGDT ...

  6. Linux驱动编程(驱动程序基石)(下)

    一.中断的线程化处理 复杂.耗时的事情,尽量使用内核线程来处理.上节视频介绍的工作队列用起来挺简单,但是它有一个缺点:工作队列中有多个 work,前一个 work 没处理完会影响后面的 work.解决 ...

  7. Linux驱动编程(驱动程序基石)(上)

    一.休眠与唤醒 要休眠的线程,放在 wq 队列里,中断处理函数从 wq 队列里把它取出来唤醒.所以,我们要做这几件事: ① 初始化 wq 队列 ② 在驱动的 read 函数中,调用 wait_even ...

  8. Linux驱动编程 step-by-step (五)主要的文件操作方法实现

    主要的文件操作方法实现 文件操作函数有很多的操作接口,驱动编程需要实现这些接口,在用户编程时候系统调用时候会调用到这些操作 [cpp] view plaincopy struct file_opera ...

  9. linux驱动read函数 copytouser,Linux驱动编程 step-by-step (五)主要的文件操作方法实现...

    主要的文件操作方法实现 文件操作函数有很多的操作接口,驱动编程需要实现这些接口,在用户编程时候系统调用时候会调用到这些操作 structfile_operations { ... loff_t (*l ...

最新文章

  1. 北京、广州同时开课 | 临床基因组学数据分析实战助力解析Case,快速发表文章...
  2. 归档 OmniFocus 中已完成的任务到 印象笔记 Evernote
  3. 深度解密Go语言之unsafe
  4. 专科生,还有未来吗?
  5. TikZ绘图示例——尺规作图: 鸭蛋圆形的近似画法
  6. [转] Js获取 本周、本月、本季度、本年、上月、上周、上季度、去年时间段
  7. OpenCV3.0.0 + VS2012 的环境搭建
  8. Xshell 6安装和使用教程
  9. 【Android安全】Oneplus 5T 救砖 刷机 root并通过SafetyNet Attestation检测
  10. 慕尼黑工业大学计算机博士申请条件,德国慕尼黑工业大学博士生申请条件
  11. 299. 猜数字游戏【我亦无他唯手熟尔】
  12. 2021年电子竞赛四天三夜征程—-信号失真度测量装置(A题)
  13. C++(11):多线程同步packaged_task
  14. 天津医科大学计算机研究生吧,天津医科大学
  15. XXXXXXXXXXX学校“专家问诊课”活动方案
  16. svg去掉黑色自带背景图
  17. 高颜值游戏专属蓝牙耳机推荐,双11认准这五款蓝牙耳机绝不踩雷
  18. U盘做启动盘后 容量变小怎么恢复?
  19. 自己的电脑出现在别人的电脑的网络位置中
  20. C++——malloc()

热门文章

  1. boost::mp11::construct_from_tuple相关用法的测试程序
  2. boost::log::parse_formatter用法的测试程序
  3. boost::hana::monadic_fold_left用法的测试程序
  4. Boost:测试BOOST_BIND_NO_PLACEHOLDERS的程序
  5. VTK:可视化算法之Office
  6. VTK:Rendering之Rainbow
  7. C++检查给定数字是否为4的幂的算法实现(附完整源码)
  8. OpenGL 颜色Colors
  9. C++绝不在构造和析构过程中调用virtual函数
  10. c++产生死锁的必要条件?已经如何预防死锁?