当一个进程睡眠
,
它这样做以期望某些条件在以后会成真
.
任何睡眠的进程必须在它再次醒来时检查来确保它在等待的条件真正为真
.
最常用的函数为:
wait_event_interruptible(queue, condition)
其中 queue 是要用的等待队列头 . 注意它是 " 通过值 " 传递的 . 条件是一个被这个宏在睡眠前后所求值的任意的布尔表达式 ; 直到条件求值为真值 , 进程继续睡眠。
睡眠唤醒的函数为:
void wake_up_interruptible(wait_queue_head_t *queue);
通过视频中将到的代码可以看出,使用了 wait_event_interruptible() 后,测试程序使用 while 循环读取按键状态也不会占据 99% 的 CPU 资源了, 进程会在条件不满足时进入睡眠,知道按键按下后,由 wake_up_interruptible() 唤醒。
同步的另一种方法是使用 select 、 poll 机制。它是一种非阻塞 I/O 的应用程序常常使用的机制。 poll, select 和 epoll 本质上有相同的功能 : 每个允许一个进程来决定它是否可读或者写一个或多个文件而不阻塞。 file_operations 结构体中 poll 的原型为:
unsigned int (*poll) (struct file *filp, poll_table *wait); 函数主要的作用就是为用户空间的 poll 、 select 提供一个系统调用。最后返回一个 mask 。
视频中 poll 的代码很简单,主要使用了 poll_wait () 函数。
void poll_wait (struct file *, wait_queue_head_t *, poll_table *);
用户空间在调用 poll 前设置了 struct pollfd fds[1]; 通过对 fd 和 events 参数的指定,使得在 fd 发生了 events 指定的条件后唤醒。最后判断 ev_press 是否按下,并返回位掩码。应用程序通过返回值是否为 0 判断是否需要读取按键状态。
视频还讲了一种异步的方法读取按键值。 file_operations 结构体中 fasync 原型为:
int(*fasync) (int fd, struct file *filp, int on)
驱动程序需要在该函数中通过 fasync_helper() 实现。 fasync_helper 被调用来从相关的进程列表中添加或去除入口项 , 当 FASYNC 标志因一个打开文件而改变。它的所有参数除了最后一个 , 都被提供给 fasync 方 法并且被直接传递。当数据到达时 kill_fasync 被用来通知相关的进程。它的 参数是被传递的信号 ( 常常是 SIGIO) 和 band, 这几乎都是 POLL_IN 。
中断触发后通过 kill_fasync() 来唤醒进程。应用程序中 signal 设置信号, fcntl 设置 FASYNC 标志位。
wait_event_interruptible(queue, condition)
其中 queue 是要用的等待队列头 . 注意它是 " 通过值 " 传递的 . 条件是一个被这个宏在睡眠前后所求值的任意的布尔表达式 ; 直到条件求值为真值 , 进程继续睡眠。
睡眠唤醒的函数为:
void wake_up_interruptible(wait_queue_head_t *queue);
通过视频中将到的代码可以看出,使用了 wait_event_interruptible() 后,测试程序使用 while 循环读取按键状态也不会占据 99% 的 CPU 资源了, 进程会在条件不满足时进入睡眠,知道按键按下后,由 wake_up_interruptible() 唤醒。
同步的另一种方法是使用 select 、 poll 机制。它是一种非阻塞 I/O 的应用程序常常使用的机制。 poll, select 和 epoll 本质上有相同的功能 : 每个允许一个进程来决定它是否可读或者写一个或多个文件而不阻塞。 file_operations 结构体中 poll 的原型为:
unsigned int (*poll) (struct file *filp, poll_table *wait); 函数主要的作用就是为用户空间的 poll 、 select 提供一个系统调用。最后返回一个 mask 。
视频中 poll 的代码很简单,主要使用了 poll_wait () 函数。
void poll_wait (struct file *, wait_queue_head_t *, poll_table *);
用户空间在调用 poll 前设置了 struct pollfd fds[1]; 通过对 fd 和 events 参数的指定,使得在 fd 发生了 events 指定的条件后唤醒。最后判断 ev_press 是否按下,并返回位掩码。应用程序通过返回值是否为 0 判断是否需要读取按键状态。
视频还讲了一种异步的方法读取按键值。 file_operations 结构体中 fasync 原型为:
int(*fasync) (int fd, struct file *filp, int on)
驱动程序需要在该函数中通过 fasync_helper() 实现。 fasync_helper 被调用来从相关的进程列表中添加或去除入口项 , 当 FASYNC 标志因一个打开文件而改变。它的所有参数除了最后一个 , 都被提供给 fasync 方 法并且被直接传递。当数据到达时 kill_fasync 被用来通知相关的进程。它的 参数是被传递的信号 ( 常常是 SIGIO) 和 band, 这几乎都是 POLL_IN 。
中断触发后通过 kill_fasync() 来唤醒进程。应用程序中 signal 设置信号, fcntl 设置 FASYNC 标志位。