|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。0 v1 t/ Q; |$ a" a# R$ S- I
, i# n7 m! S& L" o7 V- J+ F% T' l上一节文章:linux字符驱动之异步通知按键驱动4 v- Q6 X/ f6 s: R
: u( ?# b6 T* j( }, ?+ O, f; _在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。- p- ^4 D7 L0 k( Y
6 e- ^! T2 C2 s- O4 T. x
问:如何实现同一时刻只能有一个进程使用某个设备?) F/ W/ `# C1 J5 t9 Y1 \2 n$ e( `
! D; O. }' X7 }/ f( R% ^7 m
答:使用linux互斥机制- M5 X8 ~$ \) U, K6 I
" ^( o9 Y: l$ H: K7 e& k问:linux互斥机制有哪些?
. n W( z8 f! C2 q. G& c% G6 E4 c, K& N5 T2 C/ e/ f
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等
/ u! ?) C/ Y& l/ |; V* \3 i* n
5 Y; S1 w+ V: Q! x' |9 r- @5 I; w问:在这一节里,我们使用什么互斥机制?& D% C7 V1 T$ v. x7 {$ p
* q0 v2 r6 u3 B6 i; i5 @7 R答:原子变量/信号量,举二个例子来示范linux的互斥机制
% r0 z& w" V% T" @& v7 Z i9 ~* h1 x
问:如何使用原子变量的互斥机制?% o& y! M) U" _+ X6 h
- [5 q9 m6 k' |
答:先定义一个原子变量,然后再初始化它。具体如下:; d9 A1 H1 e) y2 k
3 U T7 j \8 @* ?. x/ D1 R4 x, B ], U1 B2 }; @3 w$ r- |& o- I
/* 定义原子变量canopen并初始化为1 *// c! J* L1 r) W% ^4 u
static># b" K0 }/ ^' @! u' K+ a- v
问:与原子变量相关的函数有哪些?
" H+ m6 O7 r2 O答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:, p- I# \6 a- F
( Q$ p4 p* u" [# z4 V: q% V
) O9 ^2 O) o& W8 m5 ~/ g5 u& z! a
atomic_t>
8 f8 y2 i' p/ z. A问:原子变量相关的函数在此驱动里,在哪来会被调用?
) ?: g$ L, g4 s: r7 D. _答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
( O1 u& l" v: \8 I; q
( m! y" H x# B) d7 M' h
0 K% n1 r/ K% R9 Y/ R8 C ustatic>
' _- q$ p& B$ S
8 M7 J$ `6 n. a! ]- |) m2 Z) e0 Q' V5 K' T
原子变量互斥方式应用测试程序源码:
/ s6 i1 s9 k# g/ n! b0 \) f2 R& S1 W4 \9 s
- d+ N! |6 E/ e7 _ p3 u6 d
#include <stdio.h># |/ k9 r0 C: w; r- }6 \ z* E
#include <sys/types.h>
% v5 R1 M( O H5 M% f#include <sys/stat.h>8 k0 t: H8 I8 D2 i' Z- [0 A: g- x1 @
#include <fcntl.h>
; ~9 B6 N; d6 B#include <unistd.h>
/ [* M5 S* Q, H4 Z" ~* s#include <poll.h>
$ Y- I+ F4 L a V1 w! V$ @
! v* F+ m$ W; H/ a7 j& w/*>6 \* k# ^; {) ^- K- `1 O
) P4 J7 @& r9 F
原子变量互斥方式测试步骤:
4 v# ?- V0 a% X" ^9 y5 q4 i" t. D9 a. {* `# \+ v g
[WJ2440]#>
, d! f: [3 r! l, h/ x
* }: T; k( c; t b0 h% {" \' r# H* F" b l: Y
信号量互斥方式应用测试程序源码:* i! @: X- H# T5 G
#include <stdio.h>
, F" ^* h7 y% J* X* v#include <sys/types.h>/ {7 c, e% Q' j) P9 B N" P, J
#include <sys/stat.h>
2 G3 ^8 ]) X( j#include <fcntl.h>
. K$ ]. z/ i `7 R/ H3 S1 w#include <unistd.h> //sleep
, c" v4 v0 O% [0 l( K+ X1 x#include <poll.h>7 C5 X. `! s* s
#include <signal.h>
/ f( l* {# G8 {/ R#include <fcntl.h>
, |' w3 E8 e2 c: U8 ]' \+ ?3 v" y' q* {; z' Q
int>$ A' c% p8 o' n5 ^& i$ W
8 W" c" ?* I2 T8 U7 ~/ ^
信号量互斥方式测试步骤:" b5 q$ B5 R Y9 n% T" j
- z5 H7 P; a) H2 _[WJ2440]# ls3 }: H& X3 i; J# ?' x' d# m& [7 {& v
Qt fifth_drv.ko lib sddisk third_test
& P6 ~1 H, i" |3 w2 M, v/ JTQLedtest fifth_test linuxrc second_drv.ko tmp
0 _8 O! i; D6 O4 h7 R5 Bapp_test first_drv.ko mnt second_test udisk
3 o! K" a# X1 J1 s2 D2 ~& x2 vbin first_test opt sixth_drv.ko usr
- x9 u. j3 b" a' J' @( S- i9 Y# _2 [dev fourth_drv.ko proc sixth_test var
7 g! z U0 Y& F4 z& N E$ A4 D8 r- n: Q8 |driver_test fourth_test root sys web- E" i* }0 D6 M, @6 f
etc home sbin third_drv.ko! d6 z% U+ ?" t& z B! P% g
[WJ2440]# insmod sixth_drv.ko ; {- c w+ q1 t, k6 \ I% P1 H
[WJ2440]# lsmod 2 M0 i# s/ {( M1 {; j# T
sixth_drv 3472 0 - Live 0xbf000000
- ^" f) F( l# `1 v[WJ2440]# ls /dev/buttons -l2 U: l/ N3 e9 |+ Y
crw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons H+ q* V* o4 t" M$ P) {% g9 n
[WJ2440]# ./sixth_test &
5 w0 n2 M/ Z& f, K[WJ2440]# ./sixth_test &
, U" X, ~/ |% `& _4 o[WJ2440]# ps. Y' Q4 v8 U! K4 c
PID USER VSZ STAT COMMAND# a% d* [2 I) `4 a+ i% V1 Z% l3 h$ M! v
1 root 2088 S init1 z* c2 ~' V2 e9 r1 S" G, E
2 root 0 SW< [kthreadd]
4 L& ~8 Y# H% x0 W! j/ B* g) I 3 root 0 SW< [ksoftirqd/0]
8 o- D S% W" d" K 4 root 0 SW< [events/0]
$ S2 t) \ F' Q- ` 5 root 0 SW< [khelper]4 [# K2 I5 e d2 y2 Y: [) U4 P
11 root 0 SW< [async/mgr]7 ^* ?4 o- n- t* `
237 root 0 SW< [kblockd/0]
+ j5 U. a5 L. z" b) S 247 root 0 SW< [khubd]. _5 ]8 ^& _7 o, A
254 root 0 SW< [kmmcd]6 p" {1 q4 R3 w
278 root 0 SW [pdflush]
; V0 O6 q( J ^ V5 d 279 root 0 SW [pdflush]
# A& t& L9 R# {) g. _$ V* H 280 root 0 SW< [kswapd0]! ]' p* t! N$ F y1 I! {
325 root 0 SW< [aio/0]* L0 L1 g1 m1 b. q. V4 H
329 root 0 SW< [nfsiod]
2 b- W1 G: B/ k7 y, T9 b 333 root 0 SW< [crypto/0]8 ]2 k. f6 Q: g" M
443 root 0 SW< [mtdblockd]
) O; I* q1 ?2 J1 S 557 root 0 SW< [usbhid_resumer]3 g, P( B& F/ _
573 root 0 SW< [rpciod/0]: l6 j; u# Z/ v, M& `5 t4 n
587 root 1508 S EmbedSky_wdg
' I9 O% z( v$ L4 X1 ]5 i/ u1 A 589 root 2092 S -/bin/sh
z9 L* u. e/ D 590 root 2088 S /usr/sbin/telnetd -l /bin/login
" a6 f# \# d: o: z1 h 602 root 1428 S ./sixth_test
) W! p9 N; K5 A8 W* V6 h, ?! M 603 root 1428 D ./sixth_test* N X) J% Y! {' N2 x) U3 n
604 root 2092 R ps# C* o3 ~% \" D
) e$ I9 h5 x. ]( C由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。
1 Y- G$ z" J; R0 _; t6 ~5 P% W
6 |, j- A9 s: ^3 b% J7 N1 Z6 T2 a2 O5 z$ e; F+ v" p
0 X4 y8 [$ F& ]1 A# A% _ b, @+ Z7 b0 a; O- v @: f+ p0 p1 Q
# U' c+ \& i( ?5 s1 A |
|