字符设备3 —— 代码目录

本目录包含了《RK3588系列内核开发——I/O模型、定时器、IOCTL与中断》博客中所有示例代码。

目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
字符设备3_code/
├── 01_block_io/ # 阻塞IO & 非阻塞IO
│ ├── Makefile
│ ├── block_io.c # 驱动:等待队列 + O_NONBLOCK
│ └── block_io_app.c # 用户态测试

├── 02_fasync/ # 信号驱动IO
│ ├── Makefile
│ ├── fasync_dev.c # 驱动:fasync + kill_fasync + SIGIO
│ └── fasync_app.c # 用户态:SIGIO信号处理

├── 03_poll/ # IO多路复用
│ ├── Makefile
│ ├── poll_dev.c # 驱动:.poll 回调实现
│ └── poll_app.c # 用户态:poll() 系统调用测试

├── 04_timer_led/ # 标准内核定时器
│ ├── Makefile
│ └── timer_led.c # 驱动:timer_list 周期性LED闪烁

├── 05_hrtimer/ # 高精度定时器
│ ├── Makefile
│ └── hrtimer_dev.c # 驱动:hrtimer 纳秒级周期触发

├── 06_ioctl/ # IOCTL 命令控制
│ ├── Makefile
│ ├── ioctl_cmd.h # 共享头文件:ioctl命令定义
│ ├── ioctl_dev.c # 驱动:unlocked_ioctl 实现
│ └── ioctl_app.c # 用户态:ioctl() 调用测试

├── 07_key_irq/ # GPIO按键中断(手动档)
│ ├── Makefile
│ ├── key_irq.c # 驱动:tasklet消抖 + workqueue日志 + 环形缓冲
│ └── key_test.c # 用户态:poll 监听按键事件

├── 08_key_threaded_irq/ # GPIO按键中断(自动档)
│ ├── Makefile
│ └── key_irq_threaded.c # 驱动:request_threaded_irq 线程化中断

├── assert/ # 文章中插入的图片
│ └── (请将截图放在此目录)

├── Makefile # 通用Makefile模板
└── README.md # 本文件

编译说明

每个子目录下的 Makefile 需要修改 KERNEL_DIRCROSS_COMPILE 为你的实际路径:

1
2
3
ARCH := arm64
CROSS_COMPILE := /你的交叉编译链路径/aarch64-none-linux-gnu-
KERNEL_DIR := /你的RK3588内核源码路径

然后在该目录下执行:

1
make clean && make -j$(nproc)

生成的 .ko 文件拷贝到 RK3588 开发板上:

1
scp *.ko topeet@板子IP:~/ker_test/

用户态程序编译

用户态程序(*_app.ckey_test.c)在 RK3588 开发板上直接编译:

1
gcc xxx_app.c -o xxx_app

测试命令速查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 阻塞IO
sudo insmod block_io.ko
sudo cat /dev/block_io # 终端一:阻塞等待
sudo echo "test" > /dev/block_io # 终端二:写入触发唤醒
sudo rmmod block_io

# 信号驱动IO
sudo insmod fasync_dev.ko
sudo ./fasync_app # 等待SIGIO信号
sudo echo "data" > /dev/fasync_dev # 另一终端写入
sudo rmmod fasync_dev

# IO多路复用
sudo insmod poll_dev.ko
sudo ./poll_app # poll等待
sudo echo "hello" > /dev/poll_dev
sudo rmmod poll_dev

# 定时器LED
sudo insmod timer_led.ko
sudo echo "500" > /dev/timer_led # 500ms周期闪烁
sudo echo "0" > /dev/timer_led # 停止
sudo rmmod timer_led

# 高精度定时器
sudo insmod hrtimer_dev.ko
sudo echo "100000" > /dev/hrtimer_dev # 100us周期
sudo echo "0" > /dev/hrtimer_dev
sudo rmmod hrtimer_dev

# IOCTL
sudo insmod ioctl_dev.ko
sudo ./ioctl_app
sudo rmmod ioctl_dev

# 按键中断
sudo insmod key_irq.ko
cat /proc/interrupts | grep rk3588 # 查看中断注册情况
sudo ./key_test # 按按键测试
sudo rmmod key_irq

# 线程化中断按键
sudo insmod key_irq_threaded.ko
cat /proc/interrupts | grep threaded
sudo ./key_test # 复用 key_test.c
sudo rmmod key_irq_threaded