技术知识库

为八个 KFIFO 设备添加 poll 支持

为八个 KFIFO 设备添加 poll 支持

摘要

本实验创建 8 个独立 misc 字符设备,每个设备分别拥有 KFIFO、读等待队列和写等待队列,并实现 .poll 回调。模块已经完成 ARM64 交叉编译;目标系统的 8 节点加载验证和用户态 epoll 程序尚未完成,因此不能把运行闭环标为成功。

原理见 poll 与 epoll 如何通过等待队列发现设备就绪 和 共享设备状态与每次 open 私有状态如何决定进程能否互相唤醒。

目标与完成标准

  • 创建 8 个相互独立的设备对象。
  • 每个对象拥有独立 KFIFO 和等待队列。
  • 每个 misc 节点能够在 open() 后定位回自己的设备对象。
  • .poll 登记读写等待队列并返回当前就绪掩码。
  • ARM64 模块交叉编译成功。
  • 目标系统生成 8 个 /dev/epoll_kfifo_mailbox_N 节点。
  • 用户态 epoll 程序能准确返回发生事件的设备。

工作目录

/home/martin-zou/workspace/gcc-lab/char_mod/epollkfifo_mailbox

源文件:

epollkfifo_mailbox.c
Makefile

数据结构

struct kfifo_device {
	const char *name;
	struct device *mymailbox_device;
	struct miscdevice *misc_mailbox_device;
	wait_queue_head_t read_queue;
	wait_queue_head_t write_queue;
	struct kfifo misc_kfifo;
};

struct epoll_kfifo_device {
	struct kfifo_device *device;
	char name[64];
};

数组只保存 8 个入口,每个入口的 device 指向一次独立 kzalloc() 得到的设备状态:

static struct epoll_kfifo_device
	myepoll_kfifo_device[EPOLL_KFIFO_MAX_DEVICES];

这避免 8 个设备错误地共用同一个 KFIFO 和等待队列。

misc open 如何恢复设备对象

misc 框架进入驱动 open() 前,file->private_data 指向对应 struct miscdevice。驱动用它在 8 个入口中找到所属 kfifo_device,然后覆盖为长期使用的共享设备指针:

device = find_kfifo_device(file->private_data);
if (!device)
	return -ENODEV;

file->private_data = device;

poll 回调

poll_wait(file, &device->read_queue, wait);
poll_wait(file, &device->write_queue, wait);

if (!kfifo_is_empty(&device->misc_kfifo))
	mask |= EPOLLIN | EPOLLRDNORM;
if (!kfifo_is_full(&device->misc_kfifo))
	mask |= EPOLLOUT | EPOLLWRNORM;

.poll 只登记等待关系并报告状态;用户空间在 epoll_wait() 返回后自行调用 read()。

手动构建

cd /home/martin-zou/workspace/gcc-lab/char_mod/epollkfifo_mailbox
make clean
make
file epollkfifo_mailbox.ko

预期模块为 ARM64 relocatable ELF,并生成:

epollkfifo_mailbox.ko

待完成的目标系统验证

scp -P 2222 epollkfifo_mailbox.ko martin@127.0.0.1:~/

目标系统计划执行:

sudo insmod ~/epollkfifo_mailbox.ko
ls -l /dev/epoll_kfifo_mailbox_*

之后编写用户态 epoll 程序,同时监听 8 个节点。该部分完成前,本项目保持 growing。

关联