"); //-->
asmlinkage long sys_socketcall(int call, unsigned long __user *args);
{
unsigned long a[6];
/* 从用户空间得到信息,该函数是SMP安全的 */
if (copy_from_user(a, args, nargs[call]))
return -EFAULT;
switch (call) {
case SYS_SOCKET:
err = sys_socket(a[0], a[1], a[2]);
break;
case SYS_BIND:
err = sys_bind(a[0], (struct sockaddr __user *)a[1], a[2]);
break;
case SYS_CONNECT:
err = sys_connect(a[0], (struct sockaddr __user *)a[1], a[2]);
break;
....
}
}
/*
* 下面跟踪sys_listen函数
*
* 该函数首先通过调用sockfd_lookup_light函数,
* 根据描述符获得拥有该描述符的struct file *file结构, 然后根据该file结构获得struct socket *sock结构
* 从用户空间得到fd和backlog
* 调用sock->ops->listen()函数, 该函数在tcp中是inet_listen[net/ipv4/af_inet.c]
* 如果是udp, 则sock->ops->listen = sock_no_listen,直接返回
*/
asmlinkage long sys_listen(int fd, int backlog)
{
struct socket *sock;
int err, fput_needed;
/*
* 查找到具有该描述符的struct socket *sock结构
*/
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
if ((unsigned)backlog > sysctl_somaxconn)
backlog = sysctl_somaxconn;
/*
* sock->ops = &inet_stream_ops || &inet_dgram_ops,
*
* TCP: sock->ops->listen = inet_listen
* UDP: sock->ops->listen = sock_no_listen
*/
err = sock->ops->listen(sock, backlog);
fput_light(sock->file, fput_needed);
}
return err;
}
/*
* inet_listen函数中,首先判断该sock的状态是否SS_UNCONNECTED 且类型 是否是SOCK_STREAM, 否的话直接退出
* 然后 判断该sock->sk是否是已侦听状态, 如果是就直接设置backlog, 退出
* 否则调用 inet_csk_listen_start[net/ipv4/inet_connection_sock.c]
*/
int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
unsigned char old_state;
int err;
lock_sock(sk);
err = -EINVAL;
if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
goto out;
old_state = sk->sk_state;
if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
goto out;
/* Really, if the socket is already in listen state
* we can only allow the backlog to be adjusted.
*/
if (old_state != TCP_LISTEN) {
err = inet_csk_listen_start(sk, backlog);
if (err)
goto out;
}
sk->sk_max_ack_backlog = backlog;
err = 0;
out:
release_sock(sk);
return err;
}
/*
* inet_csk_listen_start[net/ipv4/inet_connection_sock.c]
* 该函数首先调用reqsk_queue_alloc[net/core/request_sock.c]申请一块内存, 存放侦听 队列 for accept;
* 然后设置侦听状态,并把该struct sock *sk放入tcp_hashinfo.ehash中
*/
int inet_csk_listen_start(struct sock *sk, const int nr_table_entries)
{
struct inet_sock *inet = inet_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
int rc = reqsk_queue_alloc(&icsk->icsk_accept_queue, nr_table_entries);
if (rc != 0)
return rc;
sk->sk_max_ack_backlog = 0;
sk->sk_ack_backlog = 0;
/*
* only memset
* memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack));
*/
inet_csk_delack_init(sk);
/*
* 设置侦听状态, 并且判断该端口没有被使用
* 然后 加入到tcp_hashinfo.ehash中
* return 0;
*/
sk->sk_state = TCP_LISTEN;
if (!sk->sk_prot->get_port(sk, inet->num)) {
inet->sport = htons(inet->num);
sk_dst_reset(sk);
sk->sk_prot->hash(sk);
return 0;
}
sk->sk_state = TCP_CLOSE;
__reqsk_queue_destroy(&icsk->icsk_accept_queue);
return -EADDRINUSE;
}
Linux好学堂, www.linuxhao.com,Linux应用开发综合性技术网站,提供Linux视频教程,Linux培训教程,Linux技术资料免费下载。
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
晶体稳频超低频移相信号发生器的研制
结合脊和谷信息的指纹细节特征提取方法
开放式音频:面向AR/VR应用的增强型高质量解决方案
集成电路十二五规划思考
MYD-LD25X Cortex-M33实时核开发实战解析
不只有AI协作编程(Vibe Coding):生成式系统级芯片(GenSoC)将如何把生成式设计推向硬件层面
求:PCMCIA文档
简易的雷达扫描防盗系统
从概念验证到投入生产:助力边缘AI走进现实
由无线收发器组成的多用途报警器电路
联发科技校园软件大赛——无名
福特可能会杀死 F-150 Lightning
二极管导通时间引发开关稳压器的故障
电子自动门与报警器两用电路
中国是世界最安全国家!
米尔SECC方案助力国标充电桩出海
欢迎来到AI俚语时代:这些年度词语你知道几个?
具有高可靠性的高速连续数据采集的设计与实施方法
中华绝技!
国产EDA软件的发展之路
具有感兴趣区域的静止图像压缩编码算法研究
这个网站不错!
破局“芯”困境,西北地区首条硅光中试线正式通线
中国芯片装备行业乘2025年IPO浪潮助力国产化
联发科技校园软件大赛——mabill
超声波移动报警器
请教: 如何用multi-ice仿真器调试rom中的程序
介绍一种实时操作系统DSP/BIOS
微波防盗报警电路
Vicor紧凑型电源系统为电动汽车主动悬架系统节省空间与重量