|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。! }' a V7 S& [, M$ W$ u
/ j" a6 e+ F3 t8 Q2 V4 L3 G. t8 ?1 q' Q
上一节文章:linux字符驱动之异步通知按键驱动
x! c* R( `* a7 | Q& q$ ~, P1 [
. y/ a S6 j2 [3 X- t7 [0 Y8 H+ Y2 T在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。
5 E w8 t/ c' W+ c3 e2 m. P' }2 H& [3 {8 o. B3 Y5 C
问:如何实现同一时刻只能有一个进程使用某个设备?
; }' G; Q/ j! r- k" u; K2 O$ N/ g
: z- |4 T4 E9 d# q( r答:使用linux互斥机制
, ]8 m$ A ^' ]' e% h O( z! [. Y% |( X
问:linux互斥机制有哪些?
1 h: b3 ~0 I8 d$ a( b" a, ?- b: w( Z) c& T/ n7 D5 c
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等8 T( l4 s' @+ n$ L3 Y3 J: t
8 \1 j- C8 J7 x2 L) K l0 X! f问:在这一节里,我们使用什么互斥机制?4 S2 M; [. e5 W h' Y% Y' ^% ~
0 u8 U1 O$ v* z2 P. P答:原子变量/信号量,举二个例子来示范linux的互斥机制
1 P& `- q, [# W- L2 J- W
6 Y, \( a, S S$ [3 I, G ?问:如何使用原子变量的互斥机制?1 ?" B. g1 R( \0 T0 i% X* E# p
( E8 }( M+ x$ j% W/ w- [8 k# v答:先定义一个原子变量,然后再初始化它。具体如下:( {6 I- V, f/ p! I1 R
3 A0 v+ e5 e2 E- m* V
4 z' e% n# [7 t e
/* 定义原子变量canopen并初始化为1 */
3 f' O/ l" ~8 z! tstatic># A) u# e$ ~& r8 h' r
问:与原子变量相关的函数有哪些?
& D& v/ m+ G5 ^- u& i; n答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例: |4 @6 }$ {1 | D; r, D4 H
X5 I3 c- Q1 k `. X2 l7 a0 h, r9 K6 J% {! L, _
atomic_t>
( N3 [/ [5 f0 ~7 i" v6 a) D) Z% L8 f问:原子变量相关的函数在此驱动里,在哪来会被调用?* E: M: G" q/ T2 U9 j
答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
3 r. o d# r% a, t1 I
5 w) y% W6 M( D7 N. r' ?
3 q2 D0 M0 ~0 p" Mstatic>, j) b2 u/ l# O) d+ Q0 o0 H$ W6 o
9 q$ O) M) h' Q: r4 V* B5 Q* f$ H1 G. C% t# \; H1 {' M9 `9 a4 N
原子变量互斥方式应用测试程序源码:
2 C" C; c, ~2 \
1 h+ @, j1 j! {9 s8 `2 [+ \& ^; L! @0 ]0 m, Y! q
#include <stdio.h>
( }2 q" P- [, J! j9 ^5 y0 j3 s#include <sys/types.h>0 ~) c! x" M4 |9 T( K0 a$ T; j$ O
#include <sys/stat.h>6 M# V4 _; A0 C
#include <fcntl.h>
/ ?2 Y- B( ~+ D/ P% a6 b/ ~#include <unistd.h>
) |7 E, C) j9 h6 P#include <poll.h>
5 x, }4 f6 l+ m9 A
9 v) B6 [ |. x" M/*>
' E* F0 Y% \) {5 w7 ?" L2 C6 N. r$ H
$ b/ O. G/ p# x原子变量互斥方式测试步骤:
* g, ` W6 m1 ^$ L, H$ x+ [$ i0 V$ K( v
[WJ2440]#>
) w2 h% c+ T& o$ T$ i: y5 U% f( ^! f
* Y+ Z6 u( U# C. v+ N- g, A% y4 _: w: j: Q$ ^5 R5 r
信号量互斥方式应用测试程序源码:/ O* g/ d9 a0 `( {6 z) D
#include <stdio.h>& G2 s3 ?8 ~2 l) u
#include <sys/types.h>
+ l$ L% }) f9 S3 s. g#include <sys/stat.h>
) z8 R* K1 Q9 X1 Y% ~- x! @#include <fcntl.h>) a) j* p) o- O# A) R. B0 `
#include <unistd.h> //sleep. U3 ~+ }, O0 k; J% L
#include <poll.h>
7 x9 c6 A! ^# A* L) O#include <signal.h>
* X! E8 K% C. u5 S2 J, j#include <fcntl.h># R2 S: N; y0 [: n: G4 {
3 o6 h" P- F/ E6 W# X% u- a
int>- c& s& I: g* f) B* C( }
/ [) M1 Z7 m8 f' d- U
信号量互斥方式测试步骤:
2 N+ C# z# C# r( W8 H3 n* L
/ y$ k ]0 u! |1 {/ ~5 J[WJ2440]# ls* p/ `" r6 U7 _3 N! t, o" Z! e4 M
Qt fifth_drv.ko lib sddisk third_test5 T5 R6 E! U% F) z' K' x" h
TQLedtest fifth_test linuxrc second_drv.ko tmp
( V; l& A" w+ s$ o- J8 ?app_test first_drv.ko mnt second_test udisk
6 D; @/ s+ J7 _) W$ p( Y; C g; dbin first_test opt sixth_drv.ko usr: y' g+ O4 g4 V9 h! Q
dev fourth_drv.ko proc sixth_test var- `+ J) D( V! u# n& E# E/ p
driver_test fourth_test root sys web
% y6 J4 R1 k* f! L( f J3 Fetc home sbin third_drv.ko5 [1 k2 _( d l- W" X& w- ^( W
[WJ2440]# insmod sixth_drv.ko : s% @. K" n. n& A
[WJ2440]# lsmod : r- z, c) ~% w3 e" l! M8 @" X
sixth_drv 3472 0 - Live 0xbf000000- I9 U) f0 m- V4 f. v' @& |. h
[WJ2440]# ls /dev/buttons -l
- r _# V( n( C2 Y3 m. Ccrw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons
( Y. y$ v4 v: l[WJ2440]# ./sixth_test &- o9 V; N6 ^9 o& S% C( S4 f% V
[WJ2440]# ./sixth_test &6 p2 M+ O N$ r& {
[WJ2440]# ps
1 e: I" N) ?# K( u PID USER VSZ STAT COMMAND
) @; _ t2 h2 I 1 root 2088 S init. U& x& s; S% c4 P! w
2 root 0 SW< [kthreadd]
3 l0 O. x2 f# r# V 3 root 0 SW< [ksoftirqd/0], a: ?% }7 i1 z# m' X% T
4 root 0 SW< [events/0]) n6 p+ l7 D- i% [9 ~
5 root 0 SW< [khelper]
0 m0 S, L/ M9 x, C* O3 h 11 root 0 SW< [async/mgr]5 d$ J) c. k! l- n, f) O# x
237 root 0 SW< [kblockd/0]
d7 @" R" P) d+ Q0 a+ j4 {+ F: M& E9 s 247 root 0 SW< [khubd]' T1 G9 D( x5 Q6 k/ r
254 root 0 SW< [kmmcd]
) E+ L! ~8 U G7 [0 j 278 root 0 SW [pdflush]/ K* j0 B5 Q( S& T2 o
279 root 0 SW [pdflush]0 w2 @6 s8 W) }
280 root 0 SW< [kswapd0]/ a9 _* a+ X2 j: @
325 root 0 SW< [aio/0]. M4 E: F4 [- m1 W9 U/ Q5 w8 N
329 root 0 SW< [nfsiod]
! U/ ~5 C9 g _8 ~: I0 R- v+ N 333 root 0 SW< [crypto/0]/ \' v- o$ V& j# X
443 root 0 SW< [mtdblockd]
" |# m( f4 f$ \, L: } 557 root 0 SW< [usbhid_resumer]( t0 k8 v; H0 |) B. R5 [
573 root 0 SW< [rpciod/0]- ~7 @! O/ ~8 U3 l* s
587 root 1508 S EmbedSky_wdg& B! K6 z/ F" z, g
589 root 2092 S -/bin/sh
8 k4 c, \7 v! b) Z+ v 590 root 2088 S /usr/sbin/telnetd -l /bin/login7 w" X# A1 C- I. f9 z
602 root 1428 S ./sixth_test
; i) f2 R) p) s0 W: ]. R 603 root 1428 D ./sixth_test9 f& E; j# F! t1 a
604 root 2092 R ps
2 L) R2 ^- l5 P" Y0 w$ q, h! ~: P9 Z5 m9 J( A
由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。
3 f) G# q% m/ H! F! p' Y+ C3 L; a: e8 G. b" Q3 p2 ~: }7 S
% h0 P+ q3 e& V4 L
3 O1 m, W6 F: b$ Z4 l( j1 ^
0 b0 b s4 h8 H8 P, o& f5 K6 U
# l- G9 ^' @/ V" r7 }# r2 [* Y |
|