使用非阻塞的IO应用程序常调用select类函数,允许进程决定是否可以对一个或多个打开的文件进行非阻塞的读取或者写入
该功能的实现就要下面tty_poll操作来实现的。该功能的函数实现有一个关键的数据结构poll_table和一个关键的函数poll_wait
对该结构和函数这里不深入解析只知道其功能即可
/**
* tty_poll - check tty status
* @filp: file being polled
* @wait: poll wait structures to update
*
* Call the line discipline polling method to obtain the poll
* status of the device.
*
* Locking: locks called line discipline but ldisc poll method
* may be re-entered freely by other callers.
*/
//tty_poll功能的实现主要在线路规程ldisc->poll中实现即normal_poll函数
static unsigned int tty_poll(struct file *filp, poll_table *wait)
{
struct tty_struct *tty;
struct tty_ldisc *ld;
int ret = 0;
tty = (struct tty_struct *)filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
return 0;
ld = tty_ldisc_ref_wait(tty);
if (ld->ops->poll)
ret = (ld->ops->poll)(tty, filp, wait); //调用normal_poll函数
tty_ldisc_deref(ld);
return ret;
}
poll方法的实现主要完成两步操作:
1)在一个或多个指示poll状态变化的等待队列上调用poll_wait.poll_wait增加一个等待队列到poll_table结构
如果没有可执行的文件IO则内核将进程在传递到该系统调用的所有文件描述符对应的等待队列上等待。
2)返回一个用来描述操作的是否可以立即执行的位掩码
/**
* normal_poll - poll method for N_TTY
* @tty: terminal device
* @file: file accessing it
* @wait: poll table
*
* Called when the line discipline is asked to poll() for data or
* for special events. This code is not serialized with respect to
* other events save open/close.
*
* This code must be sure never to sleep through a hangup.
* Called without the kernel lock held - fine
*/
static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
poll_table *wait)
{
unsigned int mask = 0;
poll_wait(file, &tty->read_wait, wait); //增加一个等待队列到poll_table结构
poll_wait(file, &tty->write_wait, wait);
//POLLIN 设备可不阻塞地读
//POLLRDNORM 可以读"正常"数据. 一个可读的设备返回( POLLIN|POLLRDNORM ).
if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty)))
mask |= POLLIN | POLLRDNORM;
//POLLPRI 可不阻塞地读取高优先级数据(带外). 控制模式数据
if (tty->packet && tty->link->ctrl_status)
mask |= POLLPRI | POLLIN | POLLRDNORM;
//POLLHUP 当读这个设备的进程见到文件尾, 驱动必须设置POLLUP(hang-up).
if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
mask |= POLLHUP;
if (tty_hung_up_p(file))
mask |= POLLHUP;
//唤醒tty读的最小值设置
if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
if (MIN_CHAR(tty) && !TIME_CHAR(tty))
tty->minimum_to_wake = MIN_CHAR(tty);
else
tty->minimum_to_wake = 1;
}
//POLLOUT 设备可被写入而不阻塞.
//POLLWRNORM 这个位和POLLOUT有相同的含义, 并且有时它确实是相同的数. 一个可写的设备返回( POLLOUT|POLLWRNORM).
if (tty->ops->write && !tty_is_writelocked(tty) &&
tty_chars_in_buffer(tty) < WAKEUP_CHARS &&
tty_write_room(tty) > 0)
mask |= POLLOUT | POLLWRNORM;
return mask;
}