内核实验(六):使用misc框架,实现简单字符设备驱动

news/2024/11/6 19:17:38/

内核实验(六):使用misc框架,实现简单字符设备驱动

一、篇头

使用自行组建的Qemu Linux虚拟机,提升效率,继续内核实验。本文将学习使用misc框架来创建设备驱动。

在linux系统中,主设备号,在历史的长河里,都是固定分配好的(见内核文档 Documentation/admin-guide/devices.txt)。对于其他研究内核驱动,或编写驱动的开发人员来说,必须保证自己所使用的主设备号不与现有设备号发生冲突。方法一,自然是使用内核实验(五)中所使用的动态分配接口。其次,就是使用MISC设备驱动框架,它为这些小设备提供了一个公用的主设备号,此设备号则依据申请分配。

二、系列文章

略……

三、实验环境

  • 编译服务器+NFS:ubuntu 22.04
  • Qemu 虚拟机:Linux version 5.15.102 + Buysbox 1.3.36 + ARM_32bit
  • Qemu 启动命令:qemu-system-arm -nographic -M vexpress-a9 -m 1024M -kernel arch/arm/boot/zImage -initrd …/busybox/rootfs.ext4.img.gz -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb

四、源码解析

4.1 app源码

  • 文件名:linux-stable\my_kmodules\app_test.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define MY_DEV_NAME "/dev/my_dev"int main()
{char buffer[64];int fd;fd = open(MY_DEV_NAME, O_RDONLY);if (fd < 0) {printf("open device %s failded\n", MY_DEV_NAME);return -1;}read(fd, buffer, 64);close(fd);return 0;
}

4.2 驱动源码

  • 文件名:linux-stable\my_kmodules\test_4.c

4.2.1 关键部分

/*
* (1)使用MISC_DYNAMIC_MINOR动态分配次设备号;而主设备号则自动使用MISC框架的主设备号10;
* (2)创建MISC设备结构体 struct miscdevice test_4_misc_device; 
* (3)使用misc_register() 注册MISC框架设备驱动;使用 misc_deregister()注销。
*/
static struct miscdevice test_4_misc_device ={.minor = MISC_DYNAMIC_MINOR,.name = MY_DEV_NAME,.fops = &test_fops,
};

4.2.2 完整源码

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/miscdevice.h>#define MY_DEV_NAME "my_dev"static int test_4_open(struct inode *inode, struct file *file)
{int major = MAJOR(inode->i_rdev);int minor = MINOR(inode->i_rdev);pr_info("%s: major=%d, minor=%d\n", __func__, major, minor);return 0;
}static int test_4_release(struct inode *inode, struct file *file)
{pr_info("%s \n", __func__);return 0;
}static ssize_t test_4_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
{pr_info("%s \n", __func__);return 0;
}static ssize_t test_4_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{pr_info("%s \n", __func__);return 0;}static const struct file_operations test_fops = {.owner = THIS_MODULE,.open = test_4_open,.release = test_4_release,.read = test_4_read,.write = test_4_write
};static struct miscdevice test_4_misc_device ={.minor = MISC_DYNAMIC_MINOR,.name = MY_DEV_NAME,.fops = &test_fops,
};static int __init test_4_init(void)
{int ret;pr_info("test_4_init\n");ret = misc_register(&test_4_misc_device);if (ret != 0 ) {pr_err("failed to misc_register");return ret;}pr_err("Minor number = %d\n", test_4_misc_device.minor);return 0;
}static void __exit test_4_exit(void)
{pr_info("test_4_exit\n");misc_deregister(&test_4_misc_device);
}module_init(test_4_init);
module_exit(test_4_exit);MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("szhou <66176468@qq.com>");
MODULE_DESCRIPTION("test_4, 使用misc框架开发设备驱动");

4.3 Makefile

  • 文件名:linux-stable\my_kmodules\Makefile
  • 本实验,继承之前的做法,只单独添加test_4.o即可
KDIR := /home/szhou/works/qemu_linux/linux-stableobj-m := test_1.o test_2.o test_3.o test_4.o
all :$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) cleanrm -f *.ko

五、编译及部署

