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

【C语言】SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)

一、SYSCALL_DEFINE3与系统调用

在Linux操作系统中,为了从用户空间跳转到内核空间执行特定的内核级操作,使用了一种机制叫做"系统调用"(System Call)。系统调用是操作系统提供给程序员访问和使用内核功能的接口。例如,要在文件系统中创建新文件、发送网络数据或分配内存等,都需要通过系统调用来完成。
SYSCALL_DEFINE3是一个Linux内核中用来定义接收三个参数的系统调用的宏。让我们深入理解一下这个过程。

宏 SYSCALL_DEFINE3

1. 名称: SYSCALL_DEFINE3是一个合成了名称中参数数量(在这个例子中是3)的宏,表示这个宏会处理一个有三个参数的系统调用。
2. 参数:
   - socket: 这是系统调用的名字。在用户空间,例如在C语言中,我们可能使用类似`socket(…)`这样的调用。
   - int, family: 这是系统调用的第一个参数,它指定了socket的协议族。
   - int, type: 这是系统调用的第二个参数,它指定socket的类型。
   - int, protocol: 这是系统调用的第三个参数,它指定了在给定的协议族和类型下使用哪个协议。

系统调用的工作流程

1. 用户空间调用系统调用:
   程序员在用户空间程序(如C程序)中写下了一个系统调用,例如`socket(AF_INET, SOCK_STREAM, 0)`。
2. 转换为内核空间:
   当上述调用执行时,CPU切换到内核模式,这个过程通常涉及到生成一个软件中断(如x86架构的`int 0x80`指令,或者其他架构的类似机制),或者使用特定的系统调用指令(如x86-64架构的`syscall`)。
3. 系统调用分派:
   内核中有一个预先设置好的表(系统调用表),其中包括了所有系统调用对应的函数指针。执行软件中断时,会使用寄存器中的值(通常是一个系统调用号)来确定需要调用的具体函数。在x86-64架构上,这个系统调用号会被放在`RAX`寄存器中。然后系统调用表会返回对应的函数(例如`sys_socket`)。
4. 执行内核级函数:
   在这个例子中,内核会执行`__sys_socket`函数,这是内核中实现创建socket实际操作的私有函数。`__sys_scket`负责分配和设置必要的数据结构,以创建和配置一个新的socket。
5. 返回用户空间:
   一旦`__sys_socket`完成了它的工作,系统调用会返回到用户空间程序,通常携带一个值——file descriptor(文件描述符),这个值是新创建的socket的唯一标识。如系统调用执行成功,返回的是一个非负整数的文件描述符;如执行失败,就返回一个错误码(一般是-1)。

结论

通过使用宏如`SYSCALL_DEFINE3`,Linux内核的维护者可以轻松定义需要任何数量参数的系统调用,同时保持代码简洁和一致性。借助此宏能够将系统调用名称与实现细节脱钩,这样在系统调用实现或调度逻辑发生改变时,不需要对每个系统调用的定义都进行修改。

二、SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)

SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{return __sys_socket(family, type, protocol);
}

这行代码定义了一个Linux内核系统调用`socket`,其接收三个整型参数:`family`,`type`,和`protocol`。这个系统调用用来创建一个新的socket。
来逐个解释这些参数:
- family:指定了socket所使用的协议族。比如,`AF_INET`表示IPv4协议族,`AF_INET6`表示IPv6协议族,等等。
- type:指定了socket的类型,也就是通信的语义。例如,`SOCK_STREAM`表示提供顺序、可靠、双向、基于连接的字节流;`SOCK_DGRAM`表示提供数据报(一个小块的信息),它们可能会丢失或者重复,并可能不会按顺序到达。
- protocol:通常为零,让系统自动选择`family`和`type`组合的默认协议。例如,当使用`AF_INET`和`SOCK_STREAM`,默认协议是`IPPROTO_TCP`,即TCP协议。
函数名`SYSCALL_DEFINE3`是一个宏,用于定义接收三个参数的系统调用。这个宏展开后,会生成系统调用的实际实现,这里它定义了`socket`系统调用。
实现部分:`__sys_socket(family, type, protocol)`;
这是一个内核私有的函数,负责实现创建socket的逻辑。它简单地将任务委托给`__sys_socket`函数处理。这个函数会处理实际的socket创建工作,并返回一个文件描述符(file descriptor),这个文件描述符代表了新创建的socket。如果操作成功,这个文件描述符是一个非负整数;如果操作失败,则返回-1,并且设置相应的错误码。

