上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。
上一节文章链接:http://blog.youkuaiyun.com/lwj103862095/article/details/17538349
在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。
问:如何实现同一时刻只能有一个进程使用某个设备?
答:使用linux互斥机制
问:linux互斥机制有哪些?
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等
问:在这一节里,我们使用什么互斥机制?
答:原子变量/信号量,举二个例子来示范linux的互斥机制
问:如何使用原子变量的互斥机制?
答:先定义一个原子变量,然后再初始化它。具体如下:
/* 定义原子变量canopen并初始化为1 */ static> 问:与原子变量相关的函数有哪些?答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
atomic_t> 问:原子变量相关的函数在此驱动里,在哪来会被调用?答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
static>
原子变量互斥方式应用测试程序源码:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <poll.h> /*>
原子变量互斥方式测试步骤:[WJ2440]#>信号量互斥方式应用测试程序源码:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> //sleep #include <poll.h> #include <signal.h> #include <fcntl.h> int>
信号量互斥方式测试步骤:[WJ2440]# ls Qt fifth_drv.ko lib sddisk third_test TQLedtest fifth_test linuxrc second_drv.ko tmp app_test first_drv.ko mnt second_test udisk bin first_test opt sixth_drv.ko usr dev fourth_drv.ko proc sixth_test var driver_test fourth_test root sys web etc home sbin third_drv.ko [WJ2440]# insmod sixth_drv.ko [WJ2440]# lsmod sixth_drv 3472 0 - Live 0xbf000000 [WJ2440]# ls /dev/buttons -l crw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons [WJ2440]# ./sixth_test & [WJ2440]# ./sixth_test & [WJ2440]# ps PID USER VSZ STAT COMMAND 1 root 2088 S init 2 root 0 SW< [kthreadd] 3 root 0 SW< [ksoftirqd/0] 4 root 0 SW< [events/0] 5 root 0 SW< [khelper] 11 root 0 SW< [async/mgr] 237 root 0 SW< [kblockd/0] 247 root 0 SW< [khubd] 254 root 0 SW< [kmmcd] 278 root 0 SW [pdflush] 279 root 0 SW [pdflush] 280 root 0 SW< [kswapd0] 325 root 0 SW< [aio/0] 329 root 0 SW< [nfsiod] 333 root 0 SW< [crypto/0] 443 root 0 SW< [mtdblockd] 557 root 0 SW< [usbhid_resumer] 573 root 0 SW< [rpciod/0] 587 root 1508 S EmbedSky_wdg 589 root 2092 S -/bin/sh 590 root 2088 S /usr/sbin/telnetd -l /bin/login 602 root 1428 S ./sixth_test 603 root 1428 D ./sixth_test 604 root 2092 R ps由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态
,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。