accept系统调用内核实现
用户态对accept的标准使用方法:
if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1)
{
//accept()函数让server接收客户的连接请求
perror("accept Error\n");
continue;
}
sockfd是通过socket系统调用,而且经过listen过的套接字:
sockfd = socket(AF_INET, SOCK_STREAM, 0)
listen(sockfd, 128) remote_addr将会存储远端设备的地址信息。 /*
* For accept, we attempt to create a new socket, set up the link
* with the client, wake up the client, then return the new
* connected fd. We collect the address of the connector in kernel
* space and move it to user at the very end. This is unclean because
* we open the socket then return an error.
*
* 1003.1g adds the ability to recvmsg() to query connection pending
* status to recvmsg. We need to add that support in a way thats
* clean when we restucture accept also.
*/ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen)
{
struct socket *sock, *newsock;
struct file *newfile;
int err, len, newfd, fput_needed;
char address[MAX_SOCK_ADDR]; //通过监听套接字的描写叙述符fd,找到监听套接字
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out; err = -ENFILE;
//创建新的socket,即心的套接字,它将被client_fd 描写叙述,用于数据传输,
//也就是accept系统调用返回值client_fd 所相应的套接口
if (!(newsock = sock_alloc()))
goto out_put; //继承listen_fd相应的的一些属性,包含套接字类型,和操作。
//不难理解,listen_fd和client_fd 相应的套接口都是tcp,这些不用一一赋值,直接用listen_fd的属性就可以。
newsock->type = sock->type;
newsock->ops = sock->ops; /*
* We don't need try_module_get here, as the listening socket (sock)
* has the protocol module (sock->ops->owner) held.
*/
//不懂
__module_get(newsock->ops->owner); //创建新的file,然后返回newfd ,这个fd就是待会被返回的client_fd
//到如今为止,这个newfd和newfile是有关联的。
newfd = sock_alloc_fd(&newfile);
if (unlikely(newfd < 0)) {
err = newfd;
sock_release(newsock);
goto out_put;
}
//使得这个newsock绑定刚才新建的newfile
//即如今为止,newfd newfile newsock之间是有关联的
err = sock_attach_fd(newsock, newfile);
if (err < 0)
goto out_fd_simple; err = security_socket_accept(sock, newsock);
if (err)
goto out_fd;
//newsock是socket结构体,sock->ops->accept的目的是为newsock关联一个sock结构体
//即三次握手结束后,新建的sock传输控制块,它等待用户accept系统调用“领养”它。
//sock->ops->accept相应的函数是inet_accept
err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0)
goto out_fd; if (upeer_sockaddr) {
if (newsock->ops->getname(newsock, (struct sockaddr *)address,
&len, 2) < 0) {
err = -ECONNABORTED;
goto out_fd;
}
err = move_addr_to_user(address, len, upeer_sockaddr,
upeer_addrlen);
if (err < 0)
goto out_fd;
}
.........................................
} /*
* Accept a pending connection. The TCP layer now gives BSD semantics.
*/
int inet_accept(struct socket *sock, struct socket *newsock, int flags)
{
//第一个參数sock是监听套接字代表的套接字
//newsock是刚才我们新建的套接字,用以描写叙述数据传输
//显然,此函数的目的,是找到通过套接字,找到套接字上挂着的以及完毕三次握手的sk
//这个被找到的sk,将被关联到newsock //sk1 是监听套接字相应的传输控制块
struct sock *sk1 = sock->sk;
int err = -EINVAL; //sk2(三次握手后建立的传输控制块) 是挂在sk1(监听套接字的传输控制块) 中的完毕三次握手后的sk
// sk1->sk_prot->accept 相应的函数是inet_csk_accept
struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err); if (!sk2)
goto do_err; lock_sock(sk2); WARN_ON(!((1 << sk2->sk_state) &
(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); //这个被找到的sk,将被关联到newsock
//三次握手后建立的传输控制块sk(sock 结构体),是不正确应不论什么socket结构体的,所以我们关联上
//这样三次握手后建立的传输控制块sk,就和文件系统有关联了
//关联上后,我们就能对其调用send,recvfrom等系统调用了
sock_graft(sk2, newsock); newsock->state = SS_CONNECTED;
err = 0;
release_sock(sk2);
do_err:
return err;
} /*
* This will accept the next outstanding connection.
*/
//inet_csk_accept的功能时获取建立3次握手后的sk,一次调用返回一个sk
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
{
//第一个參数是监听套接字相应的传输控制块。
struct inet_connection_sock *icsk = inet_csk(sk);
struct sock *newsk;
int error; lock_sock(sk); /* We need to make sure that this socket is listening,
* and that it has something pending.
*/
error = -EINVAL;
//假设你传进的參数正确,监听套接字相应的传输控制块的状态,肯定是TCP_LISTEN
if (sk->sk_state != TCP_LISTEN)
goto out_err; /* Find already established connection */
//icsk->icsk_accept_queue挂的是request_sock,request_sock上挂的就是三次握手后新建的sk
//reqsk_queue_empty(&icsk->icsk_accept_queue)推断是否空,就进入if,怎样设置为堵塞,则休眠
if (reqsk_queue_empty(&icsk->icsk_accept_queue)) {
long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); /* If this is a non blocking socket don't sleep */
error = -EAGAIN;
if (!timeo)
goto out_err; error = inet_csk_wait_for_connect(sk, timeo);
if (error)
goto out_err;
} //reqsk_queue_get_child的逻辑是:
//1:取出icsk_accept_queue的request_sock,然后取出request_sock中的sk
//2:listen的sk中,sk_ack_backlog计数减一,sk->sk_ack_backlog--,由于sk_ack_backlog有上限。
//3:删除request_sock
//4:return取出的sk
newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk);
WARN_ON(newsk->sk_state == TCP_SYN_RECV);
out:
release_sock(sk);
return newsk;
out_err:
newsk = NULL;
*err = error;
goto out;
}
accept系统调用内核实现的更多相关文章
- 实验作业:使gdb跟踪分析一个系统调用内核函数
实验作业:使gdb跟踪分析一个系统调用内核函数(我使用的是getuid) 20135313吴子怡.北京电子科技学院 [第一部分] 根据视频演示的步骤,先做第一部分,步骤如下 ①更新menu代码到最新版 ...
- accept系统调用
/* * For accept, we attempt to create a new socket, set up the link * with the client, wake up the c ...
- Linux之增加系统调用[内核编译]
声明:如需引用或者摘抄本博文源码或者其文章的,请在显著处注明,来源于本博文/作者,以示尊重劳动成果,助力开源精神.也欢迎大家一起探讨,交流,以共同进步- 0.0 由于操作系统实验的缘故,有一个实验需要 ...
- TCP层accept系统调用的实现分析
inet_csk_accept函数实现了tcp协议accept操作,其主要完成的功能是,从已经完成三次握手的队列中取控制块,如果没有已经完成的连接,则需要根据阻塞标记来来区分对待,若非阻塞则直接返回, ...
- Linux内核分析之扒开系统调用的三层皮(下)
一.实验内容 1. 通过内核的方式使用系统调用 需要使用的命令 rm menu -rf //强制删除当前menugit clone http://github.com/mengning/menu.gi ...
- 《Linux内核分析》第五周 扒开系统调用的三层皮(下)
[刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FIVE( ...
- Linux内核分析第五周学习总结:扒开系统调用的三层皮(下)
韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.给MenuO ...
- Linux内核-系统调用
Linux内核-系统调用 1.与内核通信 #系统调用在用户空间进程和硬件设备之间添加了一个中间层 作用:1.为用户空间提供了一种硬件的抽象接口 2.系统调用保证了系统的稳定和安全 3.出于每一个进程都 ...
- Linux内核及分析 第五周 扒开系统调用的三层皮(下)
实验内容: 1.执行rm menu -rf命令,强制删除原有的menu 2.使用git命令 git clone https://github.com/mengning/menu.git 克隆新的men ...
随机推荐
- tomcat 系统服务 outofmemory
TOMCAT内存溢出outofmemory的问题: http://hi.baidu.com/mefeng47/item/3b247af74ce4e24e922af2e5 注:双击tomcat6w.ex ...
- 【转】理解RESTful架构
[转]理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时( ...
- Oracle AWR 报告详解
转自:http://blog.csdn.net/laoshangxyc/article/details/8615187 持续更新中... Oracle awr报告详解 DB Name DB Id In ...
- nice Validator参考
快速上手 例1. DOM传参 1. 要验证一个表单,只需要给字段绑定规则“data-rule”就可以了2. 字段可以有多条规则,规则之间用分号(;)分隔3. js初始化不是必要的,只要是字段并且带有“ ...
- UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现
UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现 类与类图 1) 类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性.操作.关系的对象集合的总称. 2) 在系统中, ...
- 【翻译自mos文章】当指定asm disk 为FRA时,11.2.0.3的dbua hang住
当指定asm disk 为FRA时.11.2.0.3的dbua hang住 来源于: 11.2.0.3 DBUA Hangs While Specifying ASM Disk To FRA (文档 ...
- Unity3D 4.x 使用Mecanim实现动画控制
Unity3D 4.x 版本号之后提供了一种新的动画机制Mecanim,尽管眼下还支持之前的Animation.但看到Unity3D 4.3 预览版里Sprite的动画也是基于Animator的,可知 ...
- 安装基于XenServer的DevStack
Openstack默认的hypervisior是基于KVM的,可以修改nova-compute.conf的libvirt_type改成使用其他,网上可以搜到个别文章 但是Openstack官方文档却说 ...
- C# 课堂总结1-二进制转换
一.目的:便于计算机表示,稳定性好,符合逻辑运算,真为1,假为0. 二.各进制表示方法: 2进制:0,1 8进制:0-7 16进制:0-9,A,B,C,D,E,F 二.转换方法: 1.各进制转换为10 ...
- java--equal&==
[转自]http://blog.csdn.net/yiqunattack/article/details/5727143 [非常详细的介绍了string的用法http://blog.csdn.net/ ...