|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。
9 z1 J( ]8 F* M) i: f8 w. l6 T. ~# ^; v' H# W
上一节文章:linux字符驱动之异步通知按键驱动
6 A% S( d3 @+ }. w, ?3 ~# @8 ?* V
% z* G" H U: O3 ] m8 B在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。
( N+ D- A2 [7 J8 ~2 @3 w3 b0 b7 I; X9 C% {" i4 _$ e( V# N9 d
问:如何实现同一时刻只能有一个进程使用某个设备? j6 H7 `# V; |( _ }! {7 O; h9 w
( ?) w; R; p" ~! ]7 z \# H" R* B6 ~
答:使用linux互斥机制
+ |: h4 k/ k9 J: t5 N! A
( A8 o4 B) c# D: J6 F问:linux互斥机制有哪些?1 V4 d$ c/ Y+ k; g
x! i$ j( D% M0 D! P
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等
) O% D9 t% x; i# m4 Y/ o# a
" I7 K0 {3 E: _问:在这一节里,我们使用什么互斥机制?# t% J& t% e. I
, r6 S9 j, L7 W2 O答:原子变量/信号量,举二个例子来示范linux的互斥机制' P4 E4 T) C8 L; X
1 p" _# u4 D, y/ s/ y
问:如何使用原子变量的互斥机制?
5 n4 B0 ?. g" M5 W0 I6 f+ y! Q6 d, Z
* r# h d9 _7 Z0 Q' q" |) g答:先定义一个原子变量,然后再初始化它。具体如下:: {: L: V. X* E
" z- M/ e! l! d% j6 p
0 T! z2 o! R" T/* 定义原子变量canopen并初始化为1 */
. ^: @$ R3 s& H7 Jstatic>
- W# D$ ^9 V/ s y问:与原子变量相关的函数有哪些?
; v. ~/ G4 m* ]0 P8 E答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
" p& E' h: P; N
0 b# X! ?+ m/ Q9 E& }2 J
, m% ]% i n7 katomic_t># Z% h- D/ R1 F. h2 o( R/ p5 j
问:原子变量相关的函数在此驱动里,在哪来会被调用?6 ~* J8 i- j. W
答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
) z6 k* K( V9 `* G/ y3 m( ?* Z# ?- o8 ]0 s7 {- v
( d7 G; R; w, s, I" Pstatic>' S; _6 e$ J% `# Z4 s* Q
' L- U- R0 q9 `1 O' m3 I& Q( h" M8 f K+ H) K; \
原子变量互斥方式应用测试程序源码:
5 r0 a( j% J9 z1 x3 P% E3 ^' k6 F3 j6 H# B) q1 Y
+ @* R h: ]+ N+ \; Y5 N2 a#include <stdio.h>
, l8 u0 B& s2 J) I#include <sys/types.h>
0 w9 [$ V, y* f" ]#include <sys/stat.h>. Q8 {( |7 N* m4 _
#include <fcntl.h>
9 b1 B( v; m s) x$ J) U#include <unistd.h>
4 O( y! n8 [/ {#include <poll.h>! Q7 A/ I4 B P9 a
: S' i0 W* u( R9 k/*>
. D2 x* U6 _$ U# H$ o4 }8 P! f& R: U; K, s9 ?+ t0 [, l3 H
原子变量互斥方式测试步骤:
9 Y D: J! q7 @6 i9 N1 B2 ~
5 O. Q6 u* k0 @6 F6 C4 a5 z[WJ2440]#>! d7 j2 T7 ^$ y) m7 m3 y* E7 D/ Q1 X
1 v1 G% d) q; P# [' b, |2 V3 ^
$ ~) ?: c! v6 M' I信号量互斥方式应用测试程序源码:9 f+ ~, M9 Y+ k% E- T6 @+ K
#include <stdio.h>3 X, F3 G" @( n) ~+ N; k
#include <sys/types.h>$ r( Z3 S5 F" |( ]% T" Y8 t
#include <sys/stat.h>" V- q1 {6 @. V' \! M; B8 U; J; _
#include <fcntl.h>7 j8 _% Y- }. _6 b% t9 H! J2 }
#include <unistd.h> //sleep6 z3 P0 x: w- M0 l
#include <poll.h>
. H$ z+ X$ X0 B! z, a) u1 B#include <signal.h>! W$ J) K' `. n* d' }. W) x
#include <fcntl.h>
( ]1 Z8 ^# B3 A
7 I8 f" i% d/ ]/ e( m4 Q+ P2 W7 gint>
: k: e* i' d8 k
. `# w) \. p" V0 W7 g信号量互斥方式测试步骤:
5 a2 U, {* a2 e! K( r% N7 Y2 @2 M9 i) s* m) J/ ]- ^3 G
[WJ2440]# ls/ j2 h; b3 Y* f0 ]; F# e0 v' T; V
Qt fifth_drv.ko lib sddisk third_test$ X9 E k' t& Q8 ?$ @6 Z0 Q
TQLedtest fifth_test linuxrc second_drv.ko tmp7 y* N1 k$ }8 E/ R% H6 K9 Q
app_test first_drv.ko mnt second_test udisk
9 h( [- x! j9 pbin first_test opt sixth_drv.ko usr- T P, z" w# V2 h: U& H7 D
dev fourth_drv.ko proc sixth_test var
2 i g) y1 e8 y: \driver_test fourth_test root sys web
7 M3 a- J" p, r1 metc home sbin third_drv.ko! [# Y% \1 e0 v2 r7 V: k$ E
[WJ2440]# insmod sixth_drv.ko
8 \; N6 g% k8 c! J[WJ2440]# lsmod ! }$ }- l: x& p7 ]
sixth_drv 3472 0 - Live 0xbf0000006 ]3 X" B5 M* Q3 s; q' x
[WJ2440]# ls /dev/buttons -l4 m# _3 I5 M7 Q% T" F
crw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons _4 }0 J# U0 a' M1 E" @- X( z
[WJ2440]# ./sixth_test &
\! u7 l6 r3 d2 M* I[WJ2440]# ./sixth_test &' V3 i! k# A# z6 a6 l
[WJ2440]# ps6 O/ w% [2 W5 o' B3 _+ K/ x
PID USER VSZ STAT COMMAND
- | Y: A5 I0 o% n4 W 1 root 2088 S init
% ~8 ?# B& _! m: s% o9 A/ F 2 root 0 SW< [kthreadd]6 \6 X- w! F, ]+ ~8 O0 o
3 root 0 SW< [ksoftirqd/0]
7 Q# c% M7 R/ }9 b- ^8 ]- i9 W0 B 4 root 0 SW< [events/0]
N9 Y3 E# B9 J O# T; s* w1 }% _8 a 5 root 0 SW< [khelper]
: N$ z# A+ V/ O3 j, V- j3 v 11 root 0 SW< [async/mgr]. d- i! j5 j4 \, g
237 root 0 SW< [kblockd/0]
2 a* Z2 f9 f; V' i 247 root 0 SW< [khubd]& {, u" U; _' J, G& Y; f1 I
254 root 0 SW< [kmmcd]
% E, r! C7 O3 m) d 278 root 0 SW [pdflush]
& m) Z; s/ q$ S' X4 Z, L' c 279 root 0 SW [pdflush]
& U$ J7 c, w% g; G5 I+ a# t. a 280 root 0 SW< [kswapd0]$ ~- C h4 ^0 t
325 root 0 SW< [aio/0]' u0 S4 v- N9 Z, v
329 root 0 SW< [nfsiod]/ X* i& ^" e4 W: R* Z
333 root 0 SW< [crypto/0]$ J8 E& V: g4 k/ c7 m- k. z
443 root 0 SW< [mtdblockd]
. [* y. Y, ~/ Y$ W8 A8 J 557 root 0 SW< [usbhid_resumer]3 K$ E G% ~/ T2 h8 x9 c
573 root 0 SW< [rpciod/0]
0 }5 s8 }3 E3 z+ s8 h0 S5 I 587 root 1508 S EmbedSky_wdg, z) q! {# D$ [1 m: |) u
589 root 2092 S -/bin/sh) ~% ~* |* f" @: s
590 root 2088 S /usr/sbin/telnetd -l /bin/login
$ U9 j( [+ q6 A 602 root 1428 S ./sixth_test8 k- t+ V: {! Q9 ?& l. f
603 root 1428 D ./sixth_test
8 _% `1 j, p4 [ 604 root 2092 R ps) Z* A- ?, }- w# J7 E
2 H5 H8 I- O+ u! K+ u由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。: t! `0 P9 U6 O0 W) R8 J
1 T5 t p& h% g; w$ |- N3 \6 V5 S$ X! H; T
2 a& Z5 d% X7 M% d7 v
) {* Q# {" O0 w- C9 v
$ q& G5 p% o# ~! r8 n5 F, A6 A
|
|