三、int __sys_socket(int family, int type, int protocol)

int __sys_socket(int family, int type, int protocol)
{int retval;struct socket *sock;int flags;/* Check the SOCK_* constants for consistency.  */BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);flags = type & ~SOCK_TYPE_MASK;if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))return -EINVAL;type &= SOCK_TYPE_MASK;if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;retval = sock_create(family, type, protocol, &sock);if (retval < 0)return retval;return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
}

这段代码是一个内核函数的示例,用于创建一个新的socket。它包含了在进行网络编程时创建socket的一些基本步骤和错误检查。以下是代码的解释:
1. 函数声明: int __sys_socket(int family, int type, int protocol) 定义了一个叫做 __sys_socket 的函数,接受三个参数:`family` 表示socket的地址族(如AF_INET),`type` 表示socket的类型(如SOCK_STREAM或SOCK_DGRAM),`protocol` 表示使用的协议(如IPPROTO_TCP)。
2. 函数内的局部变量声明:
   - int retval; 用来存储函数调用的返回值。
   - struct socket *sock; 定义一个指向 socket 结构体的指针变量。
   - int flags; 用于存储类型中的标志位。
3. 常量检查: BUILD_BUG_ON 宏用来在编译时检查某些情况是否真实,如果条件为真,编译将失败。此处检查了几个有关Socket的常量设置是否一致,以确保在编译时没有逻辑错误。
4. 标志处理:
   - 该函数初期根据 type 参数中的标志位获取 flags。
   - 检查 flags 是否包含除了 SOCK_CLOEXEC 和 SOCK_NONBLOCK 外的其他标志,如果包含则返回错误值 -EINVAL(表示参数无效)。
   - 然后,剔除 type 中的标志位,将其仅留下socket类型标志。
5. 非阻塞标志转换:
   - 如果 SOCK_NONBLOCK 和 O_NONBLOCK 不相同,但 flags 中的 SOCK_NONBLOCK 被设置了,那么就将 flags 中的 SOCK_NONBLOCK 转换为 O_NONBLOCK。
6. 创建socket:
   - 使用 sock_create 函数尝试创建一个socket,传入`family`, type, protocol 和一个指向 socket 结构体指针的地址。
   - 如果创建失败(即返回值小于0),则直接返回错误的返回值。
7. 返回文件描述符:
   - 如果socket创建成功,会使用 sock_map_fd 函数将socket映射到一个文件描述符,同时将 flags 中的 O_CLOEXEC 和 O_NONBLOCK 标志传递给该函数。
   - 函数最终返回一个文件描述符,该描述符可以用于后续的socket操作。

四、int __sock_create(struct net *net, int family, int type, int protocol, struct socket **res, int kern)

int __sock_create(struct net *net, int family, int type, int protocol,struct socket **res, int kern)
{int err;struct socket *sock;const struct net_proto_family *pf;// 确认传入的协议族 `family` 是否在有效范围中if (family < 0 || family >= NPROTO)return -EAFNOSUPPORT;// 确认传入的套接字类型 `type` 是否在有效范围中if (type < 0 || type >= SOCK_MAX)return -EINVAL;// 废弃的兼容性代码。如使用了SOCK_PACKET,将其转换为PF_PACKETif (family == PF_INET && type == SOCK_PACKET) {pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",current->comm);family = PF_PACKET;}// 安全模块检查创建套接字请求是否允许err = security_socket_create(family, type, protocol, kern);if (err)return err;// 为套接字分配内存sock = sock_alloc();if (!sock) {net_warn_ratelimited("socket: no more sockets\n");return -ENFILE; // 返回文件句柄不足的错误}sock->type = type;// 尝试加载协议族相关的模块(如果需要)if (rcu_access_pointer(net_families[family]) == NULL)request_module("net-pf-%d", family); // 请求加载协议族对应的模块(如果需要)rcu_read_lock();pf = rcu_dereference(net_families[family]);err = -EAFNOSUPPORT;if (!pf)goto out_release;// 尝试获取协议族模块的引用计数,如果获取失败则释放资源if (!try_module_get(pf->owner))goto out_release;// 如果获取成功,则调用该协议族的create方法来完成套接字的创建rcu_read_unlock();err = pf->create(net, sock, protocol, kern);if (err < 0)goto out_module_put;// 如果套接字创建成功,增加套接字操作模块的引用计数,这样避免在使用期间模块被卸载if (!try_module_get(sock->ops->owner))goto out_module_busy;// 套接字创建完毕后,减少协议族模块的引用计数module_put(pf->owner);// 安全模块对新创建的套接字进行后处理err = security_socket_post_create(sock, family, type, protocol, kern);if (err)goto out_sock_release;// 创建成功,将结果赋值给输出参数 `res`*res = sock;return 0;out_module_busy:err = -EAFNOSUPPORT;
out_module_put:// 如果模块忙碌,清理并释放协议族模块的引用计数sock->ops = NULL;module_put(pf->owner);
out_sock_release:// 释放创建的套接字sock_release(sock);return err;out_release:// 释放读锁并释放套接字rcu_read_unlock();goto out_sock_release;
}
EXPORT_SYMBOL(__sock_create);