1)执行驱动KO编译
shou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ make 
make -C /home/szhou/works/qemu_linux/linux-stable M=/home/szhou/works/qemu_linux/linux-stable/my_kmodules modules
make[1]: Entering directory '/home/szhou/works/qemu_linux/linux-stable'CC [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_4.oMODPOST /home/szhou/works/qemu_linux/linux-stable/my_kmodules/Module.symversLD [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_4.ko
make[1]: Leaving directory '/home/szhou/works/qemu_linux/linux-stable'
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$(2)编译APP,采用 --staitc 静态链接
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ arm-linux-gnueabi-gcc app_test.c -o app_test --static3)将KO和APP存放到NFS共享目录
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ cp test_4.ko ~/works/nfs_share/
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ cp app_test ~/works/nfs_share/
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ 

六、运行及测试

1)启动之前编译组建的QEMU虚拟机
Please press Enter to activate this console.2)挂载NFS共享目录
~ #  mount -t nfs -o nolock 192.168.3.67:/home/szhou/works/nfs_share /mnt(3)查看设备文件,这时候还没加载驱动,也没创建节点,所以肯定是没有的
~ # ls /dev | grep my
~ # ls /sys/class/misc | grep my(4) 加载ko
~ # cd /mnt/
/mnt # insmod  test_4.ko 
test_4: loading out-of-tree module taints kernel.
test_4_init
Minor number = 1254)查看设备文件,可见/dev/my_dev 依旧是不存在的(这是因为/dev下的设备并非由驱动创建,而是由/sbin/mdev -s,此处我们就手动创建就行)
/mnt # ls /dev | grep my(5)查看misc设备,可见已创建 /sys/class/misc/my_dev, 但这是设备目录文件,非设备的用户接口
/mnt # ls /sys/class/misc | grep my
my_dev(6)手动创建设备文件,主设备号为MISC框架的设备号:10 (日常开发misc,会自动调用 /sbin/mdev -s创建设备,此处虽然已经配置,但我的hotplug还是有问题,暂时用手动创建了)
/mnt # mdev -s (会检查/sys/class下所有dev文件,并创建/dev/xxx),效果等同于下面这个命令
(# mknod /dev/my_dev c 10 125 )(7)运行测试程序,将执行 fd = open("/dev/my_dev", O_RDONLY);
/mnt # ./app_test 
test_4_open: major=10, minor=125
test_4_read 
test_4_release 
/mnt # 

效果图示:

在这里插入图片描述

七、篇尾

略……


http://www.ppmy.cn/news/358985.html

相关文章

内核实验(五):传统简单字符设备驱动

文章目录 一、篇头二、源码2.1 驱动关键部分2.2 APP&#xff1a;test\_3\_app.c2.3 驱动完整源码2.4 Makefile 三、编译3.1 编译ko3.2 编译app 四、测试4.1 部署4.2 测试4.2.1 启动qemu虚拟机4.2.2 运行测试文件4.2.3 查看设备情况 五、篇尾 一、篇头 目标是把内核相关部分的实…

内核实验(八):实现O-NONBLOCK非阻塞读写

一、篇头 继续使用qemu调试内核的实验。本章复习阻塞与非阻塞IO的概念和机制&#xff0c;然后对之前实验&#xff08;七&#xff09;的代码做少许修改&#xff0c;来实现非阻塞的IO读写。 二、系列文章 略…… 三、实验环境 编译服务器NFS&#xff1a;ubuntu 22.04Qemu 虚…

BCB6

很久没有摸c builder了&#xff0c;因同事需求需要修改东西&#xff0c;再次搭建环境&#xff0c;碰到些问题&#xff0c;以此做为记录便于以后翻看。 视频会议控制台的项目&#xff0c;使用了第三方组件AlphaControls&#xff0c;需要配置Project->Options->Directories…

内核实验(四):Qemu调试Linux内核,实现NFS挂载

文章目录 一、篇头二、服务端配置2.1 运行环境2.1.1 Qemu 版本2.1.2 rootfs 版本2.1.3 Buysbox 版本2.1.4 避开: 不用安装 2.2 服务端2.2.1 安装NFS server2.2.2 配置NFS server2.2.3 启动NFS server 三、客户端配置3.1 添加 dhcp client3.2 修改开机脚本3.3 重新制作 rootfs 四…

内核实验(一):使用QEMU+GDB断点调试Linux内核代码

文章目录 一、篇头二、环境配置2.1 安装QEMU2.2 安装编译工具链 三、编译内核3.1 编译配置3.2 编译 四、GDB断点调试4.1 启动内核4.2 GDB远程连接 五、 附录1. 查看内核版本号2. 编译器 gnueabi和gnueabihf的区别 一、篇头 日常工作中对于内核的调试&#xff0c;大部分情况下只…

随机池化(Stochastic Pooling)

前言 CNN中卷积完后有个步骤叫pooling, 在ICLR2013上&#xff0c;作者Zeiler提出了另一种pooling手段(最常见的就是mean-pooling和max-pooling)&#xff0c;叫stochastic pooling。只需要对Feature Map中的元素按照其概率值大小随机选择&#xff0c;元素选中的概率与其数…

内核实验(二):自定义一个迷你Linux ARM系统,基于Kernel v5.15.102, Busybox,Qemu

文章目录 一、篇头二、内核部分2.1 源码下载2.1.1 官网2.1.2 镜像站点2.1.3 代码下载 2.2 编译2.2.1 设置工具链2.2.2 配置2.2.3 make2.2.4 编译成功 三、busybox部分3.1 源码下载3.2 编译3.2.1 配置3.2.3 编译3.2.4 查看编译结果 四、制作根文件系统4.1 回顾busybox4.2 修改bu…

BC1.2

► BC1.2规范颁布之前 在2007年第一个电池充电规范颁布之前&#xff0c;尝试为电池充电本质上是一种冒险——结果非常难以预测。当2000年 出现USB 2.0时&#xff0c;外设默认吸收100mA电流&#xff0c;除非明确协商将电流增大至最高500mA。如果总线上经过一段延迟后 没有数据活…