Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301084
  • 博文数量: 76
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 715
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-20 20:38
文章分类
文章存档

2016年(20)

2015年(56)

分类: 嵌入式

2015-06-01 19:04:03


字符驱动中阻塞与非阻塞方式

15年5月6日09:42:42

阻塞操作:是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作。被挂起的进程进入休眠状态,直到等待的条件被满足。


非阻塞操作:设备在不能进行设备操作时并不挂起,它或者放弃,或者不停地查询,直至可以进行操作为止。


简单来说,阻塞操作就是如果想去读一个按键值,当前没有按键按下的话,就一直等待,直到有按键按下才返回。而非阻塞操作就是 当前没有按键按下的话,就返回,返回一个错误或其他。


怎么分辨是阻塞还是非阻塞:

在应用程序的open函数的标记位中,传入一个参数,如果传入O_NONBLOCK的话,就是非阻塞操作,如果不传入这个参数,默认就是阻塞操作。

fd = open( “...”, O_RDWR | O_NONBLOCK);

同样,我们的驱动程序中需要对这个标记位进行处理,才能实现阻塞与非阻塞操作。这个标记位在file结构体中的 f_flags中,所以判断一个open函数中是否传入了 O_NONBLOCK参数,使用 if (file->f_flags & O_NONBLOCK) 这个语句。


代码如下(其他代码同为sixth_drv.c):

69 static int sixth_drv_open(struct inode *inode, struct file *file)

70 {

71 #if 0

72 if (!atomic_dec_and_test(&canopen))

73 {

74 atomic_inc(&canopen);

75 return -EBUSY;

76 }

77 #endif

78

79 if (file->f_flags & O_NONBLOCK) //判断是不是非阻塞操作

80 {

81 if (down_trylock(&button_lock)) /*非阻塞操作,立即判断能不能获得*/

/*button_lock这个信号量,如果不能获得,就返回。这时候需要使用 down_trylock*/

82 return -EBUSY;

83 }

84 else //阻塞操作

85 {

86 down(&button_lock);

87 }

88 request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]);

89 request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "S3", &pins_desc[1]);

90 request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S4", &pins_desc[2]);

91 request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", &pins_desc[3]);

92 return 0;

93 }

94

94

95 ssize_t sixth_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos){

96

97 if(size != 1)

98 return -EINVAL;

99

100 if (file->f_flags & O_NONBLOCK)

101 {

102 if (!ev_press) //如果为非阻塞的话,立即判断有没有按键按下。

103 return -EAGAIN; //如果没有按键按下的话,立即返回-EAGAIN

104 }

105 else

106 {

107 wait_event_interruptible(button_waitq, ev_press);

108 }

109 copy_to_user(buf, &key_val, 1);

110

111 ev_press = 0;

112

113 return 1;

114 }

115


测试程序(非阻塞方式)代码:

10

11 int fd;

12

13 void my_signal_fun(int signum)

14 {

15 unsigned char key_val;

16 read(fd, &key_val, 1);

17 printf("key_val: 0x%x\n", key_val);

18 }

19

20 int main (int argc, char **argv)

21 {

22 unsigned char key_val;

23 int ret;

24 int Oflags;

25

26 //signal(SIGIO, my_signal_fun);

27

28 fd = open("/dev/buttons",O_RDWR | O_NONBLOCK); //阻塞与非阻塞的区别。

29

30 if (fd < 0)

31 {

32 printf("cannot open!\n");

33 return -1;

34 }

35 //fcntl(fd, F_SETOWN, getpid());

36 //Oflags = fcntl(fd, F_GETFL);

37 //fcntl(fd, F_SETFL, Oflags | FASYNC);

38

39 while (1)

40 {

41 ret = read(fd, &key_val, 1);

42 printf("key_val: 0x%x\n, ret = %d\n", key_val, ret);

43 sleep(5);

44 }

45 return 0;

46 }


先测试阻塞方式:

刚开始的时候,没有注释掉sleep这一行,就出现了下图所示的结果:

阅读(1143) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~