Orchid poll 剖析
来源:互联网 发布:淘宝站内推广有哪些 编辑:程序博客网 时间:2024/06/10 01:18
/*
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
可以看到,poll 的参数中,直接列出了要监视的文件描述符的信息,而不像 select
一样要列出从 0 开始到 nfds-1 的所有文件描述符。这样的好处是,poll 不需要查询很多无
关的文件描述符的信息,在一定场合下效率会有所提高。
*/
struct poll_list {
struct poll_list *next;
int len;
struct pollfd entries[0];
}; //用来保存被监视的文件描述符的参数
struct pollfd {
int fd;
short events;
short revents;
};//记录被监视的文件描述符和它的状态。
asmlinkage long sys_poll(struct pollfd __user * ufds,unsigned int nfds,long timeout)
{
struct poll_wqueues table;
int fdcount, err;
unsigned int i;
struct poll_list *head;
struct poll_list *walk;
/* Do a sanity check on nfds ... */
if (nfds > current->files->max_fdset && nfds > OPEN_MAX)
// 用户给的nfds数不可以超过一个struct file结构支持的最大fd数(默认是256)
return -EINVAL;
if (timeout) {
/* Careful about overflow in the intermediate values */
if ((unsigned long)timeout < MAX_SCHEDULE_TIMEOUT / HZ)
timeout = (unsigned long)(timeout*HZ + 999) / 1000 + 1;
else /* Negative or overflow */
timeout = MAX_SCHEDULE_TIMEOUT;
}
poll_initwait(&table); /*其中poll_initwait较为关键,从字面上看,应该是初始化变量table,
注意此处table在整个执行poll的过程中是很关键的变量。
而struct poll_table其实就只包含了一个函数指针 :*/
//init_poll_funcptr(&pwq->pt, __pollwait);
head = NULL;
walk = NULL;
i = nfds;
err = -ENOMEM;
while (i != 0) {
struct poll_list *pp;
pp = kmalloc(sizeof(struct poll_list) +
sizeof(struct pollfd)*
(i>POLLFD_PER_PAGE ? POLLFD_PER_PAGE : i),
GFP_KERNEL);
if (pp == NULL)
goto out_fds;
pp->next = NULL;
pp->len = (i>POLLFD_PER_PAGE ? POLLFD_PER_PAGE : i);
if (head == NULL)
head = pp;
else
walk->next = pp;
walk = pp;
/*
这一大堆代码就是建立一个链表,每个链表的节点是一个page大小(通常是4k),这链表节点由一个指向
struct poll_list的指针掌控,而众多的struct pollfd就通过struct_list的entries成员访问。上面的循环就
是把用户态的struct pollfd拷进这些entries里。通常用户程序的poll调用就监控几个fd,所以上面这个链
表通常也就只需要一个节点,即操作系统的一页。但是,当用户传入的fd很多时,由于poll系统调用每次都
要把所有struct pollfd拷进内核,所以参数传递和页分配此时就成了poll系统调用的性能瓶颈。
*/
if (copy_from_user(pp->entries, ufds + nfds - i,
sizeof(struct pollfd)*pp->len)) {
err = -EFAULT;
goto out_fds;
}
i -= pp->len;
}
fdcount = do_poll(nfds, head, &table, timeout); //****
/* OK, now copy the revents fields back to user space. */
walk = head;
err = -EFAULT;
while (walk != NULL) {
struct pollfd *fds = walk->entries;
int j;
for (j = 0; j < walk->len; j++, ufds++) {
if (__put_user(fds[j].revents, &ufds->revents))
goto out_fds;
}
walk = walk->next;
}
err = fdcount;
if (!fdcount && signal_pending(current))
err = -EINTR;
out_fds:
walk = head;
while (walk != NULL) {
struct poll_list *pp = walk->next;
kfree(walk);
walk = pp;
}
poll_freewait(&table);
return err;
}
void poll_initwait(struct poll_wqueues *pwq)
{
init_poll_funcptr(&pwq->pt, __pollwait);
pwq->error = 0;
pwq->table = NULL;
}
static int do_poll(unsigned int nfds,struct poll_list *list,
struct poll_wqueues *wait, long timeout)
{
int count = 0;
poll_table* pt = &wait->pt;
if (!timeout)
pt = NULL;
for (;;) {
struct poll_list *walk;
set_current_state(TASK_INTERRUPTIBLE);
walk = list;
while (walk != NULL) {
do_pollfd(walk->len, walk->entries, &pt, &count);
walk = walk->next;
}
pt = NULL;
if (count || !timeout || signal_pending(current))
break;
count = wait->error;
if (count)
break;
timeout = schedule_timeout(timeout);
}
__set_current_state(TASK_RUNNING);
return count;
}
static void do_pollfd(unsigned int num,struct pollfd * fdpage,
poll_table ** pwait, int *count)
{
int i;
for (i = 0; i < num; i++) {
int fd;
unsigned int mask;
struct pollfd *fdp;
mask = 0;
fdp = fdpage + i;
fd = fdp->fd;
if (fd >= 0) {
struct file * file = fget(fd);
mask = POLLNVAL;
if (file != NULL) {
mask = DEFAULT_POLLMASK;
if (file->f_op && file->f_op->poll)
mask = file->f_op->poll(file, *pwait);
mask &= fdp->events | POLLERR | POLLHUP;
fput(file);
}
if (mask) {
*pwait = NULL;
(*count)++;
}
}
fdp->revents = mask;
}
}
- Orchid poll 剖析
- Orchid select 剖析
- epoll和poll剖析
- poll内核源代码剖析
- poll源码剖析
- poll源码剖析
- 源码剖析之poll
- poll与epoll源码剖析
- POLL/EPOLL的实现剖析
- linux 内核poll/select/epoll实现剖析
- linux 内核poll/select/epoll实现剖析
- linux 内核poll/select/epoll实现剖析
- With an Orchid ---年度总结
- linux下poll和epoll内核源代码剖析
- linux 内核poll/select/epoll实现剖析(原理经典)
- IO复用——poll机制内核源代码剖析
- poll()
- poll
- 疯狂Java笔记:3.1 注释
- 嵌入式LinuxC语言小常识
- Android笔记之获取文件MimeType
- MySQL 中NULL和空值的区别
- 成功解决方案cannot resolve symbol window
- Orchid poll 剖析
- 什么是真的学习能力
- PLSQL Recursion DB
- iframe获取父、子窗口的方法
- maven+hudson+git持续集成
- javascript-MDN笔记-函数
- IO复用之epoll
- Python(Pygame)字体设置
- Jenkins+Maven+Git搭建持续集成和自动化部署的配置手记