当前位置: 首页 > news >正文

【C语言】Linux内核bind系统调用代码

一、Linux 4.9内核bind系统调用代码注释

int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
{struct socket *sock;                     // 定义socket对象的指针struct sockaddr_storage address;         // 用于存储从用户空间复制过来的地址int err, fput_needed;                    // 错误码和文件指针释放标志// 通过文件描述符获取socket对象,并检查是否需要释放文件指针sock = sockfd_lookup_light(fd, &err, &fput_needed);if (sock) {  // 如果获取socket对象成功// 将用户空间的socket地址复制到内核空间err = move_addr_to_kernel(umyaddr, addrlen, &address);if (err >= 0) {  // 如果地址复制成功// 进行安全检查,判断是否允许绑定操作err = security_socket_bind(sock, (struct sockaddr *)&address, addrlen);if (!err)  // 安全检查通过// 调用协议层的bind函数完成实际的绑定操作err = sock->ops->bind(sock, (struct sockaddr *)&address, addrlen);}// 根据fput_needed标志决定是否释放文件指针fput_light(sock->file, fput_needed);}return err;  // 返回操作结果
}// 定义bind系统调用
SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
{// 调用__sys_bind函数,并返回其结果return __sys_bind(fd, umyaddr, addrlen);
}

二、代码解释

这段代码来自较老的版本的Linux内核,是`bind`系统调用的实现,其作用是将一个本地地址绑定到一个socket上。在Linux网络编程中,`bind`函数用于指定socket的本地地址,通常用在服务端指定端口号。下面将逐段用中文解读这段代码:

int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
{

定义了函数`__sys_bind`,它接收三个参数:一个文件描述符`fd`,一个指向用户空间socket地址的指针`umyaddr`,以及地址的长度`addrlen`。

    struct socket *sock;struct sockaddr_storage address;int err, fput_needed;

定义几个局部变量:`sock`用于存储内核中的socket对象的指针,`address`用于临时存储socket地址信息,`err`用于记录错误代码,`fput_needed`用于标记是否需要释放文件指针。

    sock = sockfd_lookup_light(fd, &err, &fput_needed);

通过文件描述符`fd`获取对应的socket对象,并将该对象的地址存入`sock`。此外,记录任何查找错误到`err`,并设定是否需要释放文件指针到`fput_needed`。

    if (sock) {

如果成功获取到了socket对象(即`sock`不为NULL)。

        err = move_addr_to_kernel(umyaddr, addrlen, &address);

将用户空间中的socket地址`umyaddr`复制到内核空间中的`address`变量中,检查地址的有效性,如果成功则`err`为非负值。

        if (err >= 0) {err = security_socket_bind(sock,(struct sockaddr *)&address,addrlen);

如果地址成功移动到内核空间,接着进行安全检查,看是否允许bind操作。

            if (!err)err = sock->ops->bind(sock,(struct sockaddr *)&address, addrlen);}

如果通过了安全检查,调用对应协议的`bind`函数,以进行实际的绑定操作。

        fput_light(sock->file, fput_needed);

完成绑定操作后,根据之前记录的`fput_needed`变量的值来决定是否释放文件指针。

    }return err;
}

返回操作结果,如果`err`为0,则表示绑定成功;如果为负值,则表示绑定过程中出现了错误。
最后是`SYSCALL_DEFINE3`宏定义的`bind`函数,这是一个宏来方便地定义具有三个参数的系统调用,并最终调用`__sys_bind`来完成实际的工作:

SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
{return __sys_bind(fd, umyaddr, addrlen);
}

这部分定义了系统调用`bind`,接收三个参数,内部简单地调用了`__sys_bind`函数,并返回它的返回值。这个宏用于定义一个系统调用,它定义了一个名为bind的系统调用,该系统调用接受三个参数:fdumyaddraddrlenSYSCALL_DEFINE3宏会生成一个系统调用的实现,该实现会将参数从用户空间复制到内核空间,然后调用__sys_bind函数来处理请求。

总之,这段代码实现了bind系统调用,它允许用户空间程序将套接字与本地地址和端口号关联起来。在绑定过程中,还进行了必要的安全检查和地址结构体的复制操作。

http://www.lryc.cn/news/300073.html

相关文章:

  • Ubuntu下Anaconda+PyCharm搭建PyTorch环境
  • 酷开科技荣获“消费者服务之星”称号后的未来展望
  • UVA1449 Dominating Patterns 题解
  • 【C语言】数据结构#实现堆
  • AES加密中的CBC和ECB
  • 【C++】类和对象(四)
  • XGB-5: DART Booster
  • HiveSQL——不使用union all的情况下进行列转行
  • Python环境下基于指数退化模型和LSTM自编码器的轴承剩余寿命预测
  • 无人机竞赛视觉算法开发流程开源计划(询问大家意见)
  • DMA直接内存访问,STM32实现高速数据传输使用配置
  • Web安全研究(六)
  • python3 中try 异常调试 raise 异常抛出
  • Java中的序列化是什么?如何实现对象的序列化和反序列化?请解释Serializable接口的作用是什么?请解释transient关键字的作用是什么?为什么会使用它?
  • 二维差分---三维差分算法笔记
  • D. Divisible Pairs
  • 【教程】Kotlin语言学习笔记(二)——数据类型(持续更新)
  • react 插槽
  • Linux运用fork函数创建进程
  • Pytest测试技巧之Fixture:模块化管理测试数据
  • 设计模式-职责链模式Chain of Responsibility
  • 书生浦语大模型实战营-课程作业(3)
  • 考研英语单词25
  • 计算机网络——08应用层原理
  • 面试计算机网络框架八股文十问十答第五期
  • 拟合案例1:matlab积分函数拟合详细步骤及源码
  • 嵌入式软件设计入门:从零开始学习嵌入式软件设计
  • Educational Codeforces Round 135 (Rated for Div. 2)C. Digital Logarithm(思维)
  • 微信小程序介绍、账号申请、开发者工具目录结构详解及小程序配置
  • 数字的魅力之情有独钟的素数