|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。( g! _8 ?; a4 Q8 I f7 Z
4 P7 Q* ~& g( o2 M上一节文章:linux字符驱动之异步通知按键驱动
. p* A$ y" l: @# P
$ `* Q _& I$ k+ p3 u/ J在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。& P8 m$ u( H7 _. ^! N% m0 x, s
% n8 ?! M! j$ F. _: }/ Z& K
问:如何实现同一时刻只能有一个进程使用某个设备?: H) }! y7 T# }0 ^
7 c6 I' Q# `* z/ Q答:使用linux互斥机制
v9 Y6 r' T5 g2 J: ^ C- o# F3 S
9 X5 k* W! {, C. _! P* T7 U' U* y8 K问:linux互斥机制有哪些?
6 f% X( s! H* c9 y+ D0 I( {: d% r3 X9 s3 d
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等' A- Y0 q% r2 B: F
- a( y( Y2 b; c4 G% {7 F$ U问:在这一节里,我们使用什么互斥机制?4 i5 [3 ^- x( l! R% `
) R/ @1 k2 K. v) T. c答:原子变量/信号量,举二个例子来示范linux的互斥机制
9 ]( S# F( B9 W# o- E6 `4 H2 r$ z9 v- f( ]
问:如何使用原子变量的互斥机制?+ ], A) A1 h* R7 o$ M) g
4 O% \" i$ y# q% _) G4 L7 g% O* _& }* ]% `答:先定义一个原子变量,然后再初始化它。具体如下:& \/ L' ^& d7 E: ^+ Z7 K
- I; J1 a$ o0 L6 p; B6 z
! Q% ~, f9 }; v! Y
/* 定义原子变量canopen并初始化为1 */, }8 [: m* e7 W$ N: j/ `# M
static>( H- V7 k) ^2 T/ D5 d$ w8 H5 `
问:与原子变量相关的函数有哪些?# J2 v8 W: C) T& K' U
答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
' j+ B* a* H/ W! e! l1 X
+ ^, V. p4 ]9 D2 e4 l6 L8 _5 N$ f- H& g) F, E1 N2 q7 s) W
atomic_t>/ u, W) r* i5 |7 ^+ W K" i( A ~; z
问:原子变量相关的函数在此驱动里,在哪来会被调用?
8 m* X) Q }, U/ a答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:' m) n/ _; n6 @8 Y) X+ D
0 o9 W9 i: ?" v5 C M% J0 ^
' e6 I* d6 `3 z- n* e2 F3 C& l/ Rstatic>$ ?; @. e$ c! x6 I$ G- g
/ ^) V8 u7 f, r$ w' D
3 c$ {% T e; ^/ o
原子变量互斥方式应用测试程序源码:
' `" `9 W0 f& ~0 t& Q# |+ C# j/ H8 g# B. h6 T
/ A+ p! W1 C$ U( v' H0 _! d( ^#include <stdio.h>! u7 P' m- ]$ |# r8 R" e
#include <sys/types.h>
8 F2 W& {" \2 S( B v#include <sys/stat.h>* ]" ?: Q" g0 R. b/ D3 y
#include <fcntl.h>
9 R8 Z: u3 b7 e#include <unistd.h>
, a$ ]; [ B% j; W& e4 e+ L9 n#include <poll.h>! h$ ~8 G. [( R7 G2 N/ b
* k2 u* b3 H' R0 `* G: z+ t/*>
4 u( y0 p2 |! P; u) J8 \& I4 ]
% d; p; I1 f, }) X( r/ P% m$ |原子变量互斥方式测试步骤:, W8 a, U) Y6 W7 J$ _
& d7 |8 v& O1 Q& |6 i
[WJ2440]#>' s, T% H5 f$ i \) A' H0 p8 ^
5 u$ i" ~4 E9 \' k+ @) ]* S4 |6 F5 k0 V: q5 Q
信号量互斥方式应用测试程序源码:* y n8 |1 a$ V; |7 }
#include <stdio.h>
2 t) P! J7 T: F' D#include <sys/types.h>& d' z3 ?- A( C6 g- n
#include <sys/stat.h>$ n+ Y5 B& C/ W2 b; u# Y# s
#include <fcntl.h>. w/ }' u- k% g
#include <unistd.h> //sleep* l% U9 O' m( f k( I( o
#include <poll.h>1 g1 O2 O* E+ h7 a+ k
#include <signal.h>
# T! N# J3 m" Q! B#include <fcntl.h>) g# q1 _0 e- p! X/ P$ N
+ X) H6 I! O- O- t( I1 g! v; O
int>
. H" O( h' u' K' a0 u' p7 T3 _, w9 ~! d3 v! L
信号量互斥方式测试步骤:0 `, O& b$ P; d; U
. L, @) v9 v/ U( O+ S[WJ2440]# ls5 B0 U, f- O+ }, X; U4 z! S# K* x Z
Qt fifth_drv.ko lib sddisk third_test3 d! o" S- F* E/ B
TQLedtest fifth_test linuxrc second_drv.ko tmp0 G# Y+ u1 O3 c) Z; X
app_test first_drv.ko mnt second_test udisk& U3 L) A: E h6 V- F! Y2 E
bin first_test opt sixth_drv.ko usr; z1 m; s( W0 ^) {5 t4 p0 I2 W
dev fourth_drv.ko proc sixth_test var" D% W7 ]. T8 S
driver_test fourth_test root sys web* C0 [# W. q. `( E- L
etc home sbin third_drv.ko8 |; |7 X' h9 k
[WJ2440]# insmod sixth_drv.ko
$ C0 x+ G& E5 R/ i8 h- U$ k[WJ2440]# lsmod
$ A! `! [$ `( X- f" h4 \sixth_drv 3472 0 - Live 0xbf000000 p( K: E, f1 ]( A
[WJ2440]# ls /dev/buttons -l
/ j9 d" B3 _3 a9 ^) Kcrw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons
( O: H) u; `+ Z* K; g[WJ2440]# ./sixth_test &9 S; y& s* Y8 H( _: Y% r
[WJ2440]# ./sixth_test &" v7 f+ ]6 X. T4 P' ^0 i8 z, I$ q5 J$ Q
[WJ2440]# ps. m' |2 ]; c) i! c
PID USER VSZ STAT COMMAND
1 R; b- T1 c) ^+ e% j/ M1 _ x5 E 1 root 2088 S init8 b3 J& ~1 B) ?
2 root 0 SW< [kthreadd]* W0 H. [& M8 W1 G- H/ |& J7 r, ?. r
3 root 0 SW< [ksoftirqd/0]
0 G% R+ {- @0 a4 y, A5 I 4 root 0 SW< [events/0]
% x, B* z R @. Y, [+ u 5 root 0 SW< [khelper]
0 I7 U6 o: T* f. E1 z0 l/ c: }; p' x 11 root 0 SW< [async/mgr]
+ V% b# {; \6 p' r: @ 237 root 0 SW< [kblockd/0]0 E/ v' t1 X( F
247 root 0 SW< [khubd]
& F# j" ~7 d* J/ B 254 root 0 SW< [kmmcd]
& L+ F) R/ o! G6 n: c- l 278 root 0 SW [pdflush]# g# q6 i2 B8 H. @3 R4 y
279 root 0 SW [pdflush]) _ ?8 y! {: F4 t2 c
280 root 0 SW< [kswapd0]
/ m. C& V) P D3 }9 s8 q 325 root 0 SW< [aio/0]* d- C( M9 g. a# @
329 root 0 SW< [nfsiod]& T9 _( s- `/ c" a
333 root 0 SW< [crypto/0]
0 s; H8 p {7 Z5 J# O 443 root 0 SW< [mtdblockd]: W/ g9 f8 ]; U
557 root 0 SW< [usbhid_resumer]# ^* d8 ?% C/ b" o8 Q
573 root 0 SW< [rpciod/0]
3 L5 k6 @$ e: h' Z" M, ? 587 root 1508 S EmbedSky_wdg
1 s+ }6 s8 W6 H 589 root 2092 S -/bin/sh
5 p) m/ e+ n" I8 i& z1 r1 Y 590 root 2088 S /usr/sbin/telnetd -l /bin/login
( R. y- U! a7 M6 e5 e4 `* ^ E 602 root 1428 S ./sixth_test
; u9 g9 {! n. p) i! s( u: x 603 root 1428 D ./sixth_test
- O. \; L3 ^ `3 S 604 root 2092 R ps
" M/ `# ] j% ]% Q2 {8 R ]# F3 w
由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。
* j. T. I# {$ G, j, o& B$ `& H1 Y' c9 M: L, G+ E
/ \! c! G+ ?' A' o' r
0 L1 s5 t* u. y- |0 N/ W% t
. n9 m+ o/ g' y
7 z: G" p& b }6 c) O: e |
|