Loading

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>\))访问当前进程信息。

参考资料

https://github.com/unicornx/osrusbfx2

posted @ 2025-07-04 22:37  Baiyug  阅读(30)  评论(0)    收藏  举报