|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。
" E! ^3 K; @. [8 K! u& j ?# [8 i
, j4 d9 f5 J, n! U( I# A; i5 B上一节文章:linux字符驱动之异步通知按键驱动) r- t8 B4 M+ C. C) P! x+ Y
* j5 M0 Z2 r! v( ?" e6 ~0 i
在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。+ U# M u r. `9 }
& H4 j% G- U$ C% C% c# b. u问:如何实现同一时刻只能有一个进程使用某个设备?
; Q$ U$ B5 Q, H6 B3 }) P1 W- f5 A) V) v; l4 N/ I" [
答:使用linux互斥机制" f- h. I. [3 j# b0 O: S3 V
4 t# T' v: X4 T; O# }
问:linux互斥机制有哪些?1 r; [1 ?, C4 M8 z, R6 ~5 D
4 N* q+ s+ \0 G
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等% l1 L: M) c5 d) \1 y/ C0 B
s6 z- x+ R( o/ [7 M" [问:在这一节里,我们使用什么互斥机制?
1 v. g7 d) C, _0 X. n' E/ i/ `2 K1 z" v' m
答:原子变量/信号量,举二个例子来示范linux的互斥机制
4 ]" A! x+ o; |9 D0 }' _- R6 ~# m+ H8 \+ f7 \9 X1 V
问:如何使用原子变量的互斥机制?4 f6 R. A" H f* a2 e
' _* Y. s) D0 ]. _" P$ A7 h
答:先定义一个原子变量,然后再初始化它。具体如下:
) Q, B' D, E1 {, G9 v
' s5 {% D" N0 Y Y. r
0 d' T a1 Z0 z# ^# t' \+ k& o/* 定义原子变量canopen并初始化为1 */. E& [* b2 Q( Z' F# |+ A2 z
static>1 P. G4 I' P8 O8 U- q. ?
问:与原子变量相关的函数有哪些?
C1 a* V1 E/ o( R8 i% N答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
# k/ q* }" L# V( K) }7 m5 k, K% W9 X) o# b0 n( P" j
0 A0 Q8 _% A) V# F& L
atomic_t>
: j# y) \. u9 w7 y! U. ^问:原子变量相关的函数在此驱动里,在哪来会被调用?7 V! ]% u4 V3 [7 I
答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
& O- Q' o9 A. ]+ {, h+ f4 u5 o1 f" m* U! [ O$ z6 e( J$ v
! M$ w3 L `8 t
static>, C9 d* r+ G/ \8 g8 L8 M+ ^; `
9 w) T( m9 G b7 j, R0 z' ~ ^7 S1 H$ {
原子变量互斥方式应用测试程序源码:
6 C* f% y. x$ R) k! e' k ?2 _% {) C& W7 L5 @
/ q! b) w/ o7 s1 h$ ]8 Z. G#include <stdio.h>
9 C' w9 D" p8 B- h/ h, v#include <sys/types.h>
/ _" }% {( H2 I$ Y3 ]#include <sys/stat.h>
1 w u' |7 H- L#include <fcntl.h>
' J+ `+ f$ C( P8 Q#include <unistd.h>4 f9 s; j* E f, L
#include <poll.h>
* W- ]9 ]2 Z) a# q: H, j* h/ a
/ d' D# B9 I& p/ t6 g& S/*>
& S* f" i: x7 a) ^( X( p* j
$ m* B! n) ?: f2 p- ~2 L原子变量互斥方式测试步骤:. x' l6 J5 \1 j: Q2 P( z
% h3 d0 Z& F/ X3 S# M2 W4 {% A+ b
[WJ2440]#>9 J3 n! Z) Q, T, u: N' b0 ~9 j
( @, Y4 t. h: H9 B: ^1 F
) f3 `( C& a( u1 r' I# X信号量互斥方式应用测试程序源码:9 ^- j: j) e" M/ i
#include <stdio.h>7 s) d' e, O5 b Z6 f W
#include <sys/types.h>0 f& z+ W1 i8 P. Y+ T0 P: D
#include <sys/stat.h>4 N. a' T3 J% i% J3 c
#include <fcntl.h>! f8 \: P- V; v5 V; q
#include <unistd.h> //sleep* E7 O/ U! W6 i9 N! K
#include <poll.h>' K6 q, L) k1 p' [ Q
#include <signal.h>
5 t5 E9 ~9 c% f" o n#include <fcntl.h>6 T% @( x: `0 O$ }1 X
5 Z! ~- S w, y$ ]7 k! Bint>
/ u4 K/ X$ [: P! x9 L' b2 i1 m
/ \# p- B8 m2 F% N! K8 v1 c8 |- P信号量互斥方式测试步骤:/ }8 H7 q$ j1 H. o& ~8 @) r
/ P8 S" A2 ]; o" F" F9 @- a
[WJ2440]# ls
" j H% a% B& b) d' ?$ a! mQt fifth_drv.ko lib sddisk third_test/ T! T% v, i3 t9 Q& K4 m% E/ ^
TQLedtest fifth_test linuxrc second_drv.ko tmp+ ]* O1 E& e; k/ A7 x" o. G4 `2 p
app_test first_drv.ko mnt second_test udisk
) f1 E2 c, e8 ~/ G$ f4 j. ^6 Cbin first_test opt sixth_drv.ko usr- y8 r. U2 l4 Q
dev fourth_drv.ko proc sixth_test var
' ]% g# ` O" c, udriver_test fourth_test root sys web
0 B3 D' K- H$ d+ setc home sbin third_drv.ko( s6 a# R( y8 F4 w6 H( _% U
[WJ2440]# insmod sixth_drv.ko 0 c: ?3 u. E, @ C; R8 v. p
[WJ2440]# lsmod
8 I; o7 n. ?4 h/ {/ lsixth_drv 3472 0 - Live 0xbf000000
; W, r; t( d+ j* n( M9 z[WJ2440]# ls /dev/buttons -l: f( H5 s |6 ?+ J7 S+ \: o& `
crw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons
* O0 F: P- A/ `. h/ ?9 [1 G[WJ2440]# ./sixth_test &
1 d% \, _+ z) F- P[WJ2440]# ./sixth_test &
5 |8 w0 |! U- V3 W) t[WJ2440]# ps1 m# |2 A' l5 R
PID USER VSZ STAT COMMAND% q8 E: t8 _6 e5 M8 g6 T
1 root 2088 S init
6 c: U. d( Y" ? 2 root 0 SW< [kthreadd]
k( ?8 g: {: y2 T* [# y6 O 3 root 0 SW< [ksoftirqd/0]
: o% ?# H7 U% Y 4 root 0 SW< [events/0]8 H6 @' s- [5 X C4 S6 K
5 root 0 SW< [khelper]7 m$ P) k3 l# y5 x# Y
11 root 0 SW< [async/mgr]
7 C+ i9 I) h5 r, i+ r! ~ 237 root 0 SW< [kblockd/0]
' U9 c: A2 a2 w" G 247 root 0 SW< [khubd]
6 s# r" I7 A( X/ G" b 254 root 0 SW< [kmmcd]
t% N: d% n: J9 l& ~( d. K 278 root 0 SW [pdflush]" l7 o. k* V- s' f" P' Z I' ~
279 root 0 SW [pdflush]7 K3 c% R" M: z1 h7 j A
280 root 0 SW< [kswapd0]
/ B; H; {* l% C8 s+ c) L 325 root 0 SW< [aio/0]
0 o9 O% R9 O+ x 329 root 0 SW< [nfsiod]
2 A6 N/ U2 d- W9 w8 N 333 root 0 SW< [crypto/0]0 ^. ^+ m5 `% t
443 root 0 SW< [mtdblockd]3 o- ~) i5 L3 t" M- \
557 root 0 SW< [usbhid_resumer]
, { k- `' R5 Q+ B/ c 573 root 0 SW< [rpciod/0]
; ~( {6 d0 j2 e9 F$ @3 h 587 root 1508 S EmbedSky_wdg
) ?* `6 y n3 M9 \ 589 root 2092 S -/bin/sh
/ J/ q! R [, s6 P" @* d1 { 590 root 2088 S /usr/sbin/telnetd -l /bin/login
% L& v$ k1 d2 P 602 root 1428 S ./sixth_test
. r" C( a" L2 ]' { 603 root 1428 D ./sixth_test6 q1 H" Y' @: G; X
604 root 2092 R ps
2 _( V0 K$ i8 n& Z" r4 Q E- W: u4 Z, l8 l4 g3 c) \
由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。
- r! T3 w J8 W/ l3 x. r+ x5 f
6 _; W# U4 ^3 ~- |. u8 ^% H2 l! v5 t4 v. f+ B+ ~ H. S
4 x2 k' S7 ?" a
, N3 Z! B9 S6 ?2 w0 n: B6 c7 N9 x5 f
9 }% x0 e1 p1 b5 p5 Z4 `& s |
|