|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。$ n$ I" @$ V" F( ], t' I
& F- U1 ]0 h% Y- [9 D5 Q& L" q- u上一节文章:linux字符驱动之异步通知按键驱动
7 y+ } q4 Y) I. X. G- J0 I: S6 R# M
( `: a' U3 ?; T2 E! j! ~8 d! I在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。% p/ S7 c. j5 T4 T
6 r1 L3 O& [2 @
问:如何实现同一时刻只能有一个进程使用某个设备?5 H! R# [! ?! V, L' g
]/ {5 L, P! ^1 {答:使用linux互斥机制5 L" r: L- F9 i0 K: ~
- \) k$ z/ n/ i3 C5 W问:linux互斥机制有哪些?5 b/ J# t) J0 f$ N, _
) ] }% m8 G( F& f3 e
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等
& C1 G2 [6 z! R. j
% S3 R; [6 I* q+ \7 t问:在这一节里,我们使用什么互斥机制?
5 R3 x: e) d+ E0 S" G1 \7 y8 J, R9 A% m4 ]1 P9 V) ]
答:原子变量/信号量,举二个例子来示范linux的互斥机制! ?1 C& I+ ?% r5 d7 T: h
0 O% J2 w( \: o+ Q7 @, P' W- M问:如何使用原子变量的互斥机制?1 ]3 M0 L* s, z! u$ I
. ?$ \/ }5 u( A8 p5 k7 K# y* \
答:先定义一个原子变量,然后再初始化它。具体如下:
( v" ?" t) Z8 t+ E0 [
! _4 U! N; f/ [' u2 M
: ?7 `: g" W5 m2 @/* 定义原子变量canopen并初始化为1 */
" {! \% C% d. Y! D8 N9 Tstatic>& Y) @+ C& Q' p
问:与原子变量相关的函数有哪些?
# d' J) e7 H1 L j答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
: J8 w8 T* A0 i9 C+ P& d5 I
+ M. {: E; O, v3 O, p; E" y" A: [6 d) k4 s' f+ j0 M! p+ n3 ]' T
atomic_t>
4 b$ e# x2 p2 v7 T问:原子变量相关的函数在此驱动里,在哪来会被调用?' j6 d: w& v8 r K: N
答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
/ j" j5 J5 m$ X, a" W5 Q& {* k
r1 ~6 V$ s9 ^5 S& _
4 T+ z; r" X- g, W! Y* Z3 Astatic>
* z/ A- l' o% B6 d# J) t0 o1 C8 T* M, f
6 S. `) Z6 g5 k2 U' W6 @3 |原子变量互斥方式应用测试程序源码:
, r Y& o; _. G8 T
* i" X' s$ y( ^2 n
. M5 [: @, l- S4 U8 v#include <stdio.h>
; l- `% g+ L' g#include <sys/types.h>* h; b* P% V7 f' z9 h
#include <sys/stat.h>, k" \2 }% V8 v% N. `
#include <fcntl.h>1 t9 ^8 w% |6 l" `( s" a5 p( O
#include <unistd.h>
. K' T2 u+ d0 J9 V" r0 V#include <poll.h>
: F& w9 a; o3 E* ?. [
5 D* a4 N( l+ j5 t/*>7 ?* y; C$ u6 y- L3 p( c
. V( ^" M5 o0 A2 w& b- d' h
原子变量互斥方式测试步骤:
- S; ~) h$ X y
7 N0 y) k9 j* G& E0 H; X[WJ2440]#>
, v% u5 U, u& s4 p6 ^- t9 Z g3 l- }1 q; C/ Q$ Z( L$ H
/ w; S* `; `9 O( P1 G0 ?7 i' U6 T$ M
信号量互斥方式应用测试程序源码:
6 H$ J. U. o$ j6 }* s$ s#include <stdio.h>9 C& e n2 E l5 K2 q+ v6 A+ @- |
#include <sys/types.h>
# L9 A2 H e1 B* Y, W#include <sys/stat.h>
. x3 W5 A' U8 J6 D#include <fcntl.h>
2 A2 d' ?. [" ?* H! o#include <unistd.h> //sleep
; u, L2 `2 ?6 A% a7 P7 F' d#include <poll.h># x/ Y3 ~& R* `) X% A8 m2 W9 l
#include <signal.h> `2 ^8 X" \+ G
#include <fcntl.h>
, m# i! p( g3 }1 w, ?% M, ^* C- s( m& N' S L
int>
2 @& v, r& E. d# ^. X2 G* g2 b. a4 d4 p# P- u
信号量互斥方式测试步骤:
- L' ?( T! B* G: C+ a- ?* F o+ E# x. ^
[WJ2440]# ls9 F) |- y5 ~& L6 h6 w3 L
Qt fifth_drv.ko lib sddisk third_test
( a8 H7 v8 H7 a/ x' {5 ]1 E9 v% \% ZTQLedtest fifth_test linuxrc second_drv.ko tmp" g G: Y1 T; I# [6 Q7 {! s0 [
app_test first_drv.ko mnt second_test udisk; H! u1 }& G" m W! B% }# `
bin first_test opt sixth_drv.ko usr5 _# p. b' a$ B8 @. P
dev fourth_drv.ko proc sixth_test var
. m& m2 j0 B8 V& d! gdriver_test fourth_test root sys web
* n: f* m6 Z8 h0 ~, Z+ X' Z- Yetc home sbin third_drv.ko* W& v/ A* W5 R* x0 Z3 U, k4 K
[WJ2440]# insmod sixth_drv.ko 1 d! {+ W$ e" q( b
[WJ2440]# lsmod : f( z/ l! H" u. ]$ t$ f
sixth_drv 3472 0 - Live 0xbf000000
9 C2 @0 W' O: K% l5 ~[WJ2440]# ls /dev/buttons -l/ k9 C d/ x+ x9 X! ^& c% L, E8 }
crw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons
( f0 y$ x, f5 r4 \2 A+ s[WJ2440]# ./sixth_test &' B) }+ v9 q* p* R
[WJ2440]# ./sixth_test &; O. D% c' a- B( R4 r8 P. f
[WJ2440]# ps; s& F7 t- S3 w
PID USER VSZ STAT COMMAND
; y* N" u" P" ]0 ~% X9 i. ]6 w 1 root 2088 S init
* f0 W! m2 p3 {) M 2 root 0 SW< [kthreadd]# u+ d* `) A3 t3 ]2 X2 I Z
3 root 0 SW< [ksoftirqd/0]# J8 t+ ~! W- f- M. g
4 root 0 SW< [events/0]( W. Q& R0 \* s7 w( |
5 root 0 SW< [khelper]5 v. d- s2 T8 u0 d& m
11 root 0 SW< [async/mgr]
( i1 |4 u( }2 L) R: S 237 root 0 SW< [kblockd/0]
0 Q9 I: L. S; G) ~ 247 root 0 SW< [khubd]! w. _# F! _; J7 I0 V9 f
254 root 0 SW< [kmmcd], o& g- o8 @' p. ~3 J
278 root 0 SW [pdflush]
6 B4 u& y- x1 h 279 root 0 SW [pdflush]
) H P% n# _+ s, @* x* ?$ @* s 280 root 0 SW< [kswapd0]) I0 Z# D5 N# _8 b& S
325 root 0 SW< [aio/0]
. y8 z5 {, t( N G 329 root 0 SW< [nfsiod]
- p3 U8 |4 J1 n( r 333 root 0 SW< [crypto/0]; c4 ^2 m$ P9 \6 Y& Q5 \
443 root 0 SW< [mtdblockd]! U* v, N& [! ^' w* C
557 root 0 SW< [usbhid_resumer]8 l1 p0 a& o* x- m
573 root 0 SW< [rpciod/0]" D. U; {, j2 h: w3 `+ j6 Q
587 root 1508 S EmbedSky_wdg" F7 y" ^3 I s" q7 _6 b6 ]
589 root 2092 S -/bin/sh; E" h: z X! g% Y) @ F
590 root 2088 S /usr/sbin/telnetd -l /bin/login6 y. ~, k1 _" E; V, t
602 root 1428 S ./sixth_test
% Z. \; ?: m" H* I) ~ 603 root 1428 D ./sixth_test$ c5 X- g9 Z) ~; o: p: X
604 root 2092 R ps
/ m Y# W$ x0 f0 ^1 F+ w0 j7 f/ L% x/ I
由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。0 G. H( O( U0 o9 @$ d& d
! q, m) e# d" B( C8 O5 O$ L" }* h0 D
9 t5 o Z7 i5 O# O$ |) W5 e
6 n- l; b8 i7 \ R/ l( d/ s7 w6 \$ s
|
|