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

【C语言】socketpair 的系统调用

一、 Linux 内核 4.19socketpair 的系统调用

SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,int __user *, usockvec)
{return __sys_socketpair(family, type, protocol, usockvec);
}

这段代码定义了一个名为 socketpair 的系统调用。系统调用是操作系统提供给用户程序的接口,允许用户程序请求内核提供的服务。下面解读这段代码:
1. 宏定义 SYSCALL_DEFINE4: 它是一个预处理器宏,用来定义一个带有四个参数的系统调用接口。这个宏展开后,会生成向操作系统注册 socketpair 系统调用所需的所有内核代码。
2. 参数 int, family: 定义了 socket 对的域,这表示网络通信的域。比如 AF_INET 用于 IPv4 通信,`AF_UNIX` 用于本地进程间通信。这个参数告诉内核应当使用哪种网络协议族来创建 socket 对。
3. 参数 int, type: 定义了 socket 对的类型。`SOCK_STREAM` 表示提供序列化的、可靠的、双向的、基于连接的字节流(类似 TCP)。`SOCK_DGRAM` 表示数据报文,用于无连接的消息传递(类似 UDP)。
4. 参数 int, protocol: 表明使用哪种具体的协议。通常情况下,当 family 和 type 已经确定时,`protocol` 可以被设置为 0 来自动选择默认协议。
5. 参数 int __user *, usockvec: 这是一个用户空间的整型数组指针,用来存放内核返回的两个 socket 文件描述符。这里的 __user 是一个类型说明符,用于标示该指针指向的是用户空间的内存,这是为了在内核空间和用户空间中传递数据而使用的一种安全措施。
函数体仅包含了一行代码,它直接调用了 __sys_socketpair 函数,这个函数是真正完成工作的内部函数。它接收上面的四个参数,创建一对相互连接的套接字(sockets),并将文件描述符通过 usockvec 返回给用户空间的程序。
该 socketpair 系统调用与 C 语言中的 socketpair 函数有直接关系。在用户空间编程中,当调用标准的 C 语言库函数 socketpair() 时,该库函数最终会使用一个系统调用来与内核通信,请求创建 socket 对。对于用户程序而言,`socketpair()` 函数是与 socketpair 系统调用的接口。C 函数只是内部对系统调用转换为用户空间的库函数调用,实际的工作是在内核中完成的。因此,这段代码是 socketpair 用户空间函数背后的内核实现。

二、linux内核4.9中的 __sys_socketpair函数

/**	Create a pair of connected sockets.*/int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
{struct socket *sock1, *sock2; // 定义两个socket结构体指针int fd1, fd2, err; // 分别用于存储文件描述符和错误码struct file *newfile1, *newfile2; // 对应两个socket的文件结构体指针int flags; // 标志位变量// 提取标志位并检查是否包含非法标志flags = type & ~SOCK_TYPE_MASK;if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))return -EINVAL;type &= SOCK_TYPE_MASK; // 保留有效的socket类型// 如果SOCK_NONBLOCK不与O_NONBLOCK相等,并且flags包含SOCK_NONBLOCK,则替换为O_NONBLOCKif (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;// 获取未用的文件描述符fd1fd1 = get_unused_fd_flags(flags);if (unlikely(fd1 < 0)) // 如果获取失败,返回错误码return fd1;// 获取未用的文件描述符fd2fd2 = get_unused_fd_flags(flags);if (unlikely(fd2 < 0)) { // 如果获取失败,清理fd1并返回错误码put_unused_fd(fd1);return fd2;}// 将文件描述符拷贝到用户空间err = put_user(fd1, &usockvec[0]);if (err) // 如果拷贝出错,跳转到错误处理goto out;err = put_user(fd2, &usockvec[1]);if (err) // 如果拷贝出错,跳转到错误处理goto out;// 创建第一个socketerr = sock_create(family, type, protocol, &sock1);if (unlikely(err < 0)) // 如果创建失败,跳转到错误处理goto out;// 创建第二个socketerr = sock_create(family, type, protocol, &sock2);if (unlikely(err < 0)) { // 如果创建失败,释放第一个socket并跳转到错误处理sock_release(sock1);goto out;}// 检查安全性限制err = security_socket_socketpair(sock1, sock2);if (unlikely(err)) { // 如果检查失败,释放两个socket并跳转到错误处理sock_release(sock2);sock_release(sock1);goto out;}// 使用socket操作集连接两个socketerr = sock1->ops->socketpair(sock1, sock2);if (unlikely(err < 0)) { // 如果操作失败,释放两个socket并跳转到错误处理sock_release(sock2);sock_release(sock1);goto out;}// 为两个socket分配文件结构体newfile1 = sock_alloc_file(sock1, flags, NULL);if (IS_ERR(newfile1)) { // 如果分配失败,保存错误码,释放第二个socket,跳转到错误处理err = PTR_ERR(newfile1);sock_release(sock2);goto out;}newfile2 = sock_alloc_file(sock2, flags, NULL);if (IS_ERR(newfile2)) { // 如果分配失败,保存错误码,释放第一个文件结构体,跳转到错误处理err = PTR_ERR(newfile2);fput(newfile1);goto out;}// 记录审计信息audit_fd_pair(fd1, fd2);// 安装两个文件描述符fd_install(fd1, newfile1);fd_install(fd2, newfile2);return 0; // 操作成功,返回0out: // 错误处理部分put_unused_fd(fd2); // 释放第二个文件描述符put_unused_fd(fd1); // 释放第一个文件描述符return err; // 返回错误码
}

