最近有想深入驱动和内核的想法,所以开始学习ldd3,参考着写一篇学习笔记
背景知识
什么是驱动
驱动在Linux内核中担任着特殊的角色,像是一个黑箱,隐藏掉设备工作的具体细节,并且具有模块化的特点,可以和内核的其他部分分开编译,并且可以随时装载卸载。
the role of a device driver is providing mechanism, not policy
mechanism指的是提供什么样的方法,policy指的是这些方法可以怎样使用,将这两个问题分开解决,用程序不同的部分甚至是不同的程序去实现,可以使开发变得更简单。
书中举了一个很简单的例子可以帮助很好的理解,Linux图形界面显示就可以分为两部分,一部分是X Server用以驱动显卡并给替它程序提供接口,另一部分就是我们比较熟悉的窗口管理器(比如我现在用的gnome-session),在之前安装arch linux的时候有很深的体会。
When writing drivers, a programmer should pay particular attention to this fundamental concept: write kernel code to access the hardware, but don’t force particular policies on the user, since different users have different needs.
这句话很关键,驱动程序只需要提供调用硬件的接口就可以了,并且越是policy free就越有利于实现应用可以在不同的环境下运行
内核浅析
在Unix系统中,进程会请求很多系统资源,比如cpu算力,内存,网络或者是其他资源,内核,简单来说,就是一堆可执行的代码,负责管理这些请求。内核大致可以分为以下几个部分:
进程管理
管理创建和销毁进程,进程之间的通信或者是cpu的分配
内存管理
内存管理其负责为程序分配虚拟内存
文件系统
以前看过这样一句话,几乎Unix系统中的一切都可以当作文件来看
设备控制
提供驱动管理,就是目前学习的重点
网络
模块化
Each piece of code that can be added to the kernel at runtime is called a module.
模块可以通过insmod
装载并且可以通过rmmod
卸载
模块也有很多种类,但分类的方式并不绝对,本书中分为了三类
- a char module
- a block module
- a network module
内核中的各种功能,无论是硬件还是软件,都是模块化的
安全问题
如果内核存在安全漏洞,整个系统就是不安全的。系统通过调用init_module来检测用户是否有权限,也只有有权限的用户才可以装载模块
从hello world开始
第一个程序惯例从hello world
开始,先写一个很简单的程序,即使没有任何内核基础也能看出大概意思来
1 | //hello.c |
这个模块定义了两个函数,一个在模块载入(通过module_init
加载)的时候调用,一个在模块卸载(通过module_exit
加载)的时候调用,module_init
和module_exit
是指定函数作用的两个宏定义。另外一个宏定义就是MODULE_LICENSE
,这里用来指定的是free license
,没有license
的模块在装载的时候会因为安全问题被禁用,导致装载失败。
printk
顾名思义就是打印,很像printf
,但是是打印在log
里,可以使用dmesg
命令查看。
注意在make的之前要先安装
linux-header
,我的环境是kali
,使用的命令时是
1 sudo apt-get install linux-headers-$(uname -r)
Makefile
如下
1 | ifeq ($(KERNELRELEASE),) |
make
成功之后使用sudo insmod hello.ko
加载模块,使用sudo rmmod hello.ko
卸载模块,之后可以使用sudo dmesg
查看打印出来的信息
Comments