Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志
2013-03-09 14:24
429 查看
阻塞:
在设计简单字符驱动程序时,要注意一个重要问题.当一个设备无法立刻满足用户的读写请求时应当如何处理?
例如:调用 read 时没有数据可读,但以后可能会有;
或者一个进程试图向设备写入数据,但是设备暂时没有准备好接收数据.
应用程序通常不关心这种问题,应用程序只是调用 read 或 write 并得到返回值.
驱动程序应当 ( 缺省地 ) 阻塞进程,使它进入睡眠,直到请求可以得到满足.
阻塞操作:
是指在执行设备操作时,若不能获得资源则挂起进程,直到满足可操作的条件后进行操作,被挂起的进程进入睡眠状态,被从调度器的运行队列移走,直到等待的条件被满足.
非阻塞操作:
进程不能进行设备操作时并不挂起,他或者放弃,或者不停的查询,直到可以进行操作为止.阻塞方式-read- 实现:
在阻塞型驱动程序中,read 实现方式如下:如果进程调用 read ,但设备 没有数据 或
数据不足,进程阻塞.
当新数据到达后,唤醒被阻塞进程.
阻塞方式-write- 实现:
在阻塞型驱动程序中,write 实现方式如下:如果进程调用了 write ,但设备 没有足够的空间供其写入数据,进程阻塞.
当设备中的数据被读走后,缓冲区中空出部分空间,则唤醒进程.
非阻塞方式的读写操作:
阻塞方式是文件读写操作的默认方式,但是应用程序员可通过使用O_NONBLOCK标志来人为
的设置读写操作为非阻塞方式 .( 该标志定义在 < linux/fcntl.h > 中,在打开文件时指定 ) .
如果设置了 O_NONBLOCK 标志,read 和 write 的行为是不同的 ,如果进程没有数据就绪时调用了 read ,
或者在缓冲区没有空间时调用了 write ,系统只是简单的返回 -EAGAIN,而不会阻塞进程.
实例 --- 读阻塞的实现:
用 while 是因为可能别的信号唤醒了睡眠,我们要通过while 重新检测是否真有数据了....
实例 --- 按键驱动阻塞实现:
1,在 open 函数 查看看是 阻塞方式 还是 非阻塞方式:
file 结构体中含有 f_flags 标志位,看是 阻塞方式 还是 非阻塞方式:O_NONBLOCK 为 非阻塞方式;
if (file->f_flags & O_NONBLOCK) /* 非 阻塞操作 */ { if (down_trylock(&button_lock)) /* 无法获取信号量,down_trylock 立马返回 一个 非零值 */ return -EBUSY; } else /* 阻塞操作 */ { /* 获取信号量 */ down(&button_lock); /* 获取不到 睡眠 */ }
2,在 read 函数中同样查看:
if (file->f_flags & O_NONBLOCK) /* 非 阻塞操作 */ { if (!ev_press) /* ev_press 为 1 表示有按键按下,为 0 if 成立 ,没有按键按下, */ return -EAGAIN; /* 返回 -EAGAIN 让再次来执行 */ } else /* 阻塞操作 */ { /* 如果没有按键动作, 休眠 */ wait_event_interruptible(button_waitq, ev_press); }
3,应用程序中:
1,以阻塞方式运行:
后台执行应用程序,进程处于睡眠状态,按下按键,立马打印按键号;int main(int argc, char **argv) { unsigned char key_val; int Oflags; fd = open("/dev/buttons", O_RDWR ); if (fd < 0) { printf("can't open!\n"); return -1; } while (1) { read(fd, &key_val, 1); printf("key_val: 0x%x\n", key_val); } return 0; }
2,以非阻塞方式运行:
open 驱动程序的时候,传入标志 O_NONBLOCK 非阻塞;后台执行应用程序:
int main(int argc, char **argv) { unsigned char key_val; int ret; int Oflags; fd = open("/dev/buttons", O_RDWR | O_NONBLOCK); if (fd < 0) { printf("can't open!\n"); return -1; } while (1) { ret = read(fd, &key_val, 1); printf("key_val: 0x%x, ret = %d\n", key_val, ret); sleep(5); } return 0; }
非阻塞方式,没有按键值按下,程序立马返回;
read 返回值 为 -1;
相关文章推荐
- Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志【转】
- linux字符设备驱动-同步互斥阻塞笔记
- Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]
- Linux驱动编程 step-by-step (八) 阻塞型字符设备驱动
- Linux设备驱动程式学习(5)-高级字符驱动程式操作[(2)阻塞型I/O和休眠]
- Linux字符设备驱动之同步互斥阻塞
- Linux设备驱动程序学习笔记 高级字符驱动学习--阻塞型I/0
- linux高级字符设备驱动之 三 阻塞型字符设备驱动
- linux驱动开发-阻塞的字符设备
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-按键驱动程序之异步通知机制+原子操作+互斥信号量+阻塞与非阻塞+定时器去抖
- Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]【转】
- [Linux驱动]字符设备驱动学习笔记(二)———实例
- linux字符设备驱动之LED
- linux 高级字符设备驱动 ioctl操作介绍 例程分析实现
- Linux字符设备驱动之概述篇
- linux驱动---字符设备的注册register_chrdev说起
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- linux驱动开发--字符设备:静态分配设备号
- Linux字符设备驱动框架
- linux驱动开发--字符设备:简单的file_operations示例