概述
主题是面向某一用户空间的设备访问管理。
大家都知道通常的设备访问流程是:内核设备驱动,包括usb驱动,一般情况下是通过kobject_uevent接口上报uevent消息到用户空间,由用户管理进程,如udevd、ueventd等接收uevent消息,然后解析,创建设备文件节点。之后,设备访问程序才能通过设备文件节点访问操作设备。
管理方法讨论
如果不希望用户空间访问某设备,最直接的方法是不提供相应设备驱动;次之,在koject_uevent接口过滤设备上报消息;再次之,由用户空间的设备管理进程过滤设备上报消息。
多用户空间下,如果不希望某一用户空间访问某设备,沿用上一思路,可以在具体的用户空间的设备管理进程过滤设备上报消息。那么问题来了,是否还有其他方法呢?答案是肯定的。linux2.6.24引入内核的cgroup功能,有1个device cgroup子系统,可以管理进程控制组内的进程是否能够访问某些设备节点。devices.allow指定 cgroup 中的任务可访问的设备,devices.deny指定 cgroup 中的任务禁止访问的设备。每个条目有四个字段:type、major、minor 和 access。type、major 和 minor 字段中使用的值对应 Linux 分配的设备,也称 Linux 设备列表中指定的设备类型和节点数。控制条目如下:
a 8:* rwm
其中,
a, 代表所有设备类型,也可以为b或c分别代表block块设备、character字符设备
b, 8代表设备的主设备号
c, *代表主设备号下的所有次设备号,可以根据需要指定为具体的值
d, r代表读权限、w代表写权限、m代表生成设备文件权限
将该条目写入dev cgroup组A的devices.allow,组A中的所有进程都可以操作该条目所匹配的设备;将该条目写入dev cgroup组A的devices.deny,组A中的所有进程都被禁止操作该条目所匹配的设备。判定条件选取
通过venderId和productId作为判定条件,难以穷举所有的设备。我们就希望能够可以通过usb的接口设备类型来作为判定条件,而且usb驱动本身是定义了不同的接口类型(在ch9.h中)。
1个简单usb设备插入主机后,usb驱动上报消息的流程依次为:
usb_device、usb_interface、(分层封装设备)
它们也依次为父子关系,所以,可以通过寻找父亲的方式,找到设备对应的usb_interface、usb_device。(InterfaceClass定义在usb_interface中,venderId和productId定义在usb_device中)
调整验证代码如下:
/*获取设备的venderId、productId和接口类型*/
dev = container_of(kobj, struct device,kobj);
if (NULL != dev)
{
structdevice *tdev = dev;
do{
if (tdev->type && tdev->type->name)
{
if(!strcmp("usb_interface", tdev->type->name))
{
intf =to_usb_interface(tdev);
iClass =intf->cur_altsetting->desc.bInterfaceClass;
}
if(!strcmp("usb_device", tdev->type->name))
{
udev = container_of(tdev,struct usb_device, dev);
Vid = le16_to_cpu(udev->descriptor.idVendor);
Pid = le16_to_cpu(udev->descriptor.idProduct);
break;
}
}
tdev = tdev->parent;
}while(tdev);
}
/*以或的方式判定*/
if ( iClass || ( Vid && Pid) )
{
if (MAJOR(dev->devt)) {
if ( (0x090c == Vid &&0x1000== Pid)||
(0x10c4 == Vid &&0xea60== Pid) ||
USB_CLASS_MASS_STORAGE == iClass)
{
/*wangshixin, modify dev cgroupto control device access*/
file =filp_open(DEV_CG_ANDROID, O_WRONLY|O_APPEND, 0644);
if (IS_ERR(file))
{
printk("error occuredwhile opening file %s", DEV_CG_ANDROID);
}
else
{
sprintf(buf, "a %d:%drwm", MAJOR(dev->devt), MINOR(dev->devt));
printk(KERN_DEBUG"#uevent---%d:%dn", MAJOR(dev->devt),MINOR(dev->devt));
old_fs = get_fs();
set_fs(KERNEL_DS);
retval =file->f_op->write(file, (char*)buf, 15, &file->f_pos);
set_fs(old_fs);
filp_close(file, NULL);
}
}
}
}经过调测,以上代码是可信的。不仅对内核无具体驱动的usb设备有效,而且对通用的多层驱动设备(如通用U盘)有效。这是比较理想的结果。
课题诞生初期就产生了两个思路:1)不同用户空间独立控制访问;2)通过device cgroup内核集中控制访问。思路1)优点是比较简单,用户空间逻辑便于理解,缺点是不同用户空间要维护多份,而且存在一致的情况;思路2)缺点是技术难度相对较大,在有限的时间内可能难以取得比较理想的控制效果,优点是取得理想效果后,维护简单、易于移植。
这里的验证没有涉及控制配置文件的设计与读写,因为这不是很难的事情。这里给出建议:控制配置文件做成1个内核驱动(配置条目做成链表),上述实施的条件判断修改为遍历链表比对,对控制配置文件的写只有1个实体(可以是对外的控制中心),实施时使用锁避免链表访问异常。最后
以上就是背后月饼为你收集整理的USB设备访问管理的全部内容,希望文章能够帮你解决USB设备访问管理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复