当前位置: 首页 >> 程序设计 >> linux device driver 3读书笔记:Chapter 6
 

linux device driver 3读书笔记:Chapter 6

作者:      来源:http://layne-sah.longlong.cn/sah/     发表时间:2006-03-16     浏览次数:      字号:    

第六章的笔记。

Advanced Char Driver Operations

  看完第六章之后,时间安排有了变化。接下来的第七、八章(Time, Delays, and Deffered Work 和 Allocating Memory)只能暂时略过,从第九章继续看。

  第六章中介绍的是Char设备驱动中,除读写操作以外的常见操作,包括:

    1. ioctl
    2. Blocking I/O
    3. poll and select
    4. Asynchronous Notification
    5. Seeking a Device
    6. Access Control on a Device File

ioctl

  ioctl以前给我感觉挺神秘的,原来就是选好cmd的号码,然后写个switch就行了。关键是这一章还没介绍如何真正操作硬件,所以用的ioctl的例子也只是在软件部分的一些动作。这样当然就没什么神秘的了。

Blocking I/O

  使用sleep时应该注意的一点是,必须十分确定自己一定会被wake up,才可以开始sleep。其实前面讲Semaphore的时候,已经涉及到了sleep的概念。但是到了这里才开始真正介绍sleep的种类,以及进程如何使自己开始sleep的两种方式(simply调用wait_event()的方式,和所谓“manual”的方式)。

  第一种,也是比较简单的sleep基本上是这样:

    1. 创建一个wait_queue_head。两种方法:
      DECLARE_WAIT_QUEUE_HEAD(my_queue);
        或
      wait_queue_head_t my_queue;init_waitqueue_head(my_queue);
    2. 调用wait_event()(或者个系列的其他函数):

wait_event(myqueue, condition);

其中的condition就是这个进程wake up的条件。

  然后,当然了,应该会有另一个进程调用wake up进程的函数“wake_up(&my_queue)”。这个函数会wake up所有my_queue上的进程。(对应wait_event()系列的其他函数,wake_up()也有若干变形。)

  第二种,manual sleep实际上就是把wait_event()这个宏拆开。这样可以做出更复杂的sleep(比如可以用prepare_to_wait_exclusive())。

  使用第一种sleep方式时,一般的情况下,当wake_up(&my_queue)被调用时,如果my_queue上面有多个进程在等待condition这个条件,则它们将同时被wake up。在看了wait_event()的定义以后,发现其实它内部就是一个循环,一旦被wake_up,就去检查condition是否确实为真,以判断是否需要继续sleep。但是必须注意的是,由于race的存在,这也并不意味着从wait_event()返回后condition就一定是真。

  另外,这一章里,还学到了schedule()函数。schedule()就是告诉Linux,你现在应该马上重新考虑下应该把CPU交给哪个进程使用,也就是当年操作系统课中讲的“从用户态切换到系统态”。这个动作就是一个进程在把自己的state设置为TASK_INTERRUPTIBLE或TASK_UNITERRUPTIBLE,并把自己加入sleep队列以后,要做的事情。这里还有一个有意思的事情就是,如果在进程完成了这两项动作以后,而还没有调用schedule()之前的空隙,有人调用了wake_up()试图唤醒这个进程,Linux并不会出乱子。因为wake_up()正好做了和那两项动作相反的事,所以当这个进程重新获得CPU,并继续执行到schedule()时,scheduler会直接返回。

  回顾一下Blocking I/O这部分的内容,感觉最重要的就是要想清楚流程。down_interruptible()以后进入一个循环,除非condition成立才可以退出循环。在循环体内,当condition不成立时,要先up(),再开始sleep,睡醒了之后再down_interruptible()并回到循环开始,重新判断condition。而循环体内的sleep那部分也挺烦。要先prepare_to_wait(),然后在睡前最后确认一次condition,确实仍然不成立,才调用schedule()。schedule()返回以后先finish_wait(),再看看是怎么醒的。如果是某Signal给吵醒的,要return -ESYSRESTART;重新来过。否则是自然醒,那就算是睡眠结束,继续上面说的“睡醒了之后在down_interruptible()那段”。

poll and select

  poll和select是Unix时代传下来的一个系统调用的两个版本,在file_operations结构中都是用poll()实现的。poll用来查看当前某设备可用的操作(读、写等)。在程序不希望进入sleep状态等待某个I/O设备时,它们通常会在操作前调用poll来查看设备状态。

  poll涉及到一些乱七八糟的数据结构,什么poll_table之类的。这部分只了解了poll的作用,更深的没仔细看。

Asynchronous Notification

  异步通知。也就是POSIX进程通信机制中的“Signal”,信号机制。其目的是为了让(尤其是低优先级的)进程可以更迅速地响应某些事件。这部分也没仔细看,只是知道进程需要用fcntl()在设备上注册自己。

Seeking a Device

  就是讲了一些和fops.llseek()有关的内容,说有些设备不支持seek操作的,该怎么办。

Access Control on a Device File

  scull系列的最后几个终于出场了。这章介绍了几种常见的访问控制方式:

    1. Single Open
        很直接的方法。在设备的结构中加个锁,第一次open就锁住,以后再open就返回一个-EBUSY。这样一个设备就只能open一次了。
    2. Restricting Access to a Single User at a Time
        有时候要求同一个设备可以被open多次,但必须只能是由同一个用户。有一种可能就是为了确保在进行多个进程在某个设备上的race时,不希望其他用户的进程打扰。这可以在open中判断uid,至于判断之后的处理方法有几种:
      1. Returning -EBUSY
        直接返回“忙”,没啥说的。
      2. Blocking open
        让后来的用户的进程sleep。
      3. Cloning the Device on open
        为后来的用户的进程创建一个副本。一个例子就是console设备。

  这就是第六章的内容了,很杂。单独写一篇看来是对了。

责任编辑 webmaster

 
 
 
 
 
评论更多>>
 
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •