LDD3之并发和竞态-completion(完成量)的学习和验证

LDD3之并发和竞态-completion(完成量)的学习和验证

首先说下测试环境:

Linux2.6.32.2

Mini2440开发板

一开始难以理解书上的书面语言,这里《linux中同步例子(完成量completion)》举了一个公交车上司机和乘客的例子还不错,转过来:

这是一个公交司机和售票员之间的线程调度,用于理解完成量,完成量是对信号量的一种补充,主要用于多处理器系统上发生的一种微妙竞争。在这里两个线程间同步,只有当售票员把门关了后,司机才能开动车,只有当司机停车后,售票员才能开门。

如果还是不能够理解就只能反复的调试程序了,现在就把书上的例子使用起来,编译出来completion.ko后进行如下步骤验证

# 1.插入内核模块

insmod completion.ko

# 2.查看申请的次设备号${MINOR}

cat /proc/devices | grep complete

# 3.创建设备节点

mknod /dev/complete c ${MINOR} 0

# 4.首先开启一个终端查看内核信息输出

cat /proc/kmsg

# 5.一个终端读,会睡眠

cat /dev/complete

# 6,另一个终端写

echo /dev/complete

# 7.查看输出

<7>[22050.937732] process 28852 (cat) going to sleep

<7>[22093.994805] process 28866 (bash) awakening the readers...

<7>[22093.994817] awoken 28852 (cat)

下面来验证LDD3上所说的:

1.wait_for_completion

注意wait_for_completion执行会一个非中断的等待,如果没有人来完成该任务,则会产生一个不可杀的进程。

验证:

在运行了cat /dev/complete的时候就已经运行了wait_for_completion,并不运行写程序,看不杀的进程是会不会存在。

通过尝试确实是终止不了。

结论:wait_for_completion等待后如果没人处理任务,那么真的会产生一个不可杀的用户进程,所以这个要小心使用

2.complete和complete_all

1)complete

在执行第3步(最下)后,只有第2步的cat被唤醒,第1个还在睡眠。

结论:和书的一样。

2)complete_all

分了两种情况来测试:

a.init_completion + complete_all

测试失败!和书上的不照!

b.DECLARE_COMPLETION + complete_all

测试成功!

结论:complete只会唤醒一个等待线程,complete_all会唤醒所有等待线程,前提是静态创建

3.INIT_COMPLETION

根据书上描述这个是和complet_all配合使用的,那么就测试一下驱动。

结论:使用INIT_COMPLETION进行重新初始化后,完成量可以多次使用

4.complete_and_exit

1).当内核准备清除该模块时,exit函数会告诉该线程退出并等待completion

这段描述不理解,实验证明一下:

不过看了原型,有点眉目了,这个函数是要添加到exit_xxx函数中的,也就是当没有完成时,是卸载不了的,但是为了卸载可以调用这个函数进行强制完成并卸载。检验一下,直接卸载:

会像图中所示,提示“资源不可用!”。但如果在complete_cleanup中添加complete_and_exit后,同样是“资源不可用!”说明假设失败。

2).决定应用程序的退出码?

同样假设失败,这里填写的是-1,但是应用程序退出码仍然是0.不过有一点是确实可以代替使用!

3).内核多进程中子进程的退出码

驱动群中群主是这样说的。

结论:由于多进程还没有掌握,这个先遗留下来,以后再来补充

5.wait_for_completion_timeout

结论:不可以被中断,到定时时间无人处理则自行结束

6.wait_for_completion_interruptible

这个并没有在LDD3中出现,但是很可以就是LDD3中注2中提到的可中断版本.

结论:证实可以被ctrl+c中断,即用户空间的进程可以被杀死

7.wait_for_completion_interruptible_timeout

结论:10s后如果没有completion则自行中断。

8.wait_for_completion_killable

从源码和实验结果上看不出和wait_for_completion_interruptible有任何区别,代码是前者使用的是TASK_INTERRUPTIBLE后者使用的是 TASK_KILLABLE。

理论上:TASK_NTERRUPTIBLE 睡眠,可以被信号唤醒;TASK_KILLABLE睡眠 只能被致命信号唤醒

不过现在没有办法区别哪些是致命信号,哪些不是!

9.wait_for_completion_killable_timeout

同样,从源码和实验结果上看不出和wait_for_completion_interruptible_timeout有任何区别,代码是前者使用的是TASK_INTERRUPTIBLE后者使用的是 TASK_KILLABLE。

10.try_wait_for_completion

其返回值始终为0,不知道如何操作才用使其返回值为1.

结论:完全不明白它存在的意义

11. completion_done

结论:无论有无等待者,判断出来的都是有!进程或者代码中都有把等待信息去掉都无济于事

LDD3之并发和竞态-completion(完成量)的学习和验证

时间: 2024-10-06 01:19:21

LDD3之并发和竞态-completion(完成量)的学习和验证的相关文章

LDD3阅读笔记之内核中的并发和竞态