这段代码是Linux内核中负责创建socket对(两个相互连接的socket)的系统调用`__sys_socketpair`的实现。下面是解读:
1. 定义了一些变量,包括两个socket结构体指针`sock1`和`sock2`,两个文件描述符`fd1`和`fd2`,一个错误码`err`,以及一个`newfile1`和`newfile2`文件结构体指针。
2. 通过`type & ~SOCK_TYPE_MASK`提取标志位,并检查是否有除了`SOCK_CLOEXEC`和`SOCK_NONBLOCK`之外的未知标志位,如果有,则返回错误`-EINVAL`。
3. 然后,将`type`限制为仅包含有效的socket类型。
4. 如果`SOCK_NONBLOCK`标志和`O_NONBLOCK`不是同一个值,并且`flags`中有`SOCK_NONBLOCK`,则替换为`O_NONBLOCK`标志。
5. 调用`get_unused_fd_flags`获取两个未使用的文件描述符`fd1`和`fd2`,如果获取失败,则返回对应的错误码。
6. 使用`put_user`功能将两个文件描述符复制到用户空间指定的数组。
7. 使用`sock_create`函数创建两个新的socket,如果这一步或者之后的步骤出错,则会进行清理并返回错误码。
8. 检查安全性相关的问题,如果`security_socket_socketpair`返回错误,则释放socket资源并跳转到错误处理。
9. 使用socket的操作集中的`socketpair`函数连接这两个socket,如果出错,则释放socket资源并跳转到错误处理。
10. 分别为这两个socket分配文件结构体`newfile1`和`newfile2`,这些文件结构体可以在文件系统中表示一个打开的文件。
11. 如果在分配文件结构体过程中出现错误,将错误保存在`err`中,并释放相应资源,然后跳转到错误处理。
12. 使用`audit_fd_pair`记录审计信息。
13. 使用`fd_install`将新的文件结构体安装到之前获取的文件描述符上,这使得这两个文件描述符实际上指向两个连接的socket。
14. 如果代码执行成功地到达这里,就返回0,表示socket对创建成功。
15. 如果在标签`out`下执行,表明过程中出现了错误,需要清理资源并放回未使用的文件描述符,然后返回错误码。

相关文章:

【C语言】socketpair 的系统调用

一、 Linux 内核 4.19socketpair 的系统调用 SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,int __user *, usockvec) {return __sys_socketpair(family, type, protocol, usockvec); } 这段代码定义了一个名为 socketpair 的系统调用。系统调用是操作…...

【论文精读】BERT

摘要 以往的预训练语言表示应用于下游任务时的策略有基于特征和微调两种。其中基于特征的方法如ELMo使用基于上下文的预训练词嵌入拼接特定于任务的架构&#xff1b;基于微调的方法如GPT使用未标记的文本进行预训练&#xff0c;并针对有监督的下游任务进行微调。 但上述两种策略…...

Codeforces Round 925 (Div. 3) - A、B、C、D、E

文章目录 前言A. Recovering a Small StringB. Make EqualC. Make Equal AgainD. Divisible PairsE. Anna and the Valentines Day Gift 前言 本篇博客是Codeforces Round 925周赛的A、B、C、D、E五题的题解 A. Recovering a Small String 可以通过sum的大小分为三种情况&#…...

快速部署MES源码/万界星空科技开源MES

什么是开源MES软件&#xff1f; 开源MES软件是指源代码可以免费获取、修改和分发的MES软件。与传统的商业MES软件相比&#xff0c;开源MES软件具有更高的灵活性和可定制性。企业可以根据自身的需求对软件进行定制化开发&#xff0c;满足不同生产环境下的特定需求。 开源MES软件…...

【Python网络编程之TCP三次握手】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python开发技术 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Python网络编程之[TCP三次握手] 代码见资源&#xff0c;效果图如下一、实验要求二、协议原理2.…...

【leetcode】深搜、暴搜、回溯、剪枝(C++)2

深搜、暴搜、回溯、剪枝&#xff08;C&#xff09;2 一、括号生成1、题目描述2、代码3、解析 二、组合1、题目描述2、代码3、解析 三、目标和1、题目描述2、代码3、解析 四、组合总和1、题目描述2、代码3、解析 五、字母大小写全排列1、题目描述2、代码3、解析 六、优美的排列1…...

鸿蒙开发-UI-图形-图片

鸿蒙开发-UI-组件 鸿蒙开发-UI-组件2 鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 文章目录 一、基本概念 二、图片资源加载 1. 存档图类型数据源 2.多媒体像素图 三、显示矢量图 四、图片…...

