zoukankan      html  css  js  c++  java
  • linux 在 open 时复制设备

    管理存取控制的另一个技术是创建设备的不同的私有拷贝, 根据打开它的进程.

    明显地, 这只当设备没有绑定到一个硬件实体时有可能; scull 是一个这样的"软件"设备 的例子. /dev/tty 的内部使用类似的技术来给它的进程一个不同的 /dev 入口点呈现的 视图. 当设备的拷贝被软件驱动创建, 我们称它们为虚拟设备--就象虚拟控制台使用一个 物理 tty 设备.

    结构这类的存取控制很少需要, 这个实现可说明内核代码是多么容易改变应用程序的对周 围世界的看法(即, 计算机).

    /dev/scullpriv 设备节点在 scull 软件包只实现虚拟设备. scullpriv 实现使用了进程 的控制 tty 的设备号作为对存取虚拟设备的钥匙. 但是, 你可以轻易地改变代码来使用 任何整数值作为钥匙; 每个选择都导致一个不同的策略. 例如, 使用 uid 导致一个不同 地虚拟设备给每个用户, 而使用一个 pid 钥匙创建一个新设备为每个存取它的进程.

    使用控制终端的决定打算用在易于使用 I/O 重定向测试设备: 设备被所有的在同一个虚 拟终端运行的命令所共享, 并且保持独立于在另一个终端上运行的命令所见到的.

    open 方法看来象下面的代码. 它必须寻找正确的虚拟设备并且可能创建一个. 这个函数 的最后部分没有展示, 因为它拷贝自空的 scull, 我们已经见到过.

    /* The clone-specific data structure includes a key field */ struct scull_listitem

    {

    struct scull_dev device; dev_t key;

    struct list_head list;

    };

    /* The list of devices, and a lock to protect it */ static LIST_HEAD(scull_c_list);

    static spinlock_t scull_c_lock = SPIN_LOCK_UNLOCKED;

    /* Look for a device or create one if missing */

    static struct scull_dev *scull_c_lookfor_device(dev_t key)

    {

    148

    struct scull_listitem *lptr; list_for_each_entry(lptr, &scull_c_list, list)

    {

    if (lptr->key == key)

    return &(lptr->device);

    }

    /* not found */

    lptr = kmalloc(sizeof(struct scull_listitem), GFP_KERNEL); if (!lptr)

    return NULL;

    /* initialize the device */

    memset(lptr, 0, sizeof(struct scull_listitem)); lptr->key = key;

    scull_trim(&(lptr->device)); /* initialize it */

    init_MUTEX(&(lptr->device.sem));

    /* place it in the list */ list_add(&lptr->list, &scull_c_list);

    return &(lptr->device);

    }

    static int scull_c_open(struct inode *inode, struct file *filp)

    {

    struct scull_dev *dev;

    dev_t key;

    if (!current->signal->tty)

    {

    PDEBUG("Process "%s" has no ctl tty ", current->comm); return -EINVAL;

    }

    key = tty_devnum(current->signal->tty);

    /* look for a scullc device in the list */ spin_lock(&scull_c_lock);

    dev = scull_c_lookfor_device(key);

    spin_unlock(&scull_c_lock);

    if (!dev)

    return -ENOMEM;

    /* then, everything else is copied from the bare scull device */

    149

    这个 release 方法没有做特殊的事情. 它将在最后的关闭时正常地释放设备, 但是我们 不选择来维护一个 open 计数而来简化对驱动的测试. 如果设备在最后的关闭被释放, 你 将不能读相同的数据在写入设备之后, 除非一个后台进程将保持它打开. 例子驱动采用了 简单的方法来保持数据, 以便在下一次打开时, 你会发现它在那里. 设备在 scull_cleanup 被调用时释放.

    这个代码使用通用的 linux 链表机制, 而不是从头开始实现相同的功能. linux 链表在 第 11 章中讨论.

    这里是 /dev/scullpriv 的 release 实现, 它结束了对设备方法的讨论. static int scull_c_release(struct inode *inode, struct file *filp)

    {

    /*

    *Nothing to do, because the device is persistent.

    *A `real' cloned device should be freed on last close */

    return 0;

    }

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Spring框架——AOP面向切面编程
    Spring学习
    面试题整理
    Java Web前端到后台常用框架介绍
    【Oracle】SQL/92 执行多个表的连接
    什么是持久化?
  • 原文地址:https://www.cnblogs.com/fanweisheng/p/11141939.html
Copyright © 2011-2022 走看看