|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。6 w2 Z: z" O& v( c3 v
O5 |. M4 c8 D- W/ F; G* J
上一节文章:linux字符驱动之异步通知按键驱动
1 @& G+ t5 H* K M
% c( `! _* ]+ P! t* K4 F在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。
* S/ D8 A# f4 K& N9 z/ ~9 o' v; j }9 n' u
问:如何实现同一时刻只能有一个进程使用某个设备?- W7 v" t& A# a, ?( U6 O e
1 s1 [% q7 |; W; D( R) n
答:使用linux互斥机制
4 P# @9 b: P" z' B. B2 j8 L6 y" w! Y2 u4 _3 V9 [, ], z% k
问:linux互斥机制有哪些?
4 U8 ~" ^1 y% C; L$ \! a/ w9 O4 X& U2 L6 M. r) D2 ]
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等
3 ~5 K% @5 p% a
0 c4 U- \" g7 { U9 y问:在这一节里,我们使用什么互斥机制?0 ~4 J7 a$ \! }6 I" B
7 O9 w2 ?1 X! k3 s! y% ~
答:原子变量/信号量,举二个例子来示范linux的互斥机制3 o0 Y, s! w& ~+ O q, I
9 j( _0 h i' Q- b+ Z/ u1 Y问:如何使用原子变量的互斥机制?
7 c# b! ~- Q8 ^/ g# o6 g" {/ Q3 `* _8 W: @* ?6 L, f5 R
答:先定义一个原子变量,然后再初始化它。具体如下:
$ l, d9 n" D6 k7 k& S6 L
0 D& _: ^( t" I5 a8 a
$ n5 o l0 ~/ \2 C% {$ T* w/* 定义原子变量canopen并初始化为1 */& B' h/ q5 g. }' M, A1 a ]# O
static>- A6 \+ y L! X! T y3 G1 R) ]
问:与原子变量相关的函数有哪些?
4 V0 z Z O$ k- \答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
+ a4 l# e6 t& `1 o' o, i* A, t# U( I9 F
: k% C* P' j, `# w S# G7 z2 q* X$ x
atomic_t>2 H( O7 x R' T; Z5 b! y% Y
问:原子变量相关的函数在此驱动里,在哪来会被调用?0 E8 W4 \2 E2 B$ \: n5 c3 H# H( P
答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
5 G$ T( |" f* ]! |
; Y" ^+ c6 j- l* A K/ s7 L9 Q4 M
- ~1 W( t1 S) e" q# H; x* dstatic>& @: b7 W; z. {+ q6 q2 l
7 S/ n+ n, Q8 V
0 \3 ]9 \. f" I
原子变量互斥方式应用测试程序源码:
0 l: Z8 j1 C$ h9 A7 E& P- p
( d7 P/ W6 Y6 \- Q; l1 S2 M6 _3 b1 C/ s
#include <stdio.h>
% M4 J4 K# g4 u& T+ P s) ?#include <sys/types.h>' w: y! K; [2 z6 E7 u0 E) Q
#include <sys/stat.h>
, R+ T. l L% ]3 _3 i' h1 V' Z#include <fcntl.h>: j9 q, x8 G6 \0 p" T6 ^+ U1 ]
#include <unistd.h>* P8 J' K6 F' {
#include <poll.h>1 ?$ r2 A( b* D% h
% k' P8 ?7 s1 }4 h: \
/*>2 F1 [, P# Z# S0 U9 x1 \+ c
4 _9 B: z% U1 |& X
原子变量互斥方式测试步骤:
; ~+ q9 [& K) R* `! b: r v" q
+ S2 f, f( |8 |- q% q' f! A" \7 ][WJ2440]#>- S+ a) ]1 {0 E+ R a+ `: X& L/ W) n2 @9 ^
! m1 b' _" u/ h' x/ {8 p& ?
9 d: G5 b ~4 T. w4 C6 V3 |% c信号量互斥方式应用测试程序源码:/ b$ K8 p+ w: r: O. i9 Z- C! x, @
#include <stdio.h>
* m7 A$ L2 O6 y6 B: R#include <sys/types.h>/ m' ?! t$ Y* [5 b9 c
#include <sys/stat.h>+ y5 I0 F. y$ j9 D3 {$ `
#include <fcntl.h>
2 K. C d. J- n5 @6 w/ }#include <unistd.h> //sleep3 m/ n4 u; N3 W+ n
#include <poll.h>
) y& U. h2 o; V#include <signal.h>
! X! _% |" f* K#include <fcntl.h>
# j+ k! e1 p( d, s) b( l& h1 g4 b) Y' b3 V- l: h) V+ E z4 [
int>4 v, _5 N) f( j' t! K' Y9 c
5 M2 J% ?! q0 p3 t' N6 F; n
信号量互斥方式测试步骤:
% ?' o) `. x! {/ E8 ` q! m. `8 V/ n& ]
[WJ2440]# ls
! h( n" \& K9 y4 u- pQt fifth_drv.ko lib sddisk third_test) C5 w7 M# j! G! U8 C0 G# q G2 m
TQLedtest fifth_test linuxrc second_drv.ko tmp+ n6 S# f* A2 ^( v- B
app_test first_drv.ko mnt second_test udisk
6 P9 v; B8 i, o, J/ d( ?# V" g( _bin first_test opt sixth_drv.ko usr0 }2 t+ `+ d8 V* J( k* S
dev fourth_drv.ko proc sixth_test var
. |" k, Q+ K6 Q# i$ @% Idriver_test fourth_test root sys web
- e" Q# _8 }: b) Metc home sbin third_drv.ko/ W) Z" ~- i* \& \. |8 {* G
[WJ2440]# insmod sixth_drv.ko \5 {: V. G' ^/ Z
[WJ2440]# lsmod
1 g1 F I$ w- G5 G1 Q+ y& v6 Asixth_drv 3472 0 - Live 0xbf000000
0 u, z4 G1 ]! Z4 e# e[WJ2440]# ls /dev/buttons -l
8 p3 T7 i9 `! k' j, }+ R8 dcrw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons
8 X; u# u; t: ~[WJ2440]# ./sixth_test &( K! `* i4 _# J/ C, l
[WJ2440]# ./sixth_test &6 e6 y) Z. l! H; L3 n( h# j
[WJ2440]# ps
5 r; g2 n+ f! U; w9 V% L" j K7 ]! l PID USER VSZ STAT COMMAND
0 z, }; D W! F2 g* _! t0 J* N$ U2 g 1 root 2088 S init
# n5 F! a6 z; v0 @1 D 2 root 0 SW< [kthreadd]/ F0 D6 F8 D! V
3 root 0 SW< [ksoftirqd/0]
! W" K" M' @. c 4 root 0 SW< [events/0]
! V$ u0 D2 ^: r: E; ^ 5 root 0 SW< [khelper]
~- E( X. p# d, { 11 root 0 SW< [async/mgr]7 V8 M2 T6 q; s/ C g
237 root 0 SW< [kblockd/0]3 e+ G0 _$ k4 Q& ?6 q& Q
247 root 0 SW< [khubd]
( h$ w' d/ Y5 k4 _; a 254 root 0 SW< [kmmcd]
) Q9 A0 ^' { u( X! C- x 278 root 0 SW [pdflush]
9 p5 g w, V& ^8 O: f 279 root 0 SW [pdflush]. {% d% `$ N$ g# N
280 root 0 SW< [kswapd0]/ ?/ y# n" u% V+ e/ H! i2 s
325 root 0 SW< [aio/0]
' n) v, T# r: m 329 root 0 SW< [nfsiod]
, T) q. |3 A( w" J- h8 r7 E 333 root 0 SW< [crypto/0]
& D8 v; P/ Z; L4 b5 T 443 root 0 SW< [mtdblockd]
y, v+ U" }7 c" T; a 557 root 0 SW< [usbhid_resumer]
3 E9 p: H3 p) v4 U0 G0 u: F& l4 C+ y 573 root 0 SW< [rpciod/0]* ~8 L" n' ]" f* {5 g7 o+ h+ {3 G. W
587 root 1508 S EmbedSky_wdg
% s0 }3 D4 ~6 U1 p* ]* v; C& o4 } 589 root 2092 S -/bin/sh% D) A1 r) V9 z6 q9 T4 p
590 root 2088 S /usr/sbin/telnetd -l /bin/login
0 O. I p% K9 s' K( g 602 root 1428 S ./sixth_test
6 X; S M/ h, |6 W# Z 603 root 1428 D ./sixth_test
/ H1 {; j0 F4 ]7 }" D 604 root 2092 R ps( z- o+ g1 h' ~, [$ O; t3 ^4 B
% m4 G/ q/ s' ?由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。
1 b& N5 d, F+ w3 M0 x9 l1 Z# U
) g+ p! h+ G8 {7 n- f0 g. h/ k7 b' ^* g
; i, J$ j: _. }/ \$ O
$ J2 W: c! N! V6 c8 } h2 B3 U' o1 y
: k( o6 h/ ^7 l1 [ |
|