linux内核追踪,Linux内核跟踪sys_listen函数笔记

Linux内核跟踪sys_listen函数笔记

[日期:2007-05-25]

来源:Linux公社

作者:Linux

[字体:大 中 小]

/*

* AUTHOR: anhk

* DATE: 2007-5-24

* KERNEL: 2.6.20

*

* 这是学习网络部分的笔记, 比较粗糙, 并且把一些引用计数代码去掉了.

* 还有部分加锁的代码

* sys_socketcall[net/socket.c]函数是整个网络的中断入口函数

*/

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;

}0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值