对于基础按键的驱动,有如下几种写法:
(1)查询
所谓查询方法,主要描述应用程序会在while(1)里面一直read,如果没有数据会导致阻塞,占用CPU;这种方法是最差的。
(2)中断
中断配合休眠会避免查询法占用CPU的缺点。
应用程序和查询法没有什么区别, 但是驱动里面的read函数会调用wait_event_interruptible, 直到按键产生中断并在中断里面唤醒,此时read会把数据返回给用户程序。
(3)poll
poll机制和上面中断方式差不多, 在应用程序里面基本结构是:
while(1) { ret = poll(fds, 1, 5000); if(ret == 0) { printf("time out . "); } else { read(fd, &key_vals, 1); ... } }
应用程序调用poll, 对于驱动程序里面的file_operations->poll, file_operations->poll里面首先调用poll_wait, 而poll_wait不会立即导致休眠。
驱动程序相对于中断方式来说,file_operations需要实现poll函数,如下:
static unsigned int buttons_poll (struct file *file, struct poll_table_struct *wait) { unsigned int mask = 0; poll_wait(file, &buttons_waitq, wait); // 不会立即休眠 if (press_event) mask |= POLLIN | POLLRDNORM; return mask; }
(4)异步通知
上面三种对于应用程序来说,本质上都是查询,因为都在while(1)里面实现read按键值。异步通知指驱动程序主动通知应用程序。
应用程序里面:
signal(SIGIO, my_signal_handler); void my_signal_handler(int sigid) { ... }
fcntl(fd, F_SETOWN, getpid());
Oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, Oflags | FASYNC);
对应驱动程序里面需要实现file_operation->fasync
static int buttons_fasync (int fd, struct file *filp, int on) { return fasync_helper (fd, filp, on, &buttons_async); // 注册 }
相关中断里面发送信号
kill_fasync (&buttons_async, SIGIO, POLL_IN);
(5)input子系统