- 查询方式
- 休眠-唤醒
- poll/select方式
- 异步通知
查询
不断访问查询是否 有数据
- app调用open函数时,传入"O_NONBLOCK" 表示 非阻塞
- app调用read函数读取数据时,如果驱动程序中有数据,那么app的read函数会返回数据,否则也会立刻返回错误
fd = open(argv[1], O_RDWR | O_NONBLOCK);
休眠-唤醒
一直等待驱动中返回数据
- app调用open函数时,不要传入"O_NONBLOCK"
- app调用read函数读取数据时,如果驱动程序中有数据,那么app的read函数会返回数据;否则app就会在内核态休眠,当有数据时驱动程序会把app唤醒,read函数恢复执行并返回数据给app
fd = open(argv[1], O_RDWR);
poll/select
在调用poll,select函数时可以传入 超时时间。在这段时间内,条件合适就会立刻返回,否则等到超时时返回错误
- app先调用open
- app不直接调用read函数,而是先调用poll或select函数,这2个函数中可以传入超时时间。
- app根据poll或select的返回值有判断之后,就调用read函数读取数据时,这时就会立刻获得数据
- app根据poll或select的返回值判断有数据之后,在调用read函数读取
- poll/select 函数可以监听多个文件,可以监测多种事件
在调用poll函数时,要指明:
- 要检测那个文件 那个fd
- 要检测文件的那种事件,是POLLIN、还是POLLOUT
// 导包
#include <poll.h>
// 定义pollfd 结构体
struct pollfd fds[1];
fd = open(argv[1], O_RDWR | O_NONBLOCK);
// 指定检测的文件
fds[0].fd = fd;
// 指定检测使劲啊
fds[0].events = POLLIN;
fds[0].revents = 0;
ret = poll(fds, nfds, 5000);
异步通知
所谓异步通知,就是app可以忙自己的事情,当驱动程序用数据时它会主动app发信号,这会导致app执行信号处理函数
关于发信号的 几个问题点
- 谁发信号:驱动程序来发
- 发什么:信号
- 发什么信号:SIGIO
- 怎么发:内核提供的函数
- 发给谁:app,app要把自己告诉驱动
- app收到后做什么:执行信号处理函数
- 信号处理函数和信号,之间怎么挂钩:app注册信号处理函数
// 编写信号处理函数
void my_sig_handler(int sig)
{
struct input_event event;
while (read(fd, &event, sizeof(event)) == sizeof(event))
{
printf("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value);
}
}
/* 注册信号处理函数 */
signal(SIGIO, my_sig_handler);
/* 打开驱动程序 */
fd = open(argv[1], O_RDWR | O_NONBLOCK);
/* 把APP的进程号告诉驱动程序 */
fcntl(fd, F_SETOWN, getpid());
/* 使能"异步通知" */
flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | FASYNC);