旗标机制给予 scull 一个工具, 可以在存取 scull_dev 数据结构时用来避免竞争情况. 但是正确使用这个工具是我们的责任. 正确使用加锁原语的关键是严密地指定要保护哪个 资源并且确认每个对这些资源的存取都使用了正确的加锁方法. 在我们的例子驱动中, 感 兴趣的所有东西都包含在 scull_dev 结构里面, 因此它是我们的加锁体制的逻辑范围.

让我们在看看这个结构: struct scull_dev {

struct scull_qset *data; /* Pointer to first quantum set */ int quantum; /* the current quantum size */

int qset; /* the current array size */

unsigned long size; /* amount of data stored here */

unsigned int access_key; /* used by sculluid and scullpriv */ struct semaphore sem; /* mutual exclusion semaphore */

struct cdev cdev; /* Char device structure */

};

到结构的底部是一个称为 sem 的成员, 当然, 它是我们的旗标. 我们已经选择为每个虚 拟 scull 设备使用单独的旗标. 使用一个单个的全局的旗标也可能会是同样正确. 通常 各种 scull 设备不共享资源, 然而, 并且没有理由使一个进程等待, 而另一个进程在使 用不同 scull 设备. 不同设备使用单独的旗标允许并行进行对不同设备的操作, 因此, 提高了性能.

旗标在使用前必须初始化. scull 在加载时进行这个初始化, 在这个循环中: for (i = 0; i < scull_nr_devs; i++) {

scull_devices[i].quantum = scull_quantum;

scull_devices[i].qset = scull_qset; init_MUTEX(&scull_devices[i].sem); scull_setup_cdev(&scull_devices[i], i);

}

注意, 旗标必须在 scull 设备对系统其他部分可用前初始化. 因此, init_MUTEX 在 scull_setup_cdev 前被调用. 以相反的次序进行这个操作可能产生一个竞争情况, 旗标 可能在它准备好之前被存取.

下一步, 我们必须浏览代码, 并且确认在没有持有旗标时没有对 scull_dev 数据结构的 存取. 因此, 例如, scull_write 以这个代码开始:

if (down_interruptible(&dev->sem))

return -ERESTARTSYS;

注意对 down_interruptible 返回值的检查; 如果它返回非零, 操作被打断了. 在这个情 况下通常要做的是返回 -ERESTARTSYS. 看到这个返回值后, 内核的高层要么从头重启这 个调用要么返回这个错误给用户. 如果你返回 -ERESTARTSYS, 你必须首先恢复任何用户 可见的已经做了的改变, 以保证当重试系统调用时正确的事情发生. 如果你不能以这个方 式恢复, 你应当替之返回 -EINTR.

scull_write 必须释放旗标, 不管它是否能够成功进行它的其他任务. 如果事事都顺利, 执行落到这个函数的最后几行:

out:

up(&dev->sem); return retval;

这个代码释放旗标并且返回任何需要的状态. 在 scull_write 中有几个地方可能会出错; 这些地方包括内存分配失败或者在试图从用户空间拷贝数据时出错. 在这些情况中, 代码 进行了一个 goto out, 以确保进行正确的清理.

最新文章

  1. WCF简单使用(分别部署在控制台和IIS上)
  2. [转载]AxureRP学习成长之路
  3. linux下vim如何配置markdown插件
  4. percona-toolkit 之 【pt-slave-delay】说明
  5. 2014年5月份第1周51Aspx源码发布详情
  6. Serverlet程序
  7. Microsoft Mole原理及常见问题整理
  8. supersocket中quickstart文件夹下的MultipleCommandAssembly的配置文件分析
  9. Sudoku(回溯)
  10. android代码集锦
  11. C# 自定义控件的一些文章和博客
  12. 1135: 零起点学算法42——多组测试数据(求和)IV
  13. HDFS读写过程
  14. hdu2674 N!Again---思维
  15. java8接口定义增强
  16. css学习1
  17. selenium之批量执行测试用例生成HTML结果文件
  18. Android逆向笔记之AndroidKiller与Android Studio的使用
  19. spoj TBATTLE 质因数分解+二分
  20. IOS常用代码整理

热门文章

  1. Hibernate的DetachedCriteria使用(含Criteria)转载
  2. 【JZOJ4895】【NOIP2016提高A组集训第16场11.15】三部曲
  3. iOS9 CASpringAnimation 弹簧动画详解
  4. 中文乱码在java中URLEncoder.encode方法要调用两次解决
  5. 对The Curse of Dimensionality(维度灾难)的理解
  6. php代码在模板页的活用
  7. Myeclipse jdk的安装
  8. rank(),允许并列名次、复制名次自动空缺,结果如12245558……
  9. SDUT-3340_数据结构实验之二叉树一:树的同构
  10. Gym - 101480A_ASCII Addition