我是靠谱客的博主 背后月饼,最近开发中收集的这篇文章主要介绍USB设备访问管理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

主题是面向某一用户空间的设备访问管理。

大家都知道通常的设备访问流程是:内核设备驱动,包括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中)

调整验证代码如下:

/*获取设备的venderIdproductId和接口类型*/

    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设备访问管理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部