这段代码是一个内核函数 __sock_create,它用于在Linux内核中创建一个新的套接字。

这个函数定义了创建一个新套接字的流程,在网络编程中执行一个非常重要的角色。它主要执行以下步骤:
1. 检查是否传入了有效的 family(协议族,如IPv4或IPv6)和 type(套接字类型,如流或数据报)参数。如果参数超出了预定义的范围,函数会返回对应的错误码。
2. 旧版兼容性处理,如果使用的是PF_INET和SOCK_PACKET,就发出警告并将family改成PF_PACKET。
3. 调用安全模块中的 security_socket_create 函数来执行额外的安全检查。如果安全检查失败,它将返回一个错误码。
4. 尝试为新的套接字分配内存。如果没有足够的内存可供套接字使用,则返回一个错误码。
5. 如果上文中的某些协议家族尚不存在于 net_families 数组中(即该协议没有注册),则尝试动态加载对应的协议家族模块。
6. 获取对应的协议家族结构 pf,如果 pf 为NULL或无法获取其模块的引用,将释放资源并返回错误。
7. 如果协议模块的引用成功获取,则调用协议的 ->create 函数创建套接字。如果创建失败,释放相关资源并返回错误。
8. 协议族模块的作用已完成,模块引用计数减一。
9. 使用 security_socket_post_create 函数执行套接字创建后的安全检查,如果检查失败,进行资源清理并返回错误。
10. 如果一切顺利,将 sock 指针赋给输出参数 res,表示套接字创建成功,函数返回0。
异常处理标签 out_module_busy、`out_module_put`、`out_sock_release` 是用于错误发生时的资源清理工作。例如,释放套接字、减少模块引用计数等。
最后,`EXPORT_SYMBOL` 宏将 __sock_create 函数导出,这允许其他内核模块调用这个函数。

五、rcu_read_lock和rcu_read_unlock

rcu_read_lock 和 rcu_read_unlock 是在Linux内核中使用的一对函数,它们被用来保护使用读-复制更新(Read-Copy Update, RCU)机制的数据结构。这个机制允许多个读者并行访问数据结构,而写者则能够在不阻塞读者的情况下修改数据结构。
rcu_read_lock 的作用:
当一个内核线程调用 rcu_read_lock,它标记了一个临界区开始,这个临界区内的读者可以安全地读取RCU保护的数据结构,即使有其他线程正在更改这些数据结构。`rcu_read_lock` 通常不会阻塞调用它的线程,并且它并不保护数据结构免受更改,而是确保在临界区内读取的数据结构在读取时是一致的。在这个临界区内,任何持续对数据结构的更新操作都不会被看到,这保证了数据结构的读取视图是一致的。
rcu_read_unlock 的作用:
rcu_read_unlock 标记了RCU读临界区的结束。它告诉内核,线程已经完成对RCU保护数据的读取,在此之后对数据结构的更改可能对该线程可见。在`rcu_read_unlock` 调用之后,线程不再保证能访问之前RCU保护的数据结构的一致视图。
使用这对函数可以提高并发性能,因为它们消除了传统锁机制造成的读者与写者之间的竞争,允许大量并行的读取操作,而不会与可能并发发生的写入操作冲突。然而,写入操作需要使用专门的RCU API来确保数据结构的更改能够被安全地发布给未来的读者。

六、static int sock_map_fd(struct socket *sock, int flags)