内核中的并发和竞态 一般驱动程序运行在内核态中,只能调用内核空间中提供的函数,因此在处理并发和竞态时不能使用用户空间提供的库,如pthread库,内核有着自己的一套内部实现机制. 并发及其管理 现代Linux系统中存在大量的并发来源,因此会导致可能的竞态.SMP系统甚至可能在不同的处理器上同时执行我们的代码.内核代码是可抢占的,因此,我们的驱动程序代码可能在任何时候丢失对处理器的独占,而拥有处理器的进程可能正在调用我们的驱动程序代码.设备中断是异步事件,也会导致代码的并发执行.内核还提供了很多可

Linux内核分析(七)----并发与竞态

Linux内核分析(七) 这两天家里的事好多,我们今天继续接着上一次的内容学习,上次我们完善了字符设备控制方法,并深入分析了系统调用的实质,今天我们主要来了解一下并发和竞态. 今天我们会分析到以下内容: 1.      并发和竞态简介 2.      竞态解决办法 3.      为我们的虚拟设备增加并发控制 在前几次博文我们已经实现了简单的字符设备,看似完美但我们忽视了一个很严重的问题,即并发问题,那么什么是并发,又如何解决并发呢,我们下面进行分析. l  并发和竞态简介 1.       并

Hasen的linux设备驱动开发学习之旅--linux设备驱动中的并发与竞态

/** * Author:hasen * 参考 :<linux设备驱动开发详解> * 简介:android小菜鸟的linux * 设备驱动开发学习之旅 * 主题:linux设备驱动中的并发与竞态 * Date:2014-11-04 */ 1.并发与竞态 并发(concurrency)指的是多个执行单元同时.并行被执行,而并发的执行单元对共享资源(软件上的全 局变量,静态变量等)的访问则很容易导致竞态(race conditions). 主要的竞态发生在以下几种情况: (1)对称多处理(SMP)

LINUX设备驱动程序笔记(四)并发和竞态

       <一>.并发及其管理 大部分竞态可通过使用内核的并发控制原语,并应用几个基本的原理来避免.第一个规则是,只要可能,就应该避免资源的共享,这种思想的明显应用就是避免使用全局变量.但硬件资源本质上就是共享的,软件资源经常需要对其他执行线程可用.全局变量并不是共享数据的唯一途径,只要我们的代码将一个指针传递给了内核的其他部分,一个新的共享就可能建立.在单个执行线程之外共享硬件或软件资源的任何时候,因为另外一个线程可能产生对该资源的不一致观察,因此必须显示地管理对该资源的访问.访问管理的

《Linux Device Drivers》第五章 并发和竞态——note

并发及其管理 竞态通常作为对资源的共享访问结果而产生 当两个执行线程需要访问相同的数据结构(或硬件资源)时,并发的可能性就永远存在 只要可能就应该避免资源的共享,但共享通常是必须的,硬件本质上就是共享的 访问管理的常见技术称为"锁定"或者"互斥" 信号量和互斥体 建立临界区:在任意给定的时刻,代码只能被一个线程执行 可以使用一种锁定机制,当进程在等待对临界区的访问时,此机制可让进程进入休眠状态 一个信号量本质上是一个整数值,它和一对函数联合使用,这一对函数通常称为P

并发与竞态

linux驱动--并发和竟态 序--正在运行的多个用户空间程序可能以一个令人惊讶的组合方式访问我们的代码.SMP系统甚至可能在不同的处理器上同时执行我们的代码.内核代码是可抢占的,因此我们的驱动程序代码可在任何时候丢失对处理器的独占. 信号量(semaphore)的实现: 有一对函数,通常成为P和V,加锁用P,解锁用V.在任何时刻只能有单个执行上下文拥有时,这种模式一个信号量也称谓"互斥体(mutex)".Linux内核中几乎所有信号量均用于互斥. 内核代码必须包括<asm/se

linux设备驱动程序之并发和竞态(二)

其实这blog都是阅读ldd3时的一些总结,巩固自己的学习,也方便后期的使用.大家也可以直接阅读ldd3原文. 锁陷阱 所谓的锁陷阱就是防止死锁. 不明确的规则: 1.不论是信号量还是 自旋锁,都不允许锁拥有者第二次获得这个锁(会死锁). 2.系统直接调用的那些函数要获得信号量,保护要访问的设备结构.而内部函数的访问则可以根据需要上锁. 锁顺序规则: 1.如果都要获取一系列锁的话,那么可以按照一定顺序规则来获取锁,即:获取多个锁时,锁的顺序一直: 2.如果要获取自己的局部锁和系统的中心锁,则先获

linux设备驱动第五篇:驱动中的并发与竟态

综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被执行.而并发的执行单元对共享资源(硬件资源和软件上的全局.静态变量)的访问则容易导致竞态(race conditions).可能导致并发和竟态的情况有: SMP(Symmetric Multi-Processing),对称多处理结构.SMP是一种紧耦合.共享存储的系统模型,它的特点是多个CPU使用共

linux设备驱动系列:如何处理竞态关系

综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被执行.而并发的执行单元对共享资源(硬件资源和软件上的全局.静态变量)的访问则容易导致竞态(race conditions).可能导致并发和竟态的情况有: SMP(Symmetric Multi-Processing),对称多处理结构.SMP是一种紧耦合.共享存储的系统模型,它的特点是多个CPU使用共