Linux字符设备驱动框架笔记
作者:网络转载 发布时间:[ 2016/12/15 16:19:02 ] 推荐标签:操作系统 Linux
实现ioctl
ioctl是Linux专门为用户层控制设备设计的系统调用接口,这个接口具有极大的灵活性,我们的设备打算让用户通过哪些命令实现哪些功能,都可以通过它来实现,ioctl在操作方法集中对应的函数指针是 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); ,其中的命令和参数完全由驱动指定,Linux建议如图所示的方式定义ioctl()命令
设备类型 序列号 方向 数据尺寸
8bit 8bit 2bit 13/14bit
这里,设备类型字段为一个幻数,可以是0~0xff之间的数,内核中的" ioctl-number.txt "给出了一个推荐的和已经被使用的幻数(但是已经好久没人维护了),新设备驱动定义幻数的时候要避免与其冲突。命令码的方向字段为2bit,表示数据的传输方向,可能的值是: _IOC_NONE , _IOC_READ , _IOC_WRITE 和 _IOC_READ|_IOC_WRITE 。命令码的数据字段表示涉及的用户数据的大小,这个成员的宽度依赖于体系结构,通常是13或14位。内核还定义了 _IO() , _IOR() , _IOW() , _IOWR() 这4个宏来辅助生成这种格式的命令。这几个宏的作用是根据传入的type(设备类型字段),nr(序列号字段)和size(数据长度字段)和宏名??行的方向字段移位组合生成命令码。内核中还预定义了一些I/O控制命令,如果某设备驱动中包含了与预定义命令一样的命令码,这些命令会被当做预定义命令被内核处理而不是被设备驱动处理,有如下4种:
FIOCLEX:即file ioctl close on exec 对文件设置专用的标志,通知内核当exec()系统带哦用发生时自动关闭打开的文件
FIONCLEX:即file ioctl not close on exec,清除由FIOCLEX设置的标志
FIOQSIZE:获得一个文件或目录的大小,当用于设备文件时,返回一个ENOTTY错误
FIONBIO:即file ioctl non-blocking I/O 这个调用修改flip->f_flags中的O_NONBLOCK标志
我们可以将驱动设计的命令包含在一个头文件中,记录用户程序和驱动程序的命令约定,下面是一个简单的例子
//mycmd.h
...
#include <asm/ioctl.h>
#define CMDT 'A'
#define KARG_SIZE 36
struct karg{
int kval;
char kbuf[KARG_SIZE];
};
#define CMD_OFF _IO(CMDT,0)
#define CMD_ON _IO(CMDT,1)
#define CMD_R _IOR(CMDT,2,struct karg)
#define CMD_W _IOW(CMDT,3,struct karg)
...
//chrdev.c
static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
static struct karg karg = {
.kval = 0,
.kbuf = {0},
};
struct karg *usr_arg;
switch(cmd){
case CMD_ON:
/* 开灯 */
break;
case CMD_OFF:
/* 关灯 */
break;
case CMD_R:
if(_IOC_SIZE(cmd) != sizeof(karg)){
return -EINVAL;
}
usr_arg = (struct karg *)arg;
if(copy_to_user(usr_arg, &karg, sizeof(karg))){
return -EAGAIN;
}
break;
case CMD_W:
if(_IOC_SIZE(cmd) != sizeof(karg)){
return -EINVAL;
}
usr_arg = (struct karg *)arg;
if(copy_from_user(&karg, usr_arg, sizeof(karg))){
return -EAGAIN;
}
break;
default:
;
};
return 0;
}
创建设备文件
插入的设备模块,我们可以使用 cat /proc/devices 命令查看当前系统注册的设备,但是我们还没有创建相应的设备文件,用户也不能通过文件访问这个设备。设备文件的inode应该是包含了这个设备的设备号,操作方法集指针等信息,这样我们可以通过设备文件找到相应的inode进而访问设备。创建设备文件的方法有两种, 手动创建 或 自动创建 , 手动创建设备文件 是使用 mknod /dev/xxx 设备类型 主设备号 次设备号 的命令创建,所以首先需要使用 cat /proc/devices 查看设备的主设备号并通过源码找到设备的次设备号,需要注意的是,理论上设备文件可以放置在任何文件加夹,但是放到 "/dev" 才符合Linux的设备管理机制,这里面的devtmpfs是专门设计用来管理设备文件的文件系统。设备文件创建好之后会和创建时指定的设备绑定,即使设备已经被卸载了,如要删除设备文件,只需要像删除普通文件一样 rm 即可。理论上模块名(lsmod),设备名(/proc/devices),设备文件名(/dev)并没有什么关系,完全可以不一样,但是原则上还是建议将三者进行统一,便于管理。
除了使用蹩脚的手动创建设备节点的方式,我们还可以在设备源码中使用相应的措施使设备一旦被加载 自动创建设备文件 ,自动创建设备文件需要我们在编译内核的时候或制作根文件系统的时候好相应的配置:
Device Drivers --->
Generic Driver Options --->
[*]Maintain a devtmpfs filesystem to mount at /dev
[*] Automount devtmpfs at /dev,after the kernel mounted the rootfs
OR
制作根文件系统的启动脚本写入
mount -t sysfs none sysfs /sys
mdev -s //udev也行
有了这些准备,只需要导出相应的设备信息到 "/sys" 可以按照我们的要求自动创建设备文件。内核给我们提供了相关的API
class_create(owner,name);
struct device *device_create_vargs(struct class *cls, struct device *parent,dev_t devt, void *drvdata,const char *fmt, va_list vargs);
void class_destroy(struct class *cls);
void device_destroy(struct class *cls, dev_t devt);
有了这几个函数,我们可以在设备的 xxx_init() 和 xxx_exit() 中分别填写以下的代码可以实现自动的创建删除设备文件
/* 在/sys中导出设备类信息 */
cls = class_create(THIS_MODULE,DEV_NAME);
/* 在cls指向的类中创建一组(个)设备文件 */
for(i= minor;i<(minor+cnt);i++){
devp = device_create(cls,NULL,MKDEV(major,i),NULL,"%s%d",DEV_NAME,i);
}
/* 在cls指向的类中删除一组(个)设备文件 */
for(i= minor;i<(minor+cnt);i++){
device_destroy(cls,MKDEV(major,i));
}
/* 在/sys中删除设备类信息 */
class_destroy(cls); //一定要先卸载device再卸载class
完成了这些工作,一个简单的字符设备驱动搭建完成了,现在可以写一个用户程序进行测试了^ - ^
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Linux下开源的DDR压力测试工具曝Linux恶意软件:让树莓派设备挖掘数字货币linux系统中不同颜色的文件夹及根目录介绍软件测试工程师必知必会Linux命令Linux下DNS服务器配置如何成为不可替代的Linux运维工程师?详解Linux进程(作业)的查看和杀死Linux 日志定时轮询流程详解比特币勒索病毒不只Windows系统有,Linux版的来了Linux日志定时轮询流程详解Linux iommu和vfio概念空间解构Linux系统如何低于TCP洪水攻击Linux无损调整分区大小Linux下防火墙配置实例Linux使用Jexus托管Asp.Net Core应用程序Linux中引号的那些事
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南