这个函数`sock_map_fd`是一个静态函数,它的主要作用是把一个已创建的套接字(struct socket)映射到一个文件描述符上。以下是该函数的步骤和解释:

static int sock_map_fd(struct socket *sock, int flags)
{struct file *newfile; // 定义一个用于文件描述符的指针变量int fd = get_unused_fd_flags(flags); // 获取一个未使用的文件描述符if (unlikely(fd < 0)) { // 如果获取失败(例如因为没有可用描述符)sock_release(sock); // 释放之前分配的socket资源return fd; // 返回错误码(负值)}newfile = sock_alloc_file(sock, flags, NULL); // 为socket分配一个file结构if (likely(!IS_ERR(newfile))) { // 如果分配成功fd_install(fd, newfile); // 把这个新的file结构和之前获得的描述符fd关联起来return fd; // 返回这个新的文件描述符}put_unused_fd(fd); // 如果分配失败,则释放之前获得的文件描述符return PTR_ERR(newfile); // 返回对应的错误码
}

函数首先通过调用`get_unused_fd_flags(flags)`获得一个未被使用的文件描述符(fd)。如果无法获得有效的文件描述符(例如所有的描述符都已被占用),该函数使用`sock_release(sock)`来释放套接字资源,并且返回一个错误码。
如果成功获取到一个有效的文件描述符,函数接着会尝试使用`sock_alloc_file(sock, flags, NULL)`来为套接字分配一个对应的`file`结构体。如果这个分配过程成功则没有出错,它会将这个新的`file`结构体和之前获得的文件描述符关联起来,使用`fd_install(fd, newfile)`完成这个操作。
如果`file`结构体分配失败(例如内存不足),函数会释放之前获得的文件描述符`fd`,使用`put_unused_fd(fd)`,并返回分配`file`时的错误码。
最后,如果所有操作都成功了,这个函数会返回一个正整数,它是新创建的可以用于操作套接字的文件描述符。如果操作失败,它会返回一个错误码用来表示具体何种错误发生。

相关文章:

【C语言】SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)

一、SYSCALL_DEFINE3与系统调用 在Linux操作系统中&#xff0c;为了从用户空间跳转到内核空间执行特定的内核级操作&#xff0c;使用了一种机制叫做"系统调用"&#xff08;System Call&#xff09;。系统调用是操作系统提供给程序员访问和使用内核功能的接口。例如&…...

C++实现鼠标点击和获取鼠标位置(编译环境visual studio 2022)

