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