LDD学习笔记(持续更新ing)
LDD学习笔记
0 前言
一直对linux驱动感兴趣,于是开始看linux device drivers,这本书是基于linux 2.6 的,相比于现在的linux发行版是比较老了的,但我没找到比较新的教学。话不多说,看就完了,也不知道我能不能看完(:
1 基础实验环境(第二章)
ubuntu5.04 ubuntu9.04
经过一番折腾,我放弃了使用ubuntu5.04建立内核树的方法,因为ubuntu5.04没法安装initramfs-tools,从而没法制作相应的initrd.img。什么是initrd.img,就要提到linux系统的启动方式,对于linux2.6.x,一开始,在挂载真正的文件系统之前,linux会挂载一个软件意义上的RAM filesystem作为文件系统,这里面存放了系统启动必备的用户程序和驱动模块,等系统启动完成,再切换到真正的文件系统。initrd.img就是这个RAM filesystem。制作initrd.img应用到了initramfs-tools这个工具。
理论上,基础系统的选择并不唯一,在内核源码中Document/Changes中描述了编译所需的环境,符合即可。
所谓内核树(翻译),就是当先系统内核的源码,我们获得某个版本的linux源码放在某个系统上,编译,生成内核镜像,并将内核镜像替换当前系统的内核,就可以获得所谓的内核树了。
我大致描述一下搭建内核树的基本流程
1.1 找一台linux系统的主机/虚拟机
我使用vmware,ubuntu9.04。更改/etc/apt/sources.list,就是把软件源改成旧版的软件源,
deb http://old-releases.ubuntu.com/ubuntu/ jaunty main restricted
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty main restricted
deb http://old-releases.ubuntu.com/ubuntu/ jaunty-updates main restricted
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty-updates main restricted
deb http://old-releases.ubuntu.com/ubuntu/ jaunty universe
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty universe
deb http://old-releases.ubuntu.com/ubuntu/ jaunty-updates universe
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty-updates universe
deb http://old-releases.ubuntu.com/ubuntu/ jaunty multiverse
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty multiverse
deb http://old-releases.ubuntu.com/ubuntu/ jaunty-updates multiverse
deb-src http://old-releases.ubuntu.com/ubuntu/ jaunty-updates multiverse
deb http://old-releases.ubuntu.com/ubuntu jaunty-security main restricted
deb-src http://old-releases.ubuntu.com/ubuntu jaunty-security main restricted
deb http://old-releases.ubuntu.com/ubuntu jaunty-security universe
deb-src http://old-releases.ubuntu.com/ubuntu jaunty-security universe
deb http://old-releases.ubuntu.com/ubuntu jaunty-security multiverse
deb-src http://old-releases.ubuntu.com/ubuntu jaunty-security multiverse
然后,可以使用apt安装一下必要的软件
sudo apt-get update #更新软件源
sudo apt-get install openssh-sever #ssh便于mobaxterm等工具访问虚拟机的文件系统和shell
sudo apt-get install nautilus-open-terminal #右键打开终端
sudo apt-get install initramfs-tools #制作 initrd.img 的工具
1.2 下载linux源码
找到官网 https://www.kernel.org/pub/linux/kernel/v2.6/ 下载linux2.6.38源码,上传到虚拟机。
1.3 编译
进入源码的根目录
1.3.1 config
sudo apt-get install libncurses5-dev # menuconfig 需要
make menuconfig
默认,然后保存config文件。
1.3.2 编译内核
make
直接执行,编译,一般要等上一会,正常情况不报错。
1.3.3 编译内核模块
make modules
1.3.4 安装模块
make modules_install
1.3.5 安装
make install
1.4 配置grub
我们借助grub引导内核。
这里需要自行生成initrd
mkinitramfs -o initrd.img-2.6.38 2.6.38
sudo cp initrd.img-2.6.38 /boot/
修改/boot/grub/menu.lst,在原来配置上面增加自行编译获得的vmlinuz-2.6.38和initrd.img-2.6.38,然后重启系统时grub会默认执行第一份设定。
title linux 2.6.38
uuid ed389ab6-bb05-4e1e-bcea-acb278bee453
kernel /boot/vmlinuz-2.6.38 root=UUID=ed389ab6-bb05-4e1e-bcea-acb278bee453 ro quiet splash
initrd /boot/initrd.img-2.6.38
quiet
title Ubuntu 9.04, kernel 2.6.28-11-generic
uuid ed389ab6-bb05-4e1e-bcea-acb278bee453
kernel /boot/vmlinuz-2.6.28-11-generic root=UUID=ed389ab6-bb05-4e1e-bcea-acb278bee453 ro quiet splash
initrd /boot/initrd.img-2.6.28-11-generic
quiet
title Ubuntu 9.04, kernel 2.6.28-11-generic (recovery mode)
uuid ed389ab6-bb05-4e1e-bcea-acb278bee453
kernel /boot/vmlinuz-2.6.28-11-generic root=UUID=ed389ab6-bb05-4e1e-bcea-acb278bee453 ro single
initrd /boot/initrd.img-2.6.28-11-generic
title Ubuntu 9.04, memtest86+
uuid ed389ab6-bb05-4e1e-bcea-acb278bee453
kernel /boot/memtest86+.bin
quiet
1.5 验证
重启并引导linux 2.6.38进入系统,查看内核版本
uname -r
可以看到变成了2.6.38
2 hello 模块(第二章)
hello 测试
源文件
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
makefile
obj-m := hello.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD)
执行make指令,使用当前内核树版本的makefile规则编译代码。
baiyug@baiyug-desktop:~/Desktop/hello$ make
make -C /lib/modules/2.6.38/build M=/home/baiyug/Desktop/hello
make[1]: Entering directory `/home/baiyug/Desktop/linux-2.6.38'
LD /home/baiyug/Desktop/hello/built-in.o
CC [M] /home/baiyug/Desktop/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/baiyug/Desktop/hello/hello.mod.o
LD [M] /home/baiyug/Desktop/hello/hello.ko
make[1]: Leaving directory `/home/baiyug/Desktop/linux-2.6.38'
然后进入root权限,测试加载和卸载模块
root@baiyug-desktop:/home/baiyug/Desktop/hello# insmod ./hello.ko
root@baiyug-desktop:/home/baiyug/Desktop/hello# rmmod hello
未看到理应存在的打印信息,可能是terminal使用的shell是字符控制台通过间接方式传递的,查看系统日志/var/log/syslog
Jul 1 18:36:16 baiyug-desktop kernel: [ 807.541226] Hello, world
Jul 1 18:36:18 baiyug-desktop kernel: [ 809.409880] Goodbye, cruel world
可以查看到模块的打印消息,验证成功。
3 用户空间和内核空间(第二章)
用户空间和内核空间
- 使用不同的CPU优先级,用户最低,内核最高
- 使用不同的地址
- 执行系统调用时,系统进入内核空间,内核代码执行在进程上下文,代表进程工作,访问进程的地址
- 执行中断时,系统进入内核空间,和进程是异步的(?就是说中断可以打断当前进程执行然后返回
- 模块运行在内核空间
通常,一个驱动模块分为两种工作,一些函数作为系统调用,一些函数作为中断处理。
4 内核中的并发(第二章)
并发的情形
- 多个进程同时使用某设备(usb、keyboard...)
- 异步:设备中断、定时器
- symmetric multiprocessor (SMP)
- 抢占式任务处理
应对并发,内核代码必须是reentrant,同时在不同进程上下文中运行。数据结构应当仔细设计,共享数据的访问也需要注意。
并发是内核必须考虑的问题,其引起的某种严重的bug(不阻塞)难以调试。
5 当前进程(第二章)
使用current(定义在\(<asm/current.h>\))访问当前进程信息。

浙公网安备 33010602011771号