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

明显地, 这只当设备没有绑定到一个硬件实体时有可能; 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\n", 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;

}

linux 在 open 时复制设备的更多相关文章

  1. Linux的fork()写时复制原则(转)

    写时复制技术最初产生于Unix系统,用于实现一种傻瓜式的进程创建:当发出fork(  )系统调用时,内核原样复制父进程的整个地址空间并把复制的那一份分配给子进程.这种行为是非常耗时的,因为它需要: · ...

  2. Linux进程管理——fork()和写时复制

    写时复制技术最初产生于Unix系统,用于实现一种傻瓜式的进程创建:当发出fork(  )系统调用时,内核原样复制父进程的整个地址空间并把复制的那一份分配给子进程.这种行为是非常耗时的,因为它需要: · ...

  3. Linux驱动设计——字符杂项设备

    杂项设备 linux里面的misc杂项设备是主设备号为10的驱动设备,misc设备其实也就是特殊的字符设备,可自动生成设备节点. 定义头文件<linux/miscdevice.h>   杂 ...

  4. linux下文件的复制、移动与删除

    linux下文件的复制.移动与删除命令为:cp,mv,rm 一.文件复制命令cp     命令格式:cp [-adfilprsu] 源文件(source) 目标文件(destination)      ...

  5. Linux Platform驱动模型(一)-设备信息

    我在Linux字符设备驱动框架一文中简单介绍了Linux字符设备编程模型,在那个模型中,只要应用程序open()了相应的设备文件,就可以使用ioctl通过驱动程序来控制我们的硬件,这种模型直观,但是从 ...

  6. Linux内核入门到放弃-设备驱动程序-《深入Linux内核架构》笔记

    I/O体系结构 总线系统 PCI(Peripheral Component Interconnect) ISA(Industrial Standard Architecture) SBus IEEE1 ...

  7. Linux基础命令---iostat显示设备状态

    iostat iostat指令用来显示cpu状态,系统IO设备的状态,以及相关磁盘和NFS使用状态.iostat命令通过观察设备相对于其平均传输速率的活动时间来监视系统输入/输出设备负载.iostat ...

  8. Linux DTS(Device Tree Source)设备树详解之二(dts匹配及发挥作用的流程篇)【转】

    转自:https://blog.csdn.net/radianceblau/article/details/74722395 版权声明:本文为博主原创文章,未经博主允许不得转载.如本文对您有帮助,欢迎 ...

  9. Linux运行时I/O设备的电源管理框架【转】

    转自:https://www.cnblogs.com/coryxie/archive/2013/03/01/2951243.html 本文介绍Linux运行时I/O设备的电源管理框架.属于Linux内 ...

随机推荐

  1. tftp-server服务器搭建

    学习搭建TFTP服务器(步骤来于网上) 以contos6.5为例 执行下面的命令能够看到服务是否已经启动,若已经启动则不用安装,否则需要安装下面的步骤安装tftp-server服务器 netstat ...

  2. Servlet容器container

    通俗点说,所谓容器,就是放东西的地方.Servlet容器自然就是放Servlet的地方.J2EE开发,是有分工的.一般的程序员,写得都是应用开发,我们会按照一定的规则,开发我们的系统,比如用Servl ...

  3. 在Struts2里面嵌入Spring

    第一步:在web.xml中增加以下的listener <listener> <listener-class>org.springframework.web.context.Co ...

  4. 【JZOJ4884】【NOIP2016提高A组集训第12场11.10】图的半径

    题目描述 mhy12345学习了树的直径,于是开始研究图的半径,具体来说,我们需要在图中选定一个地方作为中心,其中这个中心有可能在路径上. 而这个中心的选址需要能够使得所有节点达到这个中心的最短路里面 ...

  5. 小爬爬2:fiddler安装和了解fiddler

    1.解压安装就可以了 fiddler优点:抓取移动和PC机器的请求 2.首先进行证书的配置 如果不配置只能抓取http的请求,https不能抓取. 先选择,第一个"清空所有内容" ...

  6. postman认证使用篇(五)

    postman 认证使用篇(五) Authorization 尽管请求编辑器已经足够强大去构造各种各样的请求,但是有的时候你的请求可能是需要认证,那么就可以尝试使用下面的认证功能了(由于认证的参数信息 ...

  7. [已转移]JavaScript事件---DOM事件流

    该文章已转移到博客:https://cynthia0329.github.io/ 事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件 这个传播过程即DOM事件流. ...

  8. F4NNIU 整理的 docker-compose 几个常用命令

    F4NNIU 整理的 docker-compose 几个常用命令 up 创建并启动一个容器. 记录一下,如果已经有容器,up 和 start 都可以启动容器,up 可以看到调试窗口,但是 start ...

  9. APP上线前,如何做运营推广工作?

    http://www.cocoachina.com/market/20150723/12731.html 一 竞品分析 1.选择竞品,做好定位(选择两个产品最好,最多三个). 如何获取竞品? A 百度 ...

  10. Effective C++: 02构造、析构、赋值运算

    05:了解C++默默编写并调用哪些函数 1:一个空类,如果你自己没声明,编译器就会为它声明(编译器版本的)一个copy构造函数.一个copy assignment操作符和一个析构函数.此外如果你没有声 ...