1环境说明 2获取鼠标位置的接口 void GetMouseCurPoint() {POINT mypoint;for (int i 0; i < 100; i){GetCursorPos(&mypoint);//获取鼠标当前所在位置printf("% ld, % ld \n", mypoint.x, mypoint.y);Sleep(1000);} } 3操作鼠标左键和右键的接口 void Mo…...

Matplotlib绘制炫酷散点图:从二维到三维,再到散点图矩阵的完整指南与实战【第58篇—python:Matplotlib绘制炫酷散点图】

文章目录 Matplotlib绘制炫酷散点图&#xff1a;二维、三维和散点图矩阵的参数说明与实战引言二维散点图三维散点图散点图矩阵二维散点图进阶&#xff1a;辅助线、注释和子图三维散点图进阶&#xff1a;动画效果和交互性散点图矩阵进阶&#xff1a;调整样式和添加密度图总结与展…...

Docker-Learn(一)使用Dockerfile创建Docker镜像

1.创建并运行容器 编写Dockerfile&#xff0c;文件名字就是为Dockerfile 在自己的工作工作空间当中新建文件&#xff0c;名字为Docerfile vim Dockerfile写入以下内容&#xff1a; # 使用一个基础镜像 FROM ubuntu:latest # 设置工作目录 WORKDIR /app # 复制当前目…...

问题:银行账号建立以后,一般需要维护哪些设置,不包括() #学习方法#经验分享

问题&#xff1a;银行账号建立以后&#xff0c;一般需要维护哪些设置&#xff0c;不包括&#xff08;&#xff09; A&#xff0e;维护结算科目对照 B&#xff0e;期初余额初始化刷 C&#xff0e;自定义转账定义 D&#xff0e;对账单初始化 参考答案如图所示...

教授LLM思考和行动:ReAct提示词工程

ReAct&#xff1a;论文主页 原文链接&#xff1a;Teaching LLMs to Think and Act: ReAct Prompt Engineering 在人类从事一项需要多个步骤的任务时&#xff0c;而步骤和步骤之间&#xff0c;或者说动作和动作之间&#xff0c;往往会有一个推理过程。让LLM把内心独白说出来&am…...

FPGA_工程_按键控制的基于Rom数码管显示

一 信号 框图&#xff1a; 其中 key_filter seg_595_dynamic均为已有模块&#xff0c;直接例化即可使用&#xff0c;rom_8*256模块&#xff0c;调用rom ip实现。Rom_ctrl模块需要重新编写。 波形图&#xff1a; 二 代码 module key_fliter #(parameter CNT_MAX 24d9_999_99…...

WordPress Plugin HTML5 Video Player SQL注入漏洞复现(CVE-2024-1061)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 0x02 漏洞概述 WordPress Plugin HTML5 Video Player 插件 get_v…...

【Kotlin】Kotlin基本数据类型

1 变量声明 var a : Int // 声明整数类型变量 var b : Int 1 // 声明整数类型变量, 同时赋初值为1 var c 1 // 声明整数类型变量, 同时赋初值为1 val d 1 // 声明整数类型常量, 值为1(后面不能改变d的值) 变量命名规范如下。 变量名可以由字母、数字、下划线&#xff08;_…...

UDP端口探活的那些细节

一 背景 商业客户反馈用categraf的net_response插件配置了udp探测, 遇到报错了&#xff0c;如图 udp是无连接的&#xff0c;无法用建立连接的形式判断端口。 插件最初的设计是需要配置udp的发送字符&#xff0c;并且配置期望返回的字符串&#xff0c; [[instances]] targets…...

拦截器配置,FeignClient根据业务规则实现微服务动态路由

文章目录 业务场景拦截器用法Open Feign介绍 业务场景 我们服务使用Spring Cloud微服务架构&#xff0c;使用Spring Cloud Gateway 作为网关&#xff0c;使用 Spring Cloud OpenFeign 作为服务间通信方式我们现在做的信控平台&#xff0c;主要功能之一就是对路口信号机进行管控…...

预测模型:MATLAB线性回归

1. 线性回归模型的基本原理 线性回归是统计学中用来预测连续变量之间关系的一种方法。它假设变量之间存在线性关系&#xff0c;可以通过一个或多个自变量&#xff08;预测变量&#xff09;来预测因变量&#xff08;响应变量&#xff09;的值。基本的线性回归模型可以表示为&…...

【人工智能】神奇的Embedding:文本变向量,大语言模型智慧密码解析(10)

什么是嵌入&#xff1f; OpenAI 的文本嵌入衡量文本字符串的相关性。嵌入通常用于&#xff1a; Search 搜索&#xff08;结果按与查询字符串的相关性排序&#xff09;Clustering 聚类&#xff08;文本字符串按相似性分组&#xff09;Recommendations 推荐&#xff08;推荐具有…...

Redis + Lua 实现分布式限流器

文章目录 Redis Lua 限流实现1. 导入依赖2. 配置application.properties3. 配置RedisTemplate实例4. 定义限流类型枚举类5. 自定义注解6. 切面代码实现7. 控制层实现8. 测试 相比 Redis事务&#xff0c; Lua脚本的优点&#xff1a; 减少网络开销&#xff1a;使用Lua脚本&…...

ruoyi若依框架SpringSecurity实现分析

系列文章 ruoyi若依框架学习笔记-01 ruoyi若依框架分页实现分析 ruoyi若依框架SpringSecurity实现分析 文章目录 系列文章前言具体分析一、项目中的SpringSecurity版本二、登录认证流程分析三、权限鉴定四、退出登录五、SpringSecurity配置类 总结 前言 在ruoyi-vue若依框…...

Habitat环境学习四:Habitat-sim基础用于导航——使用导航网格NavMesh

如何使用导航网格NavMesh 官方教程1、NavMesh基础定义1.1 使用NavMesh的原因1.2 什么是NavMesh 2、NavMesh的使用方法2.1 获取自上而下Top down view视角地图2.2 在NavMesh中进行查询以及随机产生可导航点2.3 查找最短路径2.4 场景加载NavMesh2.5 重新计算并生成NavMesh2.6 什么…...

python学习笔记 -- 字符串

目录 一、输出字符串的格式 二、字符串的一些函数 1、len函数&#xff1a;字符串长度 2、查找字符所在位置index 3、某字符在字符串中的个数count 4、字符切片 对字符串进行翻转 -- 利用步长 5、修改大小写字母&#xff1a; 6、判断开头和结尾 7、拆分字符串 一、输出…...

2024年GPT如何发展?

2023 年&#xff0c;人工智能领域最具影响的莫过于 GPT-4、ChatGPT 了。 ChatGPT 凭一己之力掀起了 AI 领域的热潮&#xff0c;火爆全球&#xff0c;似乎开启了第四次工业革命。 ChatGPT 入选《Nature》2023 年度十大人物&#xff08;Nature’s 10&#xff09;&#xff0c;这…...

从REPR设计模式看 .NET的新生代类库FastEndpoints的威力

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !序言 又到了一年年末,春节将至…...

前端入门:(五)JavaScript 续

10. 浏览器存储 10.1 Cookie的概念和使用 Cookie是一种存储在用户计算机上的小型文本文件&#xff0c;用于跟踪和识别用户。Cookie通常用于存储用户的偏好设置、会话信息等&#xff0c;可以通过JavaScript进行读取和设置。 // 示例&#xff1a;设置和读取Cookie document.co…...

研究多态恶意软件,探讨网络安全与AI

前言 近期ChatGPT火遍全球&#xff0c;AI技术被应用到了全球各行各业当中&#xff0c;国内外各大厂商也开始推出自己的ChatGPT&#xff0c;笔者所在公司在前段时间也推出了自研的安全GPT&#xff0c;AI技术在网络安全行业得到了很多的应用&#xff0c;不管是网络安全研究人员、…...

linux驱动工作原理

linux或者windows驱动是如何对上和对下工作的&#xff0c;请用中文回答 在Linux系统中&#xff0c;设备驱动程序通过在/dev目录下创建文件系统条目与硬件通信。应用程序通过打开这些文件来获取描述符&#xff0c;以此来与设备交互。驱动程序内部使用主次设备号来标识设备。而在…...

Rust语言入门(第3篇)

引用与借用 上一篇中&#xff0c;我们介绍了rust的所有权概念&#xff0c;若直接传递变量做函数参数&#xff0c;堆上的变量就会失去所有权&#xff0c;而栈上变量则由于复制&#xff0c;仍有所有权。 fn main(){let b 3;makes_copy(b);println!("after using a variab…...

电脑服务器离线安装.net framework 3.5解决方案(错误:0x8024402c )(如何确定当前系统是否安装NET Framework 3.5)

问题环境&#xff1a; 日常服务的搭建或多或少都会有需要到NET Framework 3.5的微软程序运行框架&#xff0c;本次介绍几种不同的安装方式主要解决运行在Windows 2012 以上的操作系统的服务。 NET Framework 3.5 是什么&#xff1f; .NET Framework是微软公司推出的程序运行框架…...

Three.js学习8:基础贴图

一、贴图 贴图&#xff08;Texture Mapping&#xff09;&#xff0c;也翻译为纹理映射&#xff0c;“贴图”这个翻译更直观。 贴图&#xff0c;就是把图片贴在 3D 物体材质的表面&#xff0c;让它具有一定的纹理&#xff0c;来为 3D 物体添加细节的一种方法。这使我们能够添加…...

【Linux】进程学习(二):进程状态

目录 1.进程状态1.1 阻塞1.2 挂起 2. 进程状态2.1 运行状态-R进一步理解运行状态 2.2 睡眠状态-S2.3 休眠状态-D2.4 暂停状态-T2.5 僵尸状态-Z僵尸进程的危害 2.6 死亡状态-X2.7 孤儿进程 1.进程状态 1.1 阻塞 阻塞&#xff1a;进程因为等待某种条件就绪&#xff0c;而导致的…...

Spring Boot 笔记 003 Bean注册

使用Idea导入第三方jar包 在porn.xml种添加的第三方jar包依赖&#xff0c;并刷新 可以在启动类中尝试调用 以上放到启动类中&#xff0c;不推荐&#xff0c;建议创建一个专门定义的类 package com.geji.config;import cn.itcast.pojo.Country; import cn.itcast.pojo.Province;…...

PCIE 参考时钟架构

一、PCIe架构组件 首先先看下PCIE架构组件&#xff0c;下图中主要包括&#xff1a; ROOT COMPLEX (RC) (CPU); PCIE PCI/PCI-X Bridge; PCIE SWITCH; PCIE ENDPOINT (EP) (pcie设备); BUFFER; 各个器件的时钟来源都是由100MHz经过Buffer后提供。一个PCIE树上最多可以有256…...

【开源】JAVA+Vue.js实现在线课程教学系统

目录 一、摘要1.1 系统介绍1.2 项目录屏 二、研究内容2.1 课程类型管理模块2.2 课程管理模块2.3 课时管理模块2.4 课程交互模块2.5 系统基础模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示4.1 管理后台4.2 用户网页 五、样例代码5.1 新增课程类型5.2 网站登录5.3 课…...

计算机网络(第六版)复习提纲29

第六章&#xff1a;应用层 SS6.1 域名系统DNS 1 DNS被设计为一个联机分布式数据库系统&#xff0c;并采用客户服务器方式&#xff08;C/S&#xff09; 2 域名的体系结构 3 域名服务器及其体系结构 A 域名服务器的分类 1 根域名服务器 2 顶级域名服务器&#xff08;TLD服务器&a…...

有道ai写作,突破免费限制,无限制使用

预览效果 文末提供源码包及apk下载地址 有道ai写作python版 import hashlib import time import json import ssl import base64 import uuidfrom urllib.parse import quote import requests from requests_toolbelt.multipart.encoder import MultipartEncoder from Crypto…...

node.js 使用 elementtree 生成思维导图 Freemind 文件

请参阅: java : pdfbox 读取 PDF文件内书签 请注意&#xff1a;书的目录.txt 编码&#xff1a;UTF-8&#xff0c;推荐用 Notepad 转换编码。 npm install elementtree --save 编写 txt_etree_mm.js 如下 // 读目录.txt文件&#xff0c;使用 elementtree 生成思维导图 Free…...

Vue中路由守卫的详细应用

作为一名web前端开发者&#xff0c;我们肯定经常使用Vue框架来构建我们的项目。而在Vue中&#xff0c;路由是非常重要的一部分&#xff0c;它能够实现页面的跳转和导航&#xff0c;提供更好的用户体验。然而&#xff0c;有时我们需要在路由跳转前或跳转后执行一些特定的逻辑&am…...

Flink Checkpoint过程

Checkpoint 使用了 Chandy-Lamport 算法 流程 1. 正常流式处理&#xff08;尚未Checkpoint&#xff09; 如下图&#xff0c;Topic 有两个分区&#xff0c;并行度也为 2&#xff0c;根据奇偶数 我们假设任务从 Kafka 的某个 Topic 中读取数据&#xff0c;该Topic 有 2 个 Pa…...

【Java程序代理与系统代理关系】Java程序代理与系统代理关系优先级及覆盖关系

前言 使用Apache HttpClient工具包中的HttpClients.createDefault()方法创建的默认HTTP客户端会根据操作系统当前的设置来决定是否使用代理。 具体来说&#xff0c;当创建默认HTTP客户端时&#xff0c;它会检查系统的代理设置。如果操作系统当前设置了系统级代理&#xff0c;…...

MQ,RabbitMQ,SpringAMQP的原理与实操

MQ 同步通信 异步通信 事件驱动优势&#xff1a; 服务解耦 性能提升&#xff0c;吞吐量提高 服务没有强依赖&#xff0c;不担心级联失败问题 流量消峰 ​ 小结: 大多情况对时效性要求较高&#xff0c;所有大多数时间用同步。而如果不需要对方的结果&#xff0c;且吞吐…...

Vue 3 + Koa2 + MySQL 开发和上线部署个人网站

Vue 3 Koa2 MySQL 开发和上线部署个人网站 记录个人的一个操作步骤, 顺序不分先后, 嫌啰嗦请出门右转! 环境说明: 服务器: 阿里云轻量应用服务器 服务器系统: CentOS8.2 本地环境: macOS 12.7.2 Node: 20.10.0 MySQL: 8.0.26 Vue: 3.3.11 Koa: 2.7.0 pm2: 5.3.1 Nginx: 1.1…...

uniapp踩坑之项目:简易版不同角色显示不一样的tabbar和页面

1. pages下创建三个不同用户身份的“我的”页面。 显示第几个tabbar&#xff0c;0是管理员 1是财务 2是司机 2. 在uni_modules文件夹创建底部导航cc-myTabbar文件夹&#xff0c;在cc-myTabbar文件夹创建components文件夹&#xff0c;在components文件夹创建cc-myTabbar.vue组件…...

源支付V7开心1.9修复版,非网络上泛滥不能那种

源支付V7开心1.9修复版&#xff0c;非网络上泛滥不能那种 修复版源码&#xff0c;非网络泛滥版&#xff0c;防止源码泛滥&#xff0c;会员专属源码, 本站会员免费下载所有资源 注&#xff1a;开发不易&#xff0c;仅限交流学习使用&#xff0c;如商业使用&#xff0c;请支持正…...

Gitlab和Jenkins集成 实现CI (二)

Gitlab和Jenkins集成 实现CI (一) Gitlab和Jenkins集成 实现CI (二) Gitlab和Jenkins集成 实现CI (三) 配置Gitlab api token 配置 Gitlab 进入gitlab #mermaid-svg-t84fR8wrT4sB4raQ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:…...

Java:内部类、枚举、泛型以及常用API --黑马笔记

内部类 内部类是类中的五大成分之一&#xff08;成员变量、方法、构造器、内部类、代码块&#xff09;&#xff0c;如果一个类定义在另一个类的内部&#xff0c;这个类就是内部类。 当一个类的内部&#xff0c;包含一个完整的事物&#xff0c;且这个事物没有必要单独设计时&a…...

【持续更新】2024牛客寒假算法基础集训营3 题解 | JorbanS

A - 智乃与瞩目狸猫、幸运水母、月宫龙虾 string solve() {string a, b; cin >> a >> b;if (isupper(a[0])) a[0] a - A;if (isupper(b[0])) b[0] a - A;return a[0] b[0] ? yes : no; }B - 智乃的数字手串 string solve() {cin >> n;int cnt 0;for (…...

Java基于微信小程序的驾校报名小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

Android中AGP与Gradle、AS、JDK的版本关系

文章目录 AGP版本所要求的Gradle、JDK、SDK Build Tools最小版本Android Studio所要求的AGP最小版本 本文介绍了 在Android开发中由于AGP与gradle、JDK、AS等版本不匹配导致的编译失败问题屡见不鲜&#xff0c;尤其是对于新手而言更是叫苦不迭。新手经常遇到拿到别人的工程代码…...

web 前端实现一个根据域名的判断 来显示不同的logo 和不同的标题

1.需求 有可能我做一个后台 web端 我想实现一套代码的逻辑 显示不同的公司主题logo以及内容&#xff0c;但是实际上 业务逻辑一样 2.实现 建一个store oem.ts 这个名为是 oem系统 oem.ts import { defineStore } from pinia;import { store } from /store;const oemDataLis…...

复制和粘贴文本时剥离格式的5种方法(MacWindows)

您可能每天复制和粘贴多次。虽然它是一个非常方便的功能&#xff0c;但最大的烦恼之一就是带来了特殊的格式。从网络上获取一些文本&#xff0c;您经常会发现粘贴到文档中时&#xff0c;它保持原始样式。 我们将展示如何使用一些简单的技巧在不格式化的情况下复制和粘贴。 1.…...

SpringBoot实现即时通讯

SpringBoot实现即时通讯 功能简述 好友管理群组管理聊天模式&#xff1a;私聊、群聊消息类型&#xff1a;系统消息、文本、语音、图片、视频会话列表、发送消息、接收消息 核心代码 package com.qiangesoft.im.core;import com.alibaba.fastjson2.JSONObject; import com.q…...

【每日一题】LeetCode——反转链表

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…...

精通Python爬虫:掌握日志配置

源码分享 https://docs.qq.com/sheet/DUHNQdlRUVUp5Vll2?tabBB08J2 在开发Python爬虫时&#xff0c;日志记录是一个不可或缺的特性&#xff0c;它帮助我们捕捉运行时信息、调试代码和监控爬虫的健康状况。合理地配置日志系统是提高爬虫可维护性的关键。本篇技术博客将详细介绍…...

Python_百度贴吧评论情感分析

一、评论爬取 以百度贴吧中“美团骑手吧”为例&#xff0c;对页面中的帖子评论进行爬取&#xff0c;并将结果以json的格式保存到本地中。 from lxml import etree import requests import json# 根据网页url获取评论 def GetComments(url):# 使用requests库发送GET请求&#…...