linux Completions 机制
内核编程的一个普通模式包括在当前线程之外初始化某个动作, 接着等待这个动作结束. 这个动作可能是创建一个新内核线程或者用户空间进程, 对一个存在着的进程的请求, 或 者一些基于硬件的动作. 在这些情况中, 很有诱惑去使用一个旗标来同步 2 个任务, 使 用这样的代码:
struct semaphore sem; init_MUTEX_LOCKED(&sem); start_external_task(&sem); down(&sem);
外部任务可以接着调用 up(??sem), 在它的工作完成时.
事实证明, 这种情况旗标不是最好的工具. 正常使用中, 试图加锁一个旗标的代码发现旗 标几乎在所有时间都可用; 如果对旗标有很多竞争, 性能会受损并且加锁方案需要重新审 视. 因此旗标已经对"可用"情况做了很多的优化. 当用上面展示的方法来通知任务完成, 然而, 调用 down 的线程将几乎是一直不得不等待; 因此性能将受损. 旗标还可能易于处 于一个( 困难的 ) 竞争情况, 如果它们表明为自动变量以这种方式使用时. 在一些情况 中, 旗标可能在调用 up 的进程用完它之前消失.
这些问题引起了在 2.4.7 内核中增加了 "completion" 接口. completion 是任务使用的 一个轻量级机制: 允许一个线程告诉另一个线程工作已经完成. 为使用 completion, 你 的代码必须包含 <linux/completion.h>. 一个 completion 可被创建, 使用:
DECLARE_COMPLETION(my_completion);
或者, 如果 completion 必须动态创建和初始化: struct completion my_completion; /* ... */
init_completion(&my_completion); 等待 completion 是一个简单事来调用:
void wait_for_completion(struct completion *c);
注意这个函数进行一个不可打断的等待. 如果你的代码调用 wait_for_completion 并且 没有人完成这个任务, 结果会是一个不可杀死的进程.[18]18
另一方面, 真正的 completion 事件可能通过调用下列之一来发出: void complete(struct completion *c);
void complete_all(struct completion *c);
如果多于一个线程在等待同一个 completion 事件, 这 2 个函数做法不同. complete 只 唤醒一个等待的线程, 而 complete_all 允许它们所有都继续. 在大部分情况下, 只有一 个等待者, 这 2 个函数将产生一致的结果.
一个 completion 正常地是一个单发设备; 使用一次就放弃. 然而, 如果采取正确的措施 重新使用 completion 结构是可能的. 如果没有使用 complete_all, 重新使用一个 completion 结构没有任何问题, 只要对于发出什么事件没有模糊. 如果你使用 complete_all, 然而, 你必须在重新使用前重新初始化 completion 结构. 宏定义:
INIT_COMPLETION(struct completion c); 可用来快速进行这个初始化.
作为如何使用 completion 的一个例子, 考虑 complete 模块, 它包含在例子源码里. 这 个模块使用简单的语义定义一个设备: 任何试图从一个设备读的进程将等待(使用 wait_for_completion)直到其他进程向这个设备写. 实现这个行为的代码是:
DECLARE_COMPLETION(comp);
ssize_t complete_read (struct file *filp, char user *buf, size_t count, loff_t *pos)
{
printk(KERN_DEBUG "process %i (%s) going to sleep\n",current->pid, current->comm);
wait_for_completion(&comp);
printk(KERN_DEBUG "awoken %i (%s)\n", current->pid, current->comm); return 0; /* EOF */
}
ssize_t complete_write (struct file *filp, const char user *buf, size_t count, loff_t *pos)
在本书编写时, 添加可中断版本的补丁已经流行但是还没有合并到主线中.
printk(KERN_DEBUG
"process %i (%s) awakening the readers...\n", current-
>pid,
current->comm); complete(&comp);
return count; /* succeed, to avoid retrial */
}
有多个进程同时从这个设备"读"是有可能的. 每个对设备的写将确切地使一个读操作完成, 但是没有办法知道会是哪个.
completion 机制的典型使用是在模块退出时与内核线程的终止一起. 在这个原型例子里, 一些驱动的内部工作是通过一个内核线程在一个 while(1) 循环中进行的. 当模块准备好 被清理时, exit 函数告知线程退出并且等待结束. 为此目的, 内核包含一个特殊的函数 给线程使用:
void
complete_and_exit(struct completion *c, long retval);
linux Completions 机制的更多相关文章
- Linux模块机制浅析
Linux模块机制浅析 Linux允许用户通过插入模块,实现干预内核的目的.一直以来,对linux的模块机制都不够清晰,因此本文对内核模块的加载机制进行简单地分析. 模块的Hello World! ...
- android & Linux uevent机制
Linux uevent机制 Uevent是内核通知android有状态变化的一种方法,比如USB线插入.拔出,电池电量变化等等.其本质是内核发送(可以通过socket)一个字符串,应用层(andro ...
- 利用linux信号机制调试段错误(Segment fault)
在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过 ...
- Linux 内存机制详解宝典
Linux 内存机制详解宝典 在linux的内存分配机制中,优先使用物理内存,当物理内存还有空闲时(还够用),不会释放其占用内存,就算占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于 ...
- Linux Namespaces机制——实现
转自:http://www.cnblogs.com/lisperl/archive/2012/05/03/2480573.html 由于Linux内核提供了PID,IPC,NS等多个Namespace ...
- Linux Namespaces机制
转自:http://www.cnblogs.com/lisperl/archive/2012/05/03/2480316.html Linux Namespaces机制提供一种资源隔离方案.PID,I ...
- Linux分页机制之概述--Linux内存管理(六)
1 分页机制 在虚拟内存中,页表是个映射表的概念, 即从进程能理解的线性地址(linear address)映射到存储器上的物理地址(phisical address). 很显然,这个页表是需要常驻内 ...
- [转帖]Linux分页机制之分页机制的演变--Linux内存管理(七)
Linux分页机制之分页机制的演变--Linux内存管理(七) 2016年09月01日 20:01:31 JeanCheng 阅读数:4543 https://blog.csdn.net/gatiem ...
- [转帖]Linux分页机制之概述--Linux内存管理(六)
Linux分页机制之概述--Linux内存管理(六) 2016年09月01日 19:46:08 JeanCheng 阅读数:5491 标签: linuxkernel内存管理分页架构更多 个人分类: ┈ ...
随机推荐
- No.1 Verilog HDL简介
硬件描述语言HDL(Hardware Description Language)是一种用形式化方法来描述数字电路和系统的语言.设计者利用HDL可以从抽象到具体逐层描述自己的设计思想,用一系列的分 ...
- iOS 9 学习系列:Storyboard References
http://www.cocoachina.com/ios/20150922/13474.html 如果你曾经使用 interface builder 创建过一个复杂.界面非常多的应用,你就会明白最后 ...
- mysql操作手册2
6 rows in set (0.00 sec) # 我们再把 table 的位置交换一下,再用 right join 试试 select a.id,a.name,b.dept_id fr ...
- Python学习之路4☞条件和循环
一.if语句 1.1 功能 计算机又被称作电脑,意指计算机可以像人脑一样,根据周围环境条件(即expession)的变化做出不同的反应(即执行代码) if语句就是来控制计算机实现这一功能 1.2 语法 ...
- 2019-9-23-dotnet-判断特定进程存在方法
title author date CreateTime categories dotnet 判断特定进程存在方法 lindexi 2019-09-23 16:20:42 +0800 2019-09- ...
- php上传文件与图片到七牛的实例详解
上传文件到七牛最简单的方式就是使用七牛官方最新的SDK 用composer安装PHP SDK composer require qiniu/php-sdk 上传文件到七牛 use Qiniu\Auth ...
- Java练习 SDUT-1131_最大公约数与最小公倍数
C/C++训练1---最大公约数与最小公倍数 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入两个正整数,求它们的最 ...
- 安装pip3遇到:E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).
安装pip3遇到:E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution). 具 ...
- 1月北上广P2P平台之最 平台数成交量现双降
1月北上广P2P平台之最 平台数成交量现双降 今日(2月9日),网贷之家联合盈灿咨询发布了<北上广地区P2P网贷行业2017年1月月报>.月报数据显示,截至2017年1月底,北京.上海 ...
- @bzoj - 3836@ [Poi2014]Tourism
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个n个点,m条边的无向图,其中你在第i个点建立旅游站点的费 ...