在linux 字符设备驱动程序中,poll_queue_proc 函数的作用是什么?
in linux char device driver, what does the poll_queue_proc function do?
linux中有多个设备文件同步轮询的概念,我正在尝试了解它是如何工作的。
在 linux 2.6.23 source drivers/char/random.c 中,我看到以下代码
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
static unsigned int
random_poll(struct file *file, poll_table * wait)
{
unsigned int mask;
poll_wait(file, &random_read_wait, wait);
poll_wait(file, &random_write_wait, wait);
mask = 0;
if (input_pool.entropy_count >= random_read_wakeup_thresh)
mask |= POLLIN | POLLRDNORM;
if (input_pool.entropy_count < random_write_wakeup_thresh)
mask |= POLLOUT | POLLWRNORM;
return mask;
}
poll_table 定义如下 include/linux/poll.h
typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
typedef struct poll_table_struct {
poll_queue_proc qproc;
} poll_table;
我在一本书(Ch.5,Essential Linux Device Drivers,Venkateswaran)中看到 "The poll_table is a table of wait queues owned by device drivers that are being polled for data." 但消息来源说它只是一个函数指针。而且我找不到这个函数 qproc 在做什么。
下面是 include/linux/poll.h.
中定义的函数 poll_wait
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
if (p && wait_address)
p->qproc(filp, wait_address, p);
}
并且在书中它说(关于鼠标的字符驱动程序示例),"mouse_poll() uses the library function, poll_wait(), to add a wait queue (mouse_wait) to the kernel poll_table and go to sleep." 所以 poll_wait 可以睡觉,但是在上面的 random_poll() 函数中,我们查看两个连续的 poll_wait 函数。那么 random_poll 是否按顺序轮询读写可用性并将掩码发送到应用程序?如果有人可以向我展示 poll_queue_proc 函数的示例,我将不胜感激。我在 linux 驱动程序源中找不到它(它应该只出现在应用程序中吗?)。
drivers/char/random.c:random_poll()
在用户空间调用时被调用
select()
(或 poll()
或 epoll_wait()
)与文件
引用 /dev/random
.
的描述符
这些系统调用是事件多路复用的基础。在里面
下面的程序,用户空间打开了一些输入源(比如
/dev/random
和 /dev/ttyS4
) 并调用 select()
他们 阻塞直到他们中的任何一个 有输入数据要读取。 (那里
是input以外的其他事件源,input只是最简单的。)
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define _SYSE(ret, msg) do { \
if (ret == -1) { \
perror(msg); \
exit(EXIT_FAILURE); \
} \
} while (0)
static int /*bool: EOF detected*/ consume_fd(int fd, const char* msg)
{
char tmp[64];
ssize_t nread;
nread = read(fd, tmp, sizeof(tmp));
_SYSE(nread, "read");
if (nread == 0 /*EOF*/)
return 1;
printf("%s: consumed %ld bytes\n", msg, nread);
return 0;
}
int main(void)
{
int random_fd, tty_fd, nfds = 0;
random_fd = open("/dev/random", O_RDONLY);
_SYSE(random_fd, "open random");
if (random_fd > nfds)
nfds = random_fd+1;
tty_fd = open("/dev/ttyS4", O_RDONLY);
_SYSE(tty_fd, "open tty");
if (tty_fd > nfds)
nfds = tty_fd+1;
while (1) {
fd_set in_fds;
int ret;
FD_ZERO(&in_fds);
FD_SET(random_fd, &in_fds);
FD_SET(tty_fd, &in_fds);
ret = select(nfds, &in_fds, NULL, NULL, NULL);
_SYSE(ret, "select");
if (FD_ISSET(random_fd, &in_fds)) {
int eof_detected = consume_fd(random_fd, "random");
if (eof_detected)
break;
}
if (FD_ISSET(tty_fd, &in_fds)) {
int eof_detected = consume_fd(tty_fd, "tty");
if (eof_detected)
break;
}
}
return 0;
}
一旦随机数可用,或
串行线有数据。 (请注意,现在 /dev/random
不
块,而是生成伪随机数,所以输出真的是
快。)
是select()
调用进入内核的时候random_poll()
被调用,另一个类似的函数在 TTY 的某处
层 - 仅仅因为 select()
将这些文件描述符传递为
参数。这些函数应该只是将调用者排入队列
进入一个你够不到的 poll_table
(它
代表为此目的的调用任务)。
在第二阶段,select()
的实施暂停了
呼叫者,直到任何事件变为真。 (参见 fs/select.c
。)
linux中有多个设备文件同步轮询的概念,我正在尝试了解它是如何工作的。
在 linux 2.6.23 source drivers/char/random.c 中,我看到以下代码
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
static unsigned int
random_poll(struct file *file, poll_table * wait)
{
unsigned int mask;
poll_wait(file, &random_read_wait, wait);
poll_wait(file, &random_write_wait, wait);
mask = 0;
if (input_pool.entropy_count >= random_read_wakeup_thresh)
mask |= POLLIN | POLLRDNORM;
if (input_pool.entropy_count < random_write_wakeup_thresh)
mask |= POLLOUT | POLLWRNORM;
return mask;
}
poll_table 定义如下 include/linux/poll.h
typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
typedef struct poll_table_struct {
poll_queue_proc qproc;
} poll_table;
我在一本书(Ch.5,Essential Linux Device Drivers,Venkateswaran)中看到 "The poll_table is a table of wait queues owned by device drivers that are being polled for data." 但消息来源说它只是一个函数指针。而且我找不到这个函数 qproc 在做什么。 下面是 include/linux/poll.h.
中定义的函数 poll_waitstatic inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
if (p && wait_address)
p->qproc(filp, wait_address, p);
}
并且在书中它说(关于鼠标的字符驱动程序示例),"mouse_poll() uses the library function, poll_wait(), to add a wait queue (mouse_wait) to the kernel poll_table and go to sleep." 所以 poll_wait 可以睡觉,但是在上面的 random_poll() 函数中,我们查看两个连续的 poll_wait 函数。那么 random_poll 是否按顺序轮询读写可用性并将掩码发送到应用程序?如果有人可以向我展示 poll_queue_proc 函数的示例,我将不胜感激。我在 linux 驱动程序源中找不到它(它应该只出现在应用程序中吗?)。
drivers/char/random.c:random_poll()
在用户空间调用时被调用
select()
(或 poll()
或 epoll_wait()
)与文件
引用 /dev/random
.
这些系统调用是事件多路复用的基础。在里面
下面的程序,用户空间打开了一些输入源(比如
/dev/random
和 /dev/ttyS4
) 并调用 select()
他们 阻塞直到他们中的任何一个 有输入数据要读取。 (那里
是input以外的其他事件源,input只是最简单的。)
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define _SYSE(ret, msg) do { \
if (ret == -1) { \
perror(msg); \
exit(EXIT_FAILURE); \
} \
} while (0)
static int /*bool: EOF detected*/ consume_fd(int fd, const char* msg)
{
char tmp[64];
ssize_t nread;
nread = read(fd, tmp, sizeof(tmp));
_SYSE(nread, "read");
if (nread == 0 /*EOF*/)
return 1;
printf("%s: consumed %ld bytes\n", msg, nread);
return 0;
}
int main(void)
{
int random_fd, tty_fd, nfds = 0;
random_fd = open("/dev/random", O_RDONLY);
_SYSE(random_fd, "open random");
if (random_fd > nfds)
nfds = random_fd+1;
tty_fd = open("/dev/ttyS4", O_RDONLY);
_SYSE(tty_fd, "open tty");
if (tty_fd > nfds)
nfds = tty_fd+1;
while (1) {
fd_set in_fds;
int ret;
FD_ZERO(&in_fds);
FD_SET(random_fd, &in_fds);
FD_SET(tty_fd, &in_fds);
ret = select(nfds, &in_fds, NULL, NULL, NULL);
_SYSE(ret, "select");
if (FD_ISSET(random_fd, &in_fds)) {
int eof_detected = consume_fd(random_fd, "random");
if (eof_detected)
break;
}
if (FD_ISSET(tty_fd, &in_fds)) {
int eof_detected = consume_fd(tty_fd, "tty");
if (eof_detected)
break;
}
}
return 0;
}
一旦随机数可用,或
串行线有数据。 (请注意,现在 /dev/random
不
块,而是生成伪随机数,所以输出真的是
快。)
是select()
调用进入内核的时候random_poll()
被调用,另一个类似的函数在 TTY 的某处
层 - 仅仅因为 select()
将这些文件描述符传递为
参数。这些函数应该只是将调用者排入队列
进入一个你够不到的 poll_table
(它
代表为此目的的调用任务)。
在第二阶段,select()
的实施暂停了
呼叫者,直到任何事件变为真。 (参见 fs/select.c
。)