韦东山嵌入式入门笔记之——应用开发基础篇(七)APP访问硬件的方式
目录
一、四种APP访问硬件的方式
① 查询方式 ② 休眠-唤醒 ③ poll 方式 ④ 异步通知
1、查询方式
APP 调用 open 函数时,传入“O_NONBLOCK”表示“非阻塞”。
APP 调用 read 函数读取数据时,如果驱动程序中有数据,那么 APP 的 read 函数会返回数据,否则也会
立刻返回错误。
2、休眠-唤醒方式
APP 调用 open 函数时,不要传入“O_NONBLOCK”。
APP 调用 read 函数读取数据时,如果驱动程序中有数据,那么 APP 的 read 函数会返回数据;否则 APP
就会在内核态休眠,当有数据时驱动程序会把 APP 唤醒,read 函数恢复执行并返回数据给 APP。
3、POLL /SELECT
POLL 机制、SELECT 机制是完全一样的,只是 APP 接口函数不一样。
简单地说,它们就是“定个闹钟”:在调用 poll、select 函数时可以传入“超时时间”。在这段时间内,
条件合适时(比如有数据可读、有空间可写)就会立刻返回,否则等到“超时时间”结束时返回错误。
用法如下:
APP 先调用 open 函数时。APP 不是直接调用 read 函数,而是先调用 poll 或 select 函数,这 2 个函数中可以传入“超时时间”。
它们的作用是:如果驱动程序中有数据,则立刻返回;否则就休眠。在休眠期间,如果有人操作了硬件,驱动程序获得数据后就会把 APP 唤醒,导致 poll 或 select 立刻返回;如果在“超时时间”内无人操作硬件,则时间到后 poll 或 select 函数也会返回。APP 可以根据函数的返回值判断返回原因:有数据?无数据超时返回?
APP 根据 poll 或 select 的返回值判断有数据之后,就调用 read 函数读取数据时,这时就会立刻获得数据。
poll/select 函数可以监测多个文件,可以监测多种事件:

在调用 poll 函数时,要指明:
① 你要监测哪一个文件:哪一个 fd
② 你想监测这个文件的哪种事件:是 POLLIN、还是 POLLOUT
最后,在 poll 函数返回时,要判断状态。
应用程序代码如下:
struct pollfd fds[1];int timeout_ms = 5000;int ret;fds[0].fd = fd;fds[0].events = POLLIN;ret = poll(fds, 1, timeout_ms);if ((ret == 1) && (fds[0].revents & POLLIN)){read(fd, &val, 4);printf("get button : 0x%x\n", val);}二、获取设备信息
通过 ioctl 获取设备信息,ioctl 的参数如下:
int ioctl(int fd, unsigned long request, ...);有些驱动程序对 request 的格式有要求,它的格式如下:

比如 dir 为_IOC_READ(即 2)时,表示 APP 要读数据;为_IOC_WRITE(即 4)时,表示 APP 要写数据。
size 表示这个 ioctl 能传输数据的最大字节数。
type、nr 的含义由具体的驱动程序决定。
比如要读取输入设备的 evbit 时,ioctl 的 request 要写为“EVIOCGBIT(0, size)”,size 的大小可以 由你决定:你想读多少字节就设置为多少。这个宏的定义如下:
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ,'E',0x20 + (ev),len) /* get event bis */