|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。( W" i' P% d! ]$ j1 H9 }/ v
9 G% V! Q3 e3 s- _9 S
上一节文章:linux字符驱动之异步通知按键驱动1 f3 S2 Z, Q0 H* _
* Q* B/ S- N3 q
在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。
) p Z9 a7 J! E' X( a
! R D, h' i; B3 I7 ?8 A问:如何实现同一时刻只能有一个进程使用某个设备?; c4 e: f& U; H7 O9 [
: ~% Z" Q+ r; t8 G# x9 n2 J答:使用linux互斥机制# }' \7 e z; H# e
7 c/ _; j' \6 J: S; {4 [8 D
问:linux互斥机制有哪些?! F- V Y+ f- [
- o- G& s: J$ Q3 S4 E. N1 E答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等
; r& f: E1 v; _, X% l m2 P2 M) s& ~- f/ v3 ?9 p$ q( F
问:在这一节里,我们使用什么互斥机制?
3 c; a: u# O* J6 R1 u$ d1 a# ^. I/ ^
/ G& @% g! F' Y3 s+ u/ {答:原子变量/信号量,举二个例子来示范linux的互斥机制
/ b! e9 `% X) y- ?" V$ y& s- J! q
问:如何使用原子变量的互斥机制?
# |6 ~. i' ?$ }2 j$ E @0 u' `, A4 i |
答:先定义一个原子变量,然后再初始化它。具体如下:
, m! l7 r4 { S* G# X' k
4 h, @& q) p# b8 P9 o& Z, i( `4 ^& P3 @! ~6 Q3 [1 Y- U
/* 定义原子变量canopen并初始化为1 */
* f- X1 q2 _" I2 ~; \2 K+ ?static>9 e. ^/ B6 ?- S
问:与原子变量相关的函数有哪些?
* l: Y. ?) h) b& y. {答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
8 K S- B/ x4 p6 K6 B+ O6 h) |9 i/ _, @
" _ l% @) t7 {: latomic_t>% {- Q2 B+ {; f; N: S% e
问:原子变量相关的函数在此驱动里,在哪来会被调用?
4 u1 M# j; I: o9 } }4 c6 o' |8 q答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:9 r' m" A, f" R4 Z: i+ }! |
2 {! R2 t9 s+ H
8 b8 r4 a# S$ A$ z/ ?
static>
{$ L- b) V$ V: m4 J* v3 @! w5 |3 f& Z/ E0 s
# j/ O" O1 W1 h3 T
原子变量互斥方式应用测试程序源码:
& c) l' h' G) t0 h! J
2 u0 S0 k- v* o" ]' }# v9 W/ S2 K6 h
( u+ w1 N3 N) N, ^% P+ B6 d$ [#include <stdio.h>
2 [0 j h8 @! [#include <sys/types.h>" x1 j) {0 }+ v# J$ r
#include <sys/stat.h>* x' {5 f- ]9 A3 |
#include <fcntl.h>$ M. a- V' O4 j8 M0 |' J' V
#include <unistd.h># G# B; h- s$ q3 w$ e7 u3 q3 L* g
#include <poll.h>3 S9 H8 L; b5 q) _+ m
" j% y1 a( h$ y9 o, E& d/*>
. Q. [1 j7 [: n3 z( j( j# ]- W% k) {( P) H6 h
原子变量互斥方式测试步骤:! P" [0 r5 ]- x, n; X) J
, b8 U$ |* l; x+ n; c
[WJ2440]#>
* `$ I9 m# | s/ p8 R S. K8 [, N! \, g1 n7 O
: X ] J* |' x3 c信号量互斥方式应用测试程序源码:
& B$ o" w- u/ V) K8 n2 v; X#include <stdio.h>2 q s; x/ c3 J. O0 z( R" X* J
#include <sys/types.h>9 R' ]6 a' }5 y% `7 Z" {/ E: D7 i
#include <sys/stat.h>
+ W- s& ^* o/ ^& H1 O3 b: K4 r#include <fcntl.h>
/ m" V7 w/ k9 S- o#include <unistd.h> //sleep$ n ~ L, J+ \% z4 y' `* ^
#include <poll.h>
- t- e5 W7 ]" N: S, H3 Y; ?" u7 _#include <signal.h>) }: r2 _( \- c5 \
#include <fcntl.h>
4 a! [4 \; a9 m" g4 i) ?' y) z4 W9 G9 A2 V
int>
; V' G2 d: M8 w0 K: V a9 _. U$ W# |1 f' a
0 t1 }, b7 ] w" }; q0 V7 {信号量互斥方式测试步骤:
: Z% W; {! P$ e) y: o( G7 W; o- }7 L* O& x
[WJ2440]# ls% w( p% j) @# L. j: X& z' }
Qt fifth_drv.ko lib sddisk third_test* } s L% J m6 A6 b' k
TQLedtest fifth_test linuxrc second_drv.ko tmp
/ [1 `; D5 S) q1 mapp_test first_drv.ko mnt second_test udisk( z: |) n/ e6 w& Q" o
bin first_test opt sixth_drv.ko usr( {- D, `7 I1 d$ ~) z, n# {
dev fourth_drv.ko proc sixth_test var
6 R u* g) _3 Y9 {: Ydriver_test fourth_test root sys web/ z B9 L) @' ~- b
etc home sbin third_drv.ko1 b9 Y2 [5 n3 m1 _# X
[WJ2440]# insmod sixth_drv.ko # Y. J, r. e1 D0 B7 z& C$ F
[WJ2440]# lsmod
- P6 l1 C0 r# U- k! _; h' w( Xsixth_drv 3472 0 - Live 0xbf000000
) J) b6 j. s+ j) ~) U$ o+ \[WJ2440]# ls /dev/buttons -l/ w- B, Z+ h \6 m1 b+ B q; ]$ a. v, c
crw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons @4 } ~6 J0 F8 `
[WJ2440]# ./sixth_test &
6 h- ^# B2 a# [[WJ2440]# ./sixth_test &
8 }5 J6 V1 r+ B( S5 t& J4 L4 }[WJ2440]# ps
2 d; j1 z. l+ M, h PID USER VSZ STAT COMMAND# Y, l' j1 ^0 I2 h# a' D, c; q
1 root 2088 S init
" U- k, C) ^) _ 2 root 0 SW< [kthreadd], h- Z' }0 L# F3 d
3 root 0 SW< [ksoftirqd/0]% M# Q/ S9 x, S
4 root 0 SW< [events/0]8 Z6 y- M/ ~1 K6 X7 N
5 root 0 SW< [khelper]( ?- }! ^. ?5 {, |2 A. k* _- d r
11 root 0 SW< [async/mgr]& d/ m0 v5 q) ]% D$ b
237 root 0 SW< [kblockd/0]: m6 @/ N* m- D+ ~& Y
247 root 0 SW< [khubd]
& m. o& g: z. Z$ v. f0 [) Z2 @% P 254 root 0 SW< [kmmcd]
8 d. O- j' S7 l* w9 R; @. | 278 root 0 SW [pdflush]
7 V3 Q4 D; E" |: i( f, e7 t 279 root 0 SW [pdflush]
+ R1 P) z# S, n z" T' P: p 280 root 0 SW< [kswapd0]
5 S; _7 l* L' w0 W9 G9 h/ t. W0 P 325 root 0 SW< [aio/0]9 m6 m, o t8 q7 j3 b* U9 |- ]- P
329 root 0 SW< [nfsiod]5 u. h* O+ Z, \+ {
333 root 0 SW< [crypto/0]+ l; D1 v. s: l& M
443 root 0 SW< [mtdblockd]
' e) H S) {0 I* \+ Z, L# H4 x 557 root 0 SW< [usbhid_resumer]4 f! ^: W- t1 K9 Y+ h) o; M
573 root 0 SW< [rpciod/0]3 ~$ o' Q8 z7 |7 ^; \
587 root 1508 S EmbedSky_wdg
A: v1 [" ?7 L( h 589 root 2092 S -/bin/sh
7 o7 ?% w5 P; X5 x 590 root 2088 S /usr/sbin/telnetd -l /bin/login
|9 l! l6 E: h 602 root 1428 S ./sixth_test' @# K. v2 l& A+ n# r+ e0 U4 L
603 root 1428 D ./sixth_test( W# Z& E8 v7 K& }5 v
604 root 2092 R ps4 }3 y4 x, V: ]3 c
$ ?6 @! t# X4 U6 z+ ]由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。! A O* @, N+ O" g3 S
1 P5 e7 L2 O. S: D
& E& F+ F" T# }
3 P+ P, a$ G( P; u
v2 m" F. ]$ X w, d' v' b
5 X# p. a- j- G$ Q: ?! z |
|