.NET Core WebAPI中使用Log4net记录日志

一、安装NuGet包 二、添加配置 // log4net日志builder.Logging.AddLog4Net("CfgFile/log4net.config");三、配置log4net.config文件 <?xml version"1.0" encoding"utf-8"?> <log4net><!-- Define some output appenders -->…...

Nginx配置php留档

好久没有用过php了&#xff0c;近几日配置nginxphp&#xff0c;留档。 安装 ubunt下nginx和php都可以使用apt安装&#xff1a; sudo apt install nginx php8 如果想安装最新的php8.2,则需要运行下面语句&#xff1a; sudo dpkg -l | grep php | tee packages.txt sudo add-…...

英语题不会怎么搜答案?分享五个支持答案和解析的工具 #学习方法#媒体

在大学的学习过程中&#xff0c;我们常常会遇到一些难以解决的问题&#xff0c;有时候甚至会感到束手无策。然而&#xff0c;如今的技术发展给我们提供了新的解决方案。搜题软件作为一种强大的学习工具&#xff0c;正在被越来越多的大学生所接受和使用。今天&#xff0c;我将为…...

Rust 数据结构与算法:4栈:用栈实现进制转换

2、进展转换 将十进制数转换为二进制表示形式的最简单方法是“除二法”&#xff0c;可用栈来跟踪二进制结果。 除二法 下面实现一个将十进制数转换为二进制或十六进制的算法&#xff0c;代码如下&#xff1a; #[derive(Debug)] struct Stack<T> {size: usize, // 栈大…...

树莓派4B(Raspberry Pi 4B)使用docker搭建阿里巴巴sentinel服务

树莓派4B&#xff08;Raspberry Pi 4B&#xff09;使用docker搭建阿里巴巴sentinel服务 由于国内访问不了docker hub&#xff0c;而国内镜像仓库又没有适配树莓派ARM架构的sentinel镜像&#xff0c;所以我们只能退而求其次——自己动手构建镜像。本文基于Ubuntu&#xff0c;Jav…...

Django视图

HttpRequests对象 利用http协议向服务器传参的4种途径 提取url特定部分&#xff0c;如/web/index/&#xff0c;可以通过在服务器端的路由中用正则表达式截取查询字符串&#xff0c;形如?key1value&keyvalue2&#xff0c;&#xff08;&#xff1f;前面是路由&#xff0c;…...

python基本语法

变量无需声明 Python 中的变量不需要声明。每个变量在使用前都必须赋值&#xff0c;变量赋值以后该变量才会被创建。 在 Python 中&#xff0c;变量就是变量&#xff0c;它没有类型&#xff0c;我们所说的"类型"是变量所指的内存中对象的类型。 len800 #整型变…...

app逆向-⽹络请求库rxjava2

文章目录 一、前言二、安装三、GET请求实现四、POST请求实现 一、前言 RxJava 2 是一个流行的 Java 库&#xff0c;用于使用可观察序列组合异步和基于事件的程序。它是原始 RxJava 库的重新实现&#xff0c;旨在更高效并且更适合于 Java 8 及更高版本。 RxJava 2 的主要特性包…...

Spring Boot 笔记 007 创建接口_登录

1.1 登录接口需求 1.2 JWT令牌 1.2.1 JWT原理 1.2.2 引入JWT坐标 1.2.3 单元测试 1.2.3.1 引入springboot单元测试坐标 1.2.3.2 在单元测试文件夹中创建测试类 1.2.3.3 运行测试类中的生成和解析方法 package com.geji;import com.auth0.jwt.JWT; import com.auth0.jwt.JWTV…...

java数据结构与算法刷题-----LeetCode594. 最长和谐子序列

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 子序列要尽可能长&#xff0c;并且最大值和最小值之间的差&#…...

数据分析基础之《pandas(6)—高级处理》

一、缺失值处理 1、如何处理nan 两种思路&#xff1a; &#xff08;1&#xff09;如果样本量很大&#xff0c;可以删除含有缺失值的样本 &#xff08;2&#xff09;如果要珍惜每一个样本&#xff0c;可以替换/插补&#xff08;计算平均值或中位数&#xff09; 2、判断数据是否…...

IOS破解软件安装教程

对于很多iOS用户而言&#xff0c;获取软件的途径显得较为单一&#xff0c;必须通过App Store进行下载安装。 这样的限制&#xff0c;时常让人羡慕安卓系统那些自由下载各类版本软件的便捷。 心中不禁生出疑问&#xff1a;难道iOS世界里&#xff0c;就不存在所谓的“破解版”软件…...

[缓存] - 1.缓存共性问题

1. 缓存的作用 为什么需要缓存呢&#xff1f;缓存主要解决两个问题&#xff0c;一个是提高应用程序的性能&#xff0c;降低请求响应的延时&#xff1b;一个是提高应用程序的并发性。 1.1 高并发 一般来说&#xff0c; 如果 10Wqps&#xff0c;或者20Wqps &#xff0c;可使用分布…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...