select系统调用
主要对select调用过程进行一些总结,后边也会有poll和epoll相关的一系列分析。
对于分析系统调用select的源码版本是2.6.25。
select系统调用的用途是:在一段指定时间内,监听用户感兴趣的文件描述符上的可读、可写和异常等事件。
1. select系统调用的原型如下:
#include <sys/select.h>
int select( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout );
主要调用流程如下:

2. select流程
2.1 sys_select
asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
fd_set __user *exp, struct timeval __user *tvp)
{
s64 timeout = -1;
struct timeval tv;
int ret;
if (tvp) { /*如果有超时值*/
if (copy_from_user(&tv, tvp, sizeof(tv)))
return -EFAULT;
if (tv.tv_sec < 0 || tv.tv_usec < 0) /*时间无效*/
return -EINVAL;
/* Cast to u64 to make GCC stop complaining */
if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
timeout = -1; /* 无限等待*/
else {
timeout = DIV_ROUND_UP(tv.tv_usec, USEC_PER_SEC/HZ);
timeout += tv.tv_sec * HZ;\ }
}
/*主要工作都在core_sys_select中做了*/
ret = core_sys_select(n, inp, outp, exp, &timeout);
if (tvp) {/*如果有超时值*/
struct timeval rtv;
if (current->personality & STICKY_TIMEOUTS)/*模拟bug的一个机制,不详细描述*/
goto sticky;
/*rtv中是剩余的时间*/
rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
rtv.tv_sec = timeout;
if (timeval_compare(&rtv, &tv) >= 0)/*如果core_sys_select超时返回,更新时间*/
rtv = tv;
/*拷贝更新后的时间到用户空间*/
if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
sticky:
if (ret == -ERESTARTNOHAND) /*ERESTARTNOHAND表明,被中断的系统调用*/
ret = -EINTR;
}
}
return ret;
}
2.2 core_sys_select
在28行处调用core_sys_select函数,然后处理三个fd_set参数,调用do_select,将返回的结果集,返回到用户空间。
首先,fd_set结构体仅包含一个整型数组,该数组的每一位(bit)标记一个文件描述符。fd_set能容纳的文件描述符数量由FD_SETSIZE指定,这也就

340

被折叠的 条评论
为什么被折叠?



