a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 70|回复: 0

[综合辅导] Linux认证:Linux设备驱动中非阻塞操作

[复制链接]
发表于 2012-8-4 12:07:07 | 显示全部楼层 |阅读模式
Linux认证:Linux设备驱动中非阻塞操作- v/ b3 D' |# F# m# Q* t
「阻塞与非阻塞定义」- B; o# q3 v, f
阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。被挂起的进程进入sleep 状态,被从调度器的运行队列移走,直到等待的条件被满足。
4 u/ p. k0 v. ~非阻塞操作的进程在不能进行设备操作时,并不挂起。6 h$ o0 i2 ~6 k& \1 }# n) i/ f
「阻塞实例」
$ y4 L; @) J6 N, k多个进程对驱动中的全局变量,有的读有的写,用阻塞机制来保证只有在某个进程写过之后,其他进程在能够读这个变量。
5 P: I% D; s" W( k' H# {#include 《linux/module.h》 #include 《linux/init.h》 #include 《linux/fs.h》 #include 《asm/uaccess.h》 #include 《linux/wait.h》 #include 《asm/semaphore.h》- \$ q" C9 T, y/ N" S
MODULE_LICENSE(“GPL”);
# o( x6 [! w) ]  ]" f#define MAJOR_NUM 254
3 m$ T3 h7 J$ D1 hstatic ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);
3 r  M4 o" ^& f, \# Q: kstruct file_operations globalvar_fops = { read: globalvar_read,write: globalvar_write,};. m5 g4 C6 U. K& j$ N1 t& ^
static int global_var = 0;static struct semaphore sem;static wait_queue_head_t outq;//定义等待队列头static int flag = 0;//阻塞条件static int __init globalvar_init(void), E* X7 A$ J5 |8 `6 Q: l1 G
{ int ret;ret = register_chrdev(MAJOR_NUM, “globalvar”, &globalvar_fops);if (ret)
6 o2 w) l6 }0 a{ printk(“globalvar register failure”);} else { printk(“globalvar register success”);init_MUTEX(&sem);init_waitqueue_head(&outq);} return ret;} static void __exit globalvar_exit(void)
% ~# ]" R) u' |6 [5 M{ int ret;ret = unregister_chrdev(MAJOR_NUM, “globalvar”);if (ret)+ U) M1 a  }5 x
{ printk(“globalvar unregister failure”);} else { printk(“globalvar unregister success”);}/ p) m7 F9 L5 \% |
static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
2 T8 _# b$ m7 o! i{ //等待数据可获得if (wait_event_interruptible(outq, flag != 0))//在这里让调用自己的进程进入挂起状态,直到满/ //足后面的条件才脱离挂起状态{ return - ERESTARTSYS;} if (down_interruptible(&sem))/ K7 y+ @* z; D
{ return - ERESTARTSYS;} flag = 0; //阻塞条件在这里发生改变,意味着每次只能对这个变量读一次,除非再次给这个//变量赋了新值。+ B% A* i2 Q8 q7 L
! H4 z8 P$ q2 Y' ?$ N
, }- G3 z0 j+ u$ O, S( K
if (copy_to_user(buf, &global_var, sizeof(int)))
, X. c" S+ o) T5 l3 f% K" Z{ up(&sem);return - EFAULT;} up(&sem);return sizeof(int);}  R' ]( o! ?+ s$ _
static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len,loff_t *off)
3 N4 L9 s. w' S% d2 C2 `{ if (down_interruptible(&sem))
  {; L9 Q6 I4 L& C. O{ return - ERESTARTSYS;} if (copy_from_user(&global_var, buf, sizeof(int)))) U$ O( U, m, j" z2 s- |! S8 |
{ up(&sem);return - EFAULT;} up(&sem);flag = 1;//阻塞条件在这里发生改变,意味着可以挂起的进程可以解禁了/*通知数据可获得前面调用驱动read函数的进程被调整到了挂起状态,只有当满足一个条件的时候才会从挂起状态摆脱。这个地方注意了,并没有一个机制自动的检测条件,或者条件改变的时候,自动通知内核改变进程的状态。而是,我们需要调用函数去手动唤醒等待队列,队列会检测条件,如果条件满足,那么解禁进程,如果条件不满足,进程依然被封印。
8 R  L! c1 I/ C$ L7 U/ g*/ wake_up_interruptible(&outq);return sizeof(int);} module_init(globalvar_init);module_exit(globalvar_exit);
* z+ S0 `; d$ k' B+ y% L这里有一个问题,等待队列应该可能会有多个被封印的进程,在这种情况下:1. 后面的进程能否被前面的进程更早的解禁?! _5 Y+ u% ?+ g2 b
2. 每次通过函数试图唤醒队列的时候,队列对条件的检测机制是怎样的?是否一个一个的进程顺序的检测各自的条件吗?
  V. a% N0 B% e9 ~" K用来对本驱动进行测试的参考应用程序为:「读程序」+ I6 k8 X$ S3 {, v5 n( o
#include 《sys/types.h》 #include 《sys/stat.h》 #include 《stdio.h》 #include 《fcntl.h》 main()
  k6 A4 y+ U4 [{ int fd, num;fd = open(“/dev/globalvar”, O_RDWR, S_IRUSR | S_IWUSR);if (fd != - 1)% I3 i* I, c' _7 a! m+ }
{ while (1)' }3 S+ M1 s7 \* q6 d
{ read(fd, &num, sizeof(int)); //程序将阻塞在此语句,除非有针对globalvar 的输入printf(“The globalvar is %d\n”, num);//如果输入是0,则退出if (num == 0)
: Z( h4 Q" w. i+ E. g; Z, x{ close(fd);break;} else { printf(“device open failure\n”);}
; u9 u3 ~0 w2 q  B「写程序」
5 r$ J: B( c8 D/ P$ m0 K#include 《sys/types.h》 #include 《sys/stat.h》 #include 《stdio.h》 #include 《fcntl.h》 main()% r. r3 w  m; Y. D: B
{ int fd, num;fd = open(“/dev/globalvar”, O_RDWR, S_IRUSR | S_IWUSR);if (fd != - 1)
' s2 z8 X/ o/ T& |0 U, i3 D{ while (1)
& n2 d- W8 n, f8 h{ printf(“Please input the globalvar:\n”);scanf(“%d”, &num);write(fd, &num, sizeof(int));//如果输入0,退出if (num == 0)0 F1 S4 u  \3 z- X, O( e- ~9 \, w
{ close(fd);break;} else { printf(“device open failure\n”);}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-21 06:26 , Processed in 0.215971 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表