|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
上一节里,我们将在上一节的基础上修改驱动,将其修改为有异步通知功能的按键驱动,目标是,按下按键时,驱动主动去通知应用程序。是不是感觉驱动已经比较完善了,好像已经是完美无缺了?是不是这样呢?好像不是呢,有没有这么一种情况,多个进程想同时使用驱动的设备节点?在多线的环境下,分分钟可能会发生这种情况。
5 E$ B6 i5 e; g* H( b
- J2 u7 }& h/ F8 j' n, M' k上一节文章:linux字符驱动之异步通知按键驱动) t: @- v& C" ^( r$ h% |0 N! J
5 Q8 t" b9 {: h$ {8 F; J ^( I
在这一节里,我们在上一节的基础上,实现同一时刻只能有一个进程使用同一个设备,例如:只能有一个进程,在同一时刻里使用/dev/buttons这个设备。
; a2 i/ S8 ^, Y
" } {2 @6 w- k. W# z/ S3 G. i问:如何实现同一时刻只能有一个进程使用某个设备?& D5 i* n8 d2 k2 l. l6 `9 S# V
; S% @7 v) v7 ]. R' w, ^1 @
答:使用linux互斥机制) F" U" b0 P. j& f+ f+ |
. ]0 T I1 Z- M8 f
问:linux互斥机制有哪些?7 t" i! f5 k0 Y/ K- E4 o
; N2 c" }0 R6 L
答:有很多种,如:原子变量、互斥锁、信号量、自旋锁、读写锁等等
# X( q N7 s( `2 n7 | V( x
* i" @# y2 b0 E9 _6 X! r问:在这一节里,我们使用什么互斥机制?4 H) z& Q R5 I" i d$ s
* O( l& Y8 ]! E- I2 ^0 s, d" l5 C答:原子变量/信号量,举二个例子来示范linux的互斥机制
* _6 ^0 | R$ O0 S7 i' P
' M! o: d" v$ O5 c1 L) c问:如何使用原子变量的互斥机制?* p3 X, F) ?8 |+ d
# i2 ]/ ~# m; ^: ~( g答:先定义一个原子变量,然后再初始化它。具体如下:/ l. W0 r0 _$ \ @; x6 H
' I! Z) Y. p! U) P
* |3 B; ~9 K% O$ }/* 定义原子变量canopen并初始化为1 */% C/ q; ~$ P0 ~+ U7 e
static>; ?9 t5 k; i9 f) {. H8 b1 J/ N
问:与原子变量相关的函数有哪些?
9 A/ I' D z4 U/ c b) ~答:原子操作指的是在执行过程中不会被别的代码路径所中断的操作,常用原子操作函数举例:
3 ^; B6 B1 a, _: ~4 F6 j6 c) i4 @3 h. u: m5 U* t# B
4 v9 e' |! Y n4 a I
atomic_t>$ t Q. n0 m" r# W
问:原子变量相关的函数在此驱动里,在哪来会被调用?
+ k( G# L7 Z; Y: ^答:既然是防止多个进程打开同一个设备,那自然是在open函数就调用,在close函数也会被调用,示例如下:
# \5 X: m/ V; E o& k8 R1 b4 i* o9 G( {$ T$ M o
+ l3 I' t; w4 M! p
static>
; u* K- Z, [' f3 E+ l- ]/ x t6 w8 ^+ ~
' F6 {2 \- u5 z# B+ K1 u原子变量互斥方式应用测试程序源码:$ V8 K# b+ c1 J( H) B
; E% v% e6 h" ]. V4 _
/ \0 z _* d; @& h& k#include <stdio.h>
" c2 |+ C `, Y1 {# a# O7 h#include <sys/types.h>
! H% L0 c5 q3 p( b& }& B#include <sys/stat.h>
2 V$ j0 j" d, W#include <fcntl.h>
2 I/ o7 J3 O4 X% N* O#include <unistd.h>
( B/ V3 E, A4 u* v2 T#include <poll.h>' I( S' S7 {* k7 Q& C+ B# \
6 d3 ]- T# M G- A/*>. L$ ? c( I) T- y% U' R9 c
5 Q: O3 `$ J% m3 E原子变量互斥方式测试步骤:
2 p+ S& t2 B3 b" z/ ^& K
" o- R% V3 Y3 n# e: [# ][WJ2440]#>+ q7 n6 o! `/ F" _, e' {9 T# J. k
6 b) i1 X8 |& W0 h% W: G4 v; l7 w5 \' A
信号量互斥方式应用测试程序源码:
* C+ A* J# S: K8 F#include <stdio.h>
, N3 k, L" g% Y" K p0 W7 b#include <sys/types.h>7 Z1 s1 U2 C" ^& Z$ b$ Z+ R6 v# m
#include <sys/stat.h>! o( l1 E& r/ A! ~4 U, V
#include <fcntl.h>
; J4 f" i' `! I) e" g: l#include <unistd.h> //sleep
4 ]2 `. X5 v( t7 I/ c+ G1 T; V#include <poll.h>2 O$ _4 C x J! G* I4 I W1 B6 Q
#include <signal.h>
7 r, s& D- ]: ~; R$ n# K#include <fcntl.h>" J9 R2 A7 X) F' @$ h* `
% ^% v2 B$ p1 \6 g& Pint> |7 X( P9 p: ?* y5 I
6 m0 h4 \3 N5 f0 y
信号量互斥方式测试步骤:1 V2 L5 v& v1 O7 C) Y; [, d: p; H) O
) A+ z6 D0 D: n i+ t0 {[WJ2440]# ls
9 U6 R, E: q2 MQt fifth_drv.ko lib sddisk third_test
) M) }# ~9 W# L- ~: w: pTQLedtest fifth_test linuxrc second_drv.ko tmp
8 E6 J# P0 a* D8 h/ Vapp_test first_drv.ko mnt second_test udisk, p) j' s5 w4 g+ T3 H8 O' ?/ p
bin first_test opt sixth_drv.ko usr' I! I! ]% s, z. r0 x" S6 A/ ]* A" r
dev fourth_drv.ko proc sixth_test var
5 }* w6 W7 B. W* s. K6 b5 A. ?driver_test fourth_test root sys web
9 K5 v* n2 K% r; a; Cetc home sbin third_drv.ko; N+ U9 L$ _; g% m) x3 Z/ r/ Y
[WJ2440]# insmod sixth_drv.ko
! L+ J+ o" `) l. \) v L8 F8 _1 E[WJ2440]# lsmod + Z' ?5 r8 ^0 d
sixth_drv 3472 0 - Live 0xbf000000
3 u" x9 f5 \8 m7 |4 s$ N[WJ2440]# ls /dev/buttons -l
/ r6 l9 Y( ^7 i _1 T" Zcrw-rw---- 1 root root 252, 0 Jan 2 04:47 /dev/buttons8 v& X5 y- n' K% i
[WJ2440]# ./sixth_test &9 V+ s& s4 G% c9 Y0 H
[WJ2440]# ./sixth_test &( U* \. M2 o& D( k( M* a9 I r" M
[WJ2440]# ps1 _. D8 M; k; [$ V4 \, z
PID USER VSZ STAT COMMAND
/ U+ j# q. u8 k" \. h) [ 1 root 2088 S init8 S* U0 R7 J8 {& R7 E
2 root 0 SW< [kthreadd] Q: ^5 q _$ M; n3 S
3 root 0 SW< [ksoftirqd/0]% v" p3 k& ?; C: I6 ]% O, S/ r
4 root 0 SW< [events/0]/ h" K6 z& w. J! N
5 root 0 SW< [khelper]7 r q. y+ e6 m- Y/ E
11 root 0 SW< [async/mgr]
3 o. H) c: m( G: G 237 root 0 SW< [kblockd/0]
4 w! R& c' F/ w% P# Y# M 247 root 0 SW< [khubd]
3 Q" o+ t' h" |' B; E3 T! P 254 root 0 SW< [kmmcd]
k4 j% O/ C, d, p: l 278 root 0 SW [pdflush]
D7 E$ ^3 [4 c, F( J8 b" D8 s' C 279 root 0 SW [pdflush]
- z: B. p) d, N8 N 280 root 0 SW< [kswapd0]
% V" j: v2 v' p: E( c 325 root 0 SW< [aio/0]9 c% `4 z/ Y1 U& k* R- s
329 root 0 SW< [nfsiod]
/ X1 r% _) m! W0 q! L 333 root 0 SW< [crypto/0]5 |" m" {8 @, P
443 root 0 SW< [mtdblockd]4 ?8 n3 C' J t6 K6 z" C
557 root 0 SW< [usbhid_resumer] u7 g; v/ D% Z# i0 T% B- Z% w
573 root 0 SW< [rpciod/0]4 O9 T5 y7 u5 U2 _/ ]4 Y
587 root 1508 S EmbedSky_wdg
- D( j3 X9 O; w& A! l* i 589 root 2092 S -/bin/sh; y- q* l$ ?( }0 A
590 root 2088 S /usr/sbin/telnetd -l /bin/login* k6 i5 j1 K! {4 N$ \: D) J* C
602 root 1428 S ./sixth_test7 X- e+ A5 e: l3 X, \0 C/ E
603 root 1428 D ./sixth_test+ B% d W# K1 S8 G. H; `, D
604 root 2092 R ps3 x* J7 L" d' i
2 _* U$ E, m$ G( i( ^' H7 H
由上面的测试结果可知:当多次执行./sixth_test &时,可发现进程602的状态为S即睡眠状态,而进程603的状态为D即僵死状态,只有当我们杀死602进程时,603的状态才能变为S正常状态,这也就达到了互斥的目的。
9 M0 e) N& m4 e- q+ {
3 I/ h! A1 z5 {. H5 N. |5 D: o5 |- x. ~
' B( Z2 i) X6 U$ [6 s1 f C
7 I5 R2 F$ w0 a; b! H* S x, l
5 J; I* K2 [( o$ l9 J |
|