首页 > 代码库 > LDD3之并发和竞态-completion(完成量)的学习和验证

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.completecomplete_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

 

 

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