select源码剖析(Linux2.6.11)

select是在一定时间内,监听用户注册的可读、可写、异常事件。它的可读、可写、异常事件分别对应着文件描述符的集合。当有事件发生的时候,内核就会修改这些参数来告诉应用程序哪些文件描述符以及就绪了。这样的话下次调用select时就需要重新设置可读、可写、异常事件的文件描述符。
select系统调用的顺序是:
select () -> sys_select() -> do_select ()
所以,select是系统调用,它进入内核态就调用sys_select()

typedef struct 
{
    unsigned long *in, *out, *ex;
    unsigned long *res_in, *res_out, *res_ex;
}fd_set_bits;
/*
in out ex分别保存用户注册的感兴趣的事件,res_in,res_out,res_ex分别保存这个文件描述符上的用户感兴趣的事件,
返回的时候把res_in res_out res_ex的值赋给in,out,ex,这就是从用户空间拷贝到内核空间,然后再从内核空间拷贝到用户空间。
因为select这样每次调用的时候需要来回拷贝,所以造成效率问题。
当fd_set_bits这个结构体整合好之后当做参数,作为参数传递给do_select()
*/
//sys_select是处理时间函数
asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
{
    fd_set_bits fds;//这个结构体保存用户传进来的参数
    char *bits;
    long timeout;
    int ret, size, max_fdset;

    //从用户进程拷贝超时时间,将超时时间换成时钟周期数
    timeout = MAX_SCHEDULE_TIMEOUT;//检查事件会不会永远等待下去
    if (tvp) {
  //对timeval超时时间参数处理
        time_t sec, usec;

        if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
            || (ret = __get_user(sec, &tvp->tv_sec))
            || (ret = __get_user(usec, &tvp->tv_usec)))
            goto out_nofds;

        ret = -EINVAL;
        if (sec < 0 || usec < 0)
            goto out_nofds;
    //进行单位换算
        if ((unsigned long) sec < MAX_SELECT_SECONDS) {
            timeout = ROU
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值