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

 SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
fd_set __user *, exp, struct timeval __user *, tvp)
{
struct timespec64 end_time, *to = NULL;
struct timeval tv;
int ret; if (tvp) {
if (copy_from_user(&tv, tvp, sizeof(tv)))
return -EFAULT; to = &end_time;
if (poll_select_set_timeout(to,
tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
(tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
return -EINVAL;
} ret = core_sys_select(n, inp, outp, exp, to);
ret = poll_select_copy_remaining(&end_time, tvp, , ret); return ret;
}

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

  /**
* select系统调用函数调用关系
* sys_select
* |-->core_sys_select
* |-->do_select
* |-->f_op->poll 调用文件的poll操作
*/

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

 /*
* Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
* in the operation structures but are done directly via the socketcall() multiplexor.
*/
/* socket文件操作函数 */
static const struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read_iter = sock_read_iter,
.write_iter = sock_write_iter,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_sock_ioctl,
#endif
.mmap = sock_mmap,
.release = sock_close,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read = sock_splice_read,
};

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

 /* No kernel lock held - perfect */
static unsigned int sock_poll(struct file *file, poll_table *wait)
{
unsigned int busy_flag = ;
struct socket *sock; /*
* We can't return errors to poll, so it's either yes or no.
*/
/* 获取到socket */
sock = file->private_data; if (sk_can_busy_loop(sock->sk)) {
/* this socket can poll_ll so tell the system call */
busy_flag = POLL_BUSY_LOOP; /* once, only if requested by syscall */
if (wait && (wait->_key & POLL_BUSY_LOOP))
sk_busy_loop(sock->sk, );
} /* 执行socket操作中的poll,tcp为tcp_poll,udp为udp_poll */
return busy_flag | sock->ops->poll(file, sock, wait);
}

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

最新文章

  1. js控制div滚动条,滚动滚动条使div中的元素可见并居中
  2. Validate Disk Failover Failed
  3. Ubuntu下root密码认证错误
  4. Porter/Duff,图片加遮罩setColorFilter
  5. Sharepoint学习笔记—习题系列--70-573习题解析 -(Q104-Q106)
  6. 关联参数(&的用法)
  7. 解决ionic在ios无法使用focus,ios focus失效的问题
  8. Spring/Hibernate Improved SQL Logging with log4jdbc---reference
  9. Android AES加密算法及事实上现
  10. android viewpager 深究
  11. 循环神经网络RNN公式推导走读
  12. [刷题]算法竞赛入门经典(第2版) 4-3/UVa220 - Othello
  13. SPI FLASH与NOR FLASH的区别?
  14. Carthage入门篇-安装和使用
  15. vue插件 使用use注册Vue全局组件和全局指令
  16. Visual Studio Code 常用快捷键
  17. js 动态声明变量
  18. 字符串最长子串匹配-dp矩阵[转载]
  19. jar与war 包解压
  20. linux kill 掉所有匹配到名字的进程

热门文章

  1. 解决mac下brew install报错
  2. 详解EveryThing
  3. 树莓派wifi环境下初始化及环境配置
  4. 在centos7上kvm网卡桥接
  5. golang 方法
  6. maven中使用jetty插件
  7. 使用putty对linux与windows之间的文件传输
  8. js获取前几个月的具体日期
  9. hivesql之str_to_map函数
  10. Oracle数据库查询优化方案