linux内核代码-注释详解:recvfrom & __sys_recvfrom

//linux-5.10.x\net\socket.c
SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
		unsigned int, flags, struct sockaddr __user *, addr,
		int __user *, addr_len)
{
	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
	/*参数
		int, fd:表示文件描述符。
		void __user *, ubuf:表示接收数据的缓冲区
		size_t, size:表示接收数据的最大长度
		unsigned int, flags:表示标志参数
		struct sockaddr __user *, addr:表示指向存储发送方地址信息的结构体的指针
		int __user *, addr_len:表示发送方地址信息的长度
	*/
}
int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
                   struct sockaddr __user *addr, int __user *addr_len)
{
    struct socket *sock;  												// 套接字指针
    struct iovec iov;  													// 消息数据缓冲区描述符
    struct msghdr msg;  												// 消息头描述符
    struct sockaddr_storage address;  									// 存储目标地址信息的结构体
    int err, err2;  													// 错误码
    int fput_needed;  													// 是否需要减少引用计数

    err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);	// 将用户空间缓冲区(ubuf)导入为内核空间的数据,以便进行读取或操作
    /*参数:
		READ:表示要从用户空间读取数据到内核空间
		ubuf:指向用户空间缓冲区的指针
		size:用户空间缓冲区的大小
		&iov:保存导入过程中的权限和偏移信息
		&msg.msg_iter:保存导入过程中的迭代状态信息*/
    if (unlikely(err))
        return err;

    sock = sockfd_lookup_light(fd, &err, &fput_needed);					// 根据给定的文件描述符fd在内核中查找对应的套接字(socket)
    if (!sock)
        goto out;
	
	/* 以下字段用于在进行套接字传输时指定相关的参数和选项 */
    msg.msg_control = NULL;  											// 不使用辅助数据(ancillary data),将消息控制信息置为 NULL
    msg.msg_controllen = 0;  											// 辅助数据长度为 0,即没有辅助数据
    msg.msg_name = addr ? (struct sockaddr *)&address : NULL;			// 根据条件判断是否需要设置目的地址。如果需要,将地址复制到用户空间
    msg.msg_namelen = 0;  												// 目的地址长度为 0,即不使用目的地址
    msg.msg_iocb = NULL;												// 不使用 I/O 控制块,将其置为 NULL
    msg.msg_flags = 0;													// 不设置任何标志
    
    if (sock->file->f_flags & O_NONBLOCK)								// 检查套接字文件描述符的状态是否为非阻塞模式O_NONBLOCK
        flags |= MSG_DONTWAIT;											// 如为非阻塞模式,则设置MSG_DONTWAIT标志,表示设置消息传输为非阻塞模式
    
    err = sock_recvmsg(sock, &msg, flags);								// 通过给定的套接字 sock接收数据和消息信息,并存到msg,返回接收到的字节数

    if (err >= 0 && addr != NULL) {										// 如果接收成功且需要返回地址信息,
        err2 = move_addr_to_user(&address,
									msg.msg_namelen, addr, addr_len);	// 则将地址信息复制到用户空间
        if (err2 < 0)
            err = err2;
    }
    
    fput_light(sock->file, fput_needed);								// 释放套接字引用计数
out:
    return err;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值