/*linux-5.10.x\net\ipv4\udp.c
*负责接收UDP数据包,并进行数据处理、复制和相关的控制消息处理。也处理接收过程中的错误情况,并提供时间戳和丢弃计数等统计信息
1、参数解析:函数接收struct sock类型的套接字指针sk和struct msghdr类型的消息头指针msg作为参数
2、数据接收:函数通过调用sk_recv_datagram函数从套接字的接收队列中获取一个数据包,
该函数会处理接收缓冲区的相关逻辑,包括数据包的复制和消耗等
3、数据处理:函数根据套接字的类型和配置,对接收到的数据包进行处理,例如校验和验证、解析IP头部、解析UDP头部等
4、数据复制:函数将接收到的数据复制到msg结构体中的缓冲区,并更新复制的数据长度
5、控制消息处理:函数根据套接字的配置,处理控制消息,例如获取源地址信息、处理IP层的控制消息等
6、错误处理:函数处理接收过程中可能出现的错误情况,例如校验和错误、无法放入接收队列等,同时更新相关的统计信息
7、时间戳和丢弃计数:函数根据套接字的类型和配置,获取接收数据包的时间戳和丢弃的数据包计数,
并将其存储在msg结构体中的msg_control字段中
8、返回值:函数返回已经复制的数据长度
*/
int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
int flags, int *addr_len)
{
struct inet_sock *inet = inet_sk(sk); // 获取套接字的底层数据结构 inet_sock 的指针
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); // 将消息头部的 msg_name 强制转换为 sockaddr_in 类型
struct sk_buff *skb; // 用于处理网络数据包
unsigned int ulen, copied; // UDP 数据包长度和拷贝长度
int off, err, peeking = flags & MSG_PEEK; // 偏移量 off、错误码 err 和标志位 peeking,标志是否进行 MSG_PEEK 操作
int is_udplite = IS_UDPLITE(sk); // 判断是否为 UDPLite 协议(轻型 UDP)
bool checksum_valid = false; // 标志校验和是否有效
if (flags & MSG_ERRQUEUE) // 如果flags参数中包含了MSG_ERRQUEUE标志
return ip_recv_error(sk, msg, len, addr_len); // 处理接收错误队列中的数据包,并返回结果
try_again: /* 设置标签try_again,在需要重新尝试接收数据包时跳转到该标签 */
off =<
linux内核代码-注释详解:udp_recvmsg
最新推荐文章于 2024-08-14 18:08:45 发布