linux协议栈udp收发

刚学协议栈的同学可能不是找不见代码流程 而是不明白协议栈运行原理。例如进入内核态 中断 阻塞非阻塞等。

1
2
3
4
5
6
7
8
9
10
11
12
static int __init inet_init(void)

​ (void)sock_register(&inet_family_ops);



static const struct net_proto_family inet_family_ops = {
.family = PF_INET,
.create = inet_create,
.owner = THIS_MODULE,
};

一文搞懂Linux内核网络协议栈socket函数原理.

socket(AF_INET, SOCK_DGRAM, 0); -> inet_create

在这里插入图片描述

udp_rcv

​ __udp4_lib_rcv

​ udp_unicast_rcv_skb

​ udp_queue_rcv_skb

​ __udp_enqueue_schedule_skb

​ __skb_queue_tail

===================udp_queue_rcv_skb=========================

上面介绍了报文接收在软中断的处理流程,下面介绍用户态进程读取报文是如何实现的。用户态的recvmsg()最终会调用raw_recvmsg(),后者再调用skb_recv_datagram。如果套接字接收队列sk->sk_receive_queue中有报文就取skb并返回。否则调用wait_for_packet()等待,直到内核软中断收到报文并唤醒用户态进程。

sys_recvmsg()->sock_recvmsg()->…->sock_common_recvmsg()->raw_recvmsg()

sock_recvmsg

​ sock_recvmsg_nosec

​ sock->ops->recvmsg

​ inet_recvmsg //注册的ipv4 AF_INET

​ sk->sk_prot->recvmsg

​ udp_recvmsg //注册的数据包 SOCK_DGRAM

​ __skb_recv_udp

​ __skb_try_recv_from_queue //尝试从接收队列接收

​ __skb_wait_for_more_packets //如果不是非阻塞则 加入等待队列 休眠进程

1
2
3
4
5
6
7
8
9
10
11
12
int __skb_wait_for_more_packets(struct sock *sk, struct sk_buff_head *queue,
int *err, long *timeo_p,
const struct sk_buff *skb)
{
int error;
DEFINE_WAIT_FUNC(wait, receiver_wake_function);

​ prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);

​ ...

}

linux协议栈udp收发
https://dnsnat.gitee.io/NETWORK/linux协议栈udp收发.html
作者
dnsnat
发布于
2022年5月18日
许可协议