• 套接字之select系统调用


    select是IO多路复用的一种方式,用来等待一个列表中的多个描述符的可读可写状态;

     1 SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
     2         fd_set __user *, exp, struct timeval __user *, tvp)
     3 {
     4     struct timespec64 end_time, *to = NULL;
     5     struct timeval tv;
     6     int ret;
     7 
     8     if (tvp) {
     9         if (copy_from_user(&tv, tvp, sizeof(tv)))
    10             return -EFAULT;
    11 
    12         to = &end_time;
    13         if (poll_select_set_timeout(to,
    14                 tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
    15                 (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
    16             return -EINVAL;
    17     }
    18 
    19     ret = core_sys_select(n, inp, outp, exp, to);
    20     ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
    21 
    22     return ret;
    23 }

    本文主要分析socket的select操作,所以对于select系统调用前面通用的部分,我们只分析其调用关系,如下,可见在do_select函数中,会调用文件操作的poll函数;

    1  /**
    2   * select系统调用函数调用关系
    3   * sys_select
    4   *   |-->core_sys_select
    5   *       |-->do_select
    6   *           |-->f_op->poll 调用文件的poll操作
    7   */

    socket文件操作结构实现如下,我们本文重点分析poll操作,即sock_poll函数;

     1 /*
     2  *    Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
     3  *    in the operation structures but are done directly via the socketcall() multiplexor.
     4  */
     5 /* socket文件操作函数 */
     6 static const struct file_operations socket_file_ops = {
     7     .owner =    THIS_MODULE,
     8     .llseek =    no_llseek,
     9     .read_iter =    sock_read_iter,
    10     .write_iter =    sock_write_iter,
    11     .poll =        sock_poll,
    12     .unlocked_ioctl = sock_ioctl,
    13 #ifdef CONFIG_COMPAT
    14     .compat_ioctl = compat_sock_ioctl,
    15 #endif
    16     .mmap =        sock_mmap,
    17     .release =    sock_close,
    18     .fasync =    sock_fasync,
    19     .sendpage =    sock_sendpage,
    20     .splice_write = generic_splice_sendpage,
    21     .splice_read =    sock_splice_read,
    22 };

    sock_poll函数在获取到socket之后,会调用其操作中的poll函数,其中tcp为tcp_poll,udp为udp_poll;

     1 /* No kernel lock held - perfect */
     2 static unsigned int sock_poll(struct file *file, poll_table *wait)
     3 {
     4     unsigned int busy_flag = 0;
     5     struct socket *sock;
     6 
     7     /*
     8      *      We can't return errors to poll, so it's either yes or no.
     9      */
    10     /* 获取到socket */
    11     sock = file->private_data;
    12 
    13     if (sk_can_busy_loop(sock->sk)) {
    14         /* this socket can poll_ll so tell the system call */
    15         busy_flag = POLL_BUSY_LOOP;
    16 
    17         /* once, only if requested by syscall */
    18         if (wait && (wait->_key & POLL_BUSY_LOOP))
    19             sk_busy_loop(sock->sk, 1);
    20     }
    21 
    22     /* 执行socket操作中的poll,tcp为tcp_poll,udp为udp_poll */
    23     return busy_flag | sock->ops->poll(file, sock, wait);
    24 }

    tcp_poll的代码分析会在阅读tcp源码时补充;

  • 相关阅读:
    基于thinkphp3.2.3开发的CMS内容管理系统(二)- Rbac用户权限
    phpstrom 快捷键
    基于thinkphp3.2.3开发的CMS内容管理系统
    html中的字幕滚动marquee属性
    学会这些网站优化技巧,秒变seo专家
    服务器设置防火墙规则,实现远程桌面连接的ip限制
    IIS7.5中神秘的ApplicationPoolIdentity
    mysql 安装成功后如何设置密码?
    网站优化提高加载速度的14个技巧
    解决帝国cms系统后台管理员登录密码输入五次密码错误后需等候60分钟的方法
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11749272.html
Copyright © 2020-2023  润新知