【linux 多线程并发】线程属性设置与查看,绑定CPU,线程分离与可连接,避够多线程下的内存泄漏
线程属性设置
专栏内容:
参天引擎内核架构
本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。手写数据库toadb
本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。
本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,方便阶段学习。
开源贡献:
- toadb开源库
个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
文章目录
- 线程属性设置
- 前言
- 概述
- 线程属性
- 栈属性
- 栈地址
- 栈大小
- 栈保护区
- 调度属性
- 继承属性
- 调度策略属性
- 优先级属性
- 调度资源范围属性
- CPU亲和性属性
- 分离属性
- 信号属性
- 默认属性
- 总结
- 结尾
前言
现代的CPU都是多core处理器,而且在intel处理器中每个core又可以多个processor,形成了多任务并行处理的硬件架构,在服务器端的处理器上架构又有一些不同,传统的采用SMP,也就是对称的多任务处理架构,每个任务都可以对等的访问所有内存,外设等,而如今在ARM系列CPU上,多采用NUMA架构,它将CPU核分了几个组,给每个组的CPU core分配了对应的内存和外设,CPU访问对应的内存和外设时速度最优,跨组访问时性能会降底一些。
随着硬件技术的持续发展,它们对一般应用的性能优化能力越来越强,同时对于服务器软件的开发,提出更高要求,要想达到极高的并发和性能,就需要充分利用当前硬件架构的特点,对它们进行压榨。那么,我们的应用至少也是要采用多任务架构,不管是多线程还是多进程的多任务架构,才可以充分利用硬件的资源,达到高效的处理能力。
当然多任务框架的采用,不仅仅是多线程的执行,需要对多任务下带来的问题进行处理,如任务执行返回值获取,任务间数据的传递,任务执行次序的协调;当然也不是任务越多处理越快,要避免线程过多导致操作系统夯住,也要防止任务空转过快导致CPU使用率飙高。
本专栏主要介绍使用多线程与多进程模型,如何搭建多任务的应用框架,同时对多任务下的数据通信,数据同步,任务控制,以及CPU core与任务绑定等相关知识的分享,让大家在实际开发中轻松构建自已的多任务程序。
概述
前一篇博客介绍了创建线程的步骤和调用的接口,但是传递的参数都采用了默认值,其实线程有很多属性值可以进行设置,这样让多线程的应用运行更加的协调,充分利用硬件资源。
本文就来分享一下线程的属性,以及设置方法和接口,最后会分享一段示例代码看一下设置效果。
特点说明一下,这里分享的linux thread 库,是Native Posix Thread Library(NPTL),也就是符合posix的接口;为什么要强调这个呢,因为linux 下的线程库有好几种,各家实现都有一些差异,也会存在一些问题,而posix的这一套NTPL已经被大家广泛接受而大量使用,所以我们也以这套库为基础来介绍;编译时需要加-lptrhead或libpthread库引用。
线程属性
线程属性有很多,这里分类列举一下。
| 属性名 | 接口 | 描述 |
|---|---|---|
| 栈属性 | pthread_attr_getstack, pthread_attr_setstack | 设置栈地址和栈大小 |
| 栈地址 | pthread_attr_getstackaddr, pthread_attr_setstackaddr | 设置栈地址 |
| 栈大小 | pthread_attr_getstacksize, pthread_attr_setstacksize | 设置栈大小 |
| 堆栈保护区 | pthread_attr_getguardsize, pthread_attr_setguardsize | 设置堆栈保护区大小 |
| 分离状态 | pthread_attr_getdetachstate, pthread_attr_setdetachstate | 设置线程的可连接或分离 |
| 调度继承属性 | pthread_attr_getinheritsched, pthread_attr_setinheritsched | 是否继承调度属性的设置 |
| 调度优先级属性 | pthread_attr_getschedparam, pthread_attr_setschedparam | 调度优先级参数的设置 |
| 调度策略属性 | pthread_attr_getschedpolicy, pthread_attr_setschedpolicy | 调度策略属性的设置 |
| 调度资源的范围 | pthread_attr_getscope, pthread_attr_setscope | 设置调度资源的范围 |
| CPU 亲和性 | pthread_attr_getaffinity_np,pthread_attr_setaffinity_np | 设置线程运行时绑定的CPU core |
| 信号掩码 | pthread_attr_getsigmask_np, pthread_attr_setsigmask_np | 信号掩码设置 |
| 默认属性 | pthread_getattr_default_np, pthread_setattr_default_np | 设置为线程默认属性 |
| 获取属性 | pthread_getattr_np | 获取线程实际属性 |
主要分为四大类:
- 堆栈相关属性,设置栈大小和起始地址,还可以设置保护区,给越界留有缓冲区;
- 调度相关属性,CPU的绑定,调度策略等;
- 分离状态,对线程退出时,资源的回收方式的设置;
- 信号掩码设置,对线程级别的信号中断响应设置;
栈属性
| 属性名 | 接口 | 描述 |
|---|---|---|
| 栈属性 | pthread_attr_getstack, pthread_attr_setstack | 设置栈地址和栈大小 |
| 栈地址 | pthread_attr_getstackaddr, pthread_attr_setstackaddr | 设置栈地址 |
| 栈大小 | pthread_attr_getstacksize, pthread_attr_setstacksize | 设置栈大小 |
| 堆栈保护区 | pthread_attr_getguardsize, pthread_attr_setguardsize | 设置堆栈保护区大小 |
主要有四组接口,其中栈属性设置包括了对栈地址和栈大小的设置,所以这里只介绍下面三组接口。
栈地址
int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr, size_t stacksize);
int pthread_attr_getstack(pthread_attr_t *attr,void **stackaddr, size_t *stacksize);int pthread_attr_getstackaddr(const pthread_attr_t *restrict attr,void **restrict stackaddr);
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
设置线程栈的起始地址,我们知道栈的地址是从起始地址开始从大到小的增长,也就是向下连续的分配空间,如果该地址超出了分配的栈区域的最高地址,就会发生栈溢出。
不建议平常使用单独设置栈地址的功能 pthread_attr_setstackaddr,由于无法提供指定增长方向或栈范围的方法; 而pthread_attr_setstack中指定了起始地址和stacksize参数指定的栈的范围,可以分配连续的向下的区域。
栈大小
int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,size_t *restrict stacksize);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
常用的是对栈大小的设置,根据程序本身的特点,如并发线程多少,递归调用深度,分配大的结构体数据等情况,决定是否需要调整默认栈大小。
栈保护区
int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,size_t *restrict guardsize);
int pthread_attr_setguardsize(pthread_attr_t *attr,size_t guardsize);
出于以下两个原因,为应用程序提供了 guardsize 属性:
-
溢出保护可能会导致系统资源浪费。如果应用程序创建大量线程,并且已知这些线程永远不会溢出其栈,则可以关闭溢出保护区。通过关闭溢出保护区,可以节省系统资源。
-
线程在栈上分配大型数据结构时,可能需要较大的溢出保护区来检测栈溢出。
guardsize 参数提供了对栈指针溢出的保护。如果创建线程的栈时使用了保护功能,则实现会在栈的溢出端分配额外内存。此额外内存的作用与缓冲区一样,可以防止栈指针的栈溢出。如果应用程序溢出到此缓冲区中,这个错误可能会导致 SIGSEGV 信号被发送给该线程。
如果 guardsize 为零,则不会为线程提供溢出保护区。如果 guardsize 大于零,则会为每个使用 attr 创建的线程提供大小至少为 guardsize 字节的溢出保护区。缺省情况下,线程具有实现定义的非零溢出保护区。
允许合乎惯例的实现,将 guardsize 的值向上舍入为可配置的系统变量 PAGESIZE 的倍数。
调度属性
| 属性名 | 接口 | 描述 |
|---|---|---|
| 调度继承属性 | pthread_attr_getinheritsched, pthread_attr_setinheritsched | 是否继承调度属性的设置 |
| 调度优先级属性 | pthread_attr_getschedparam, pthread_attr_setschedparam | 调度优先级参数的设置 |
| 调度策略属性 | pthread_attr_getschedpolicy, pthread_attr_setschedpolicy | 调度策略属性的设置 |
| 调度资源的范围 | pthread_attr_getscope, pthread_attr_setscope | 设置调度资源的范围 |
| CPU 亲和性 | pthread_attr_getaffinity_np,pthread_attr_setaffinity_np | 设置线程运行时绑定的CPU core |
线程调度属性主要有以下几种:
- 继承属性
- 调度参数属性
- 调度策略属性
- CPU亲和性属性
继承属性
int pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched);
int pthread_attr_getinheritsched(pthread_attr_t *attr,int *inheritsched);
- inherit 值为
PTHREAD_INHERIT_SCHED表示新建的线程将继承创建者线程中定义的调度策略, 将忽略在 pthread_create() 调用中定义的所有调度属性。 - 如果使用缺省值
PTHREAD_EXPLICIT_SCHED,则将使用 pthread_create() 调用中的属性。
调度策略属性
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);
这里的策略支持三种取值:
当policy 取值为以下:
- SCHED_FIFO, 先来先服务;
- SCHED_RR, 时间片轮转;
- SCHED_OTHER, 普通策略;
前两种是realtime,实时系统的调度策略,一般不会使用,它们两个支持优先级的设置,范围是1-99;
第三种是用户线程默认的策略类型,在内核中的命名是SCHED_NORMAL, 不支持优先级设置,必须为0;
当然在SCHED_OTHER策略下的各用户线程之间可以通过调整nice值,进行优先级调整,它的范围为-20 - 19之间,越小优先级越高。
优先级属性
int pthread_attr_setschedparam(pthread_attr_t *attr,const struct sched_param *param);
int pthread_attr_getschedparam(pthread_attr_t *attr,struct sched_param *param);
调度参数在结构sched_param中定义,仅支持优先级参数设定。
优先级参数仅在支持的调度策略下设置才有效,在SCHED_OTHER, SCHED_IDLE, SCHED_BATCH这三种策略下,优先级必须设置为0;
在SCHED_FIFO, SCHED_RR这两种实时调度策略下,优先级范围为1-99,数字越大优先级越高;
新创建的线程以此优先级运行, 简单示例代码如下:
pthread_attr_t tattr;
int newprio;
sched_param param;/* set the priority; others are unchanged */
param.sched_priority = 10;/* set the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, ¶m);
调度资源范围属性
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);
int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope);
contentionscope的取值如下:
- PTHREAD_SCOPE_SYSTEM, 线程在抢占资源,与它竞争的线程是系统中的所有线程;
- PTHREAD_SCOPE_PROCESS, 线程在抢占资源时,与它竞争的线程是本进程创建的线程,优先级依赖与策略和优先级设定;
CPU亲和性属性
int pthread_attr_setaffinity_np(pthread_attr_t *attr,size_t cpusetsize, const cpu_set_t *cpuset);
int pthread_attr_getaffinity_np(pthread_attr_t *attr, size_t cpusetsize, cpu_set_t *cpuset);
参数说明
- cpusetsize, 是第三个参数的size, 也就是sizeof(cpu_set_t);
- cpuset, 指定CPU core的掩码,使用
CPU_ZERO(&set);和CPU_SET(numCpu, &set);两个宏来设定,numCpu指定绑定的core或thread编号,是整型数字;
参看机制的CPU 数量和core数量
[senllang@hatch example_03]$ lscpu | egrep -i 'core.*:|socket'
Thread(s) per core: 2
Core(s) per socket: 8
Socket(s): 1
这里有一个CPU,包含8个core,每个core可以有两个线程,那就是可以有16个掩码值,设置时编号从0-15;
有时CPU会采用NUMA架构,那么相关线程需要设置到同一个Node的CPU编号下。
分离属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
detachstate的取值如下:
- PTHREAD_CREATE_DETACHED, 创建分离状态的线程,此时不用关注线程退出时的资源回收;
- PTHREAD_CREATE_JOINABLE, 创建可连接状态的线程,线程退出时,需要使用pthread_join对线程资源回收;默认参数就是可连接状态的线程。
如果线程以PTHREAD_CREATE_JOINABLE创建后,没有时机调用pthread_join时,还可以调用pthread_detach 函数,将指定线程置为分离状态,这样系统会自动回收线程资源。
如果线程以PTHREAD_CREATE_JOINABLE创建后,没有调用pthread_join,会造成一定的内存泄漏,这里一定要注意。
信号属性
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>int pthread_attr_setsigmask_np(pthread_attr_t *attr,const sigset_t *sigmask);
int pthread_attr_getsigmask_np(const pthread_attr_t *attr,sigset_t *sigmask);
设置线程级别的信号掩码,也就是那些信号会被阻塞。
sigset_t 类型的操作,需要使用一组信号掩码操作函数
- int sigemptyset (sigset_t *set) ,清空信号掩码变量
- int sigfillset (sigset_t *set) , 填充所有信号掩码
- int sigaddset (sigset_t *set, int signum) ,将某个信号添加到掩码中
- int sigdelset (sigset_t *set, int signum) ,将某个信号从掩码中移除
- int sigismember (const sigset_t *set, int signum), 检测某个信号是否在掩码中
默认属性
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>int pthread_getattr_default_np(pthread_attr_t *attr);
int pthread_setattr_default_np(pthread_attr_t *attr);int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
前两个函数是将线程属性设置为默认值,也就是创建线程时,将线程属性设置为NULL,这两者是等价的。
第三个函数是获取指定线程的属性,可以在线程运行过程中获取线程属性。
总结
本文主要分享了线程属性相关的接口,以及部分属性的含义,如何正确使用;在应用编程时,大多数情况下都会采用多线程并发的架构,线程属性的正确使用,能够帮助我们有提高CPU的利用效率,同时在使用过程中避够资源泄漏也非常关键。
在gitCode上分享了工程hatchCode,会不断增加多线程并发的案例代码,请大家关注保留。
结尾
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
相关文章:
【linux 多线程并发】线程属性设置与查看,绑定CPU,线程分离与可连接,避够多线程下的内存泄漏
线程属性设置 专栏内容: 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况…...
70.乐理基础-打拍子-三连音
上一个内容:69.乐理基础-打拍子-大切分与变体-CSDN博客 62-66是总拍数为一拍的节奏型,一共有七个,68-69是两拍的节奏型。 三连音说明: 1.三连音的总拍数可以是一拍、两拍、四拍。。。。 2.打拍子比较难,或许需要用V字…...
100天精通Python(实用脚本篇)——第111天:批量将PDF转Word文档(附上脚本代码)
文章目录 专栏导读1. 将PDF转Word文档需求2. 模块安装3. 模块介绍4. 注意事项5. 完整代码实现6. 运行结果书籍推荐 专栏导读 🔥🔥本文已收录于《100天精通Python从入门到就业》:本专栏专门针对零基础和需要进阶提升的同学所准备的一套完整教…...
如何在 NAS 上安装 ONLYOFFICE 文档?
文章作者:ajun 导览 ONLYOFFICE 文档 是一款开源办公套件,其是包含文本文档、电子表格、演示文稿、表单、PDF 查看器和转换工具的协作性编辑工具。它高度兼容微软 Office 格式,包括 .docx、.xlsx 、.pptx 、pdf等文件格式,并支持…...
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的图像剪切(ROI)功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的图像剪切(ROI)功能(C) Baumer工业相机Baumer工业相机的图像剪切(ROI)功能的技术背景CameraExplorer如何使用图像剪切(ROI)功…...
从 WasmEdge 运行环境读写 Rust Wasm 应用的时序数据
WebAssembly (Wasm) 正在成为一个广受欢迎的编译目标,帮助开发者构建可迁移平台的应用。最近 Greptime 和 WasmEdge 协作,支持了在 WasmEdge 平台上的 Wasm 应用通过 MySQL 协议读写 GreptimeDB 中的时序数据。 什么是 WebAssembly WebAssembly 是一种…...
算法训练营Day34(贪心算法)
1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣(LeetCode) 秒了 class Solution {public int largestSumAfterKNegations(int[] nums, int k) {Arrays.sort(nums);// -4 -3 -2 -1 5//-2 -2 0 2 5int last -1;for(int i 0;i<…...
uniapp:全局消息是推送,实现app在线更新,WebSocket,apk上传
全局消息是推送,实现app在线更新,WebSocket 1.在main.js中定义全局的WebSocket2.java后端建立和发送WebSocket3.通知所有用户更新 背景: 开发人员开发后app后打包成.apk文件,上传后通知厂区在线用户更新app。 那么没在线的怎么办&…...
ARM1.2作业
实现数码管不同位显示不同的数字 spi.h #ifndef __SPI_H__ #define __SPI_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h"//MOSI对应的引脚输入高低电平的信号PE14 #define MOSI_OUTPUT_H() do{GPIOE->ODR | (0x1 << 14);}whi…...
【算法专题】递归算法
递归 递归1. 汉诺塔问题2. 合并两个有序链表3. 反转链表4. 两两交换链表中的节点5. Pow(x, n) --- 快速幂 递归 在解决⼀个规模为 n 的问题时,如果满足以下条件,我们可以使用递归来解决: 问题可以被划分为规模更小的子问题,并且…...
不停止业务的情况下优化 Elasticsearch Reindex
在使用 Elasticsearch 时,我们总有需要修改索引映射的时候,这时我们只能进行 _reindex。事实上,这是一个相当昂贵的操作,因为根据数据量和分片数量,完整复制一个索引可能需要几个小时。 花费的时间不是大问题,但更严重的是,它会影响生产环境的性能甚至功能。 相信大家…...
PB 按Excel动态创建对应字段
/* > Function: w_cwjk_xhyy.wf_dw_init >-------------------------------------------------------------------- > 描述: 按excel表格列名,创建对应字段,用于部分接口对应字段导出文件 >-------------------------------------------------------------------- …...
数据结构——红黑树 and B-树
红黑树 根据平衡条件第4、5两点 最短路径,都是黑色 最长路径,红黑相间 最长是最短的两倍 B-树...
Android中线程间的通信-Handler
Handler机制在Android中主要用于线程间的通信,特别是处理从子线程向主线程(UI线程)传递消息和更新界面。 Handler中的四个关键对象及其作用: Message: Message 是在线程间传递的数据载体,它包含了需要处理…...
Spring Boot Admin健康检查引起的Spring Boot服务假死
问题现象 最近在spring boot项目中引入了 spring-boot-starter-actuator 后,测试环境开始出现服务假死的现象, 且这个问题十分怪异,只在多个微服务中的简称A的这个服务中出现,其他服务都没有出现这个问题, 之所以说…...
java企业人事信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 java Web企业人事信息管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发,数据库为M…...
如何通过 useMemo 和 useCallback 提升你的 React 应用性能
背景 在 React 中,useMemo 和 useCallback 这两个 hook 是我们优化应用性能的有力工具。它们会返回 memoized 版本的值或函数,只在依赖项发生变化时才进行重新计算或定义。 Hook 介绍 useMemo useMemo 的作用是返回一个 memoized 值,它接…...
ArkTS - @Prop、@Link
一、作用 Prop 装饰器 和Link装饰器都是父组件向子组件传递参数,子组件接收父组件参数的时候用的,变量前边需要加上Prop或者Link装饰器即可。(跟前端vue中父组件向子组件传递参数类似) // 子组件 Component struct SonCom {Prop…...
Python中matplotlib库的使用1
1 matplotlib库简介 matplotlib是一个数学绘图库,可以将数据通过图形的方式显示出来,也就是数据可视化。 2 matplotlib库的安装 2.1 打开cmd窗口 点击键盘的“Win”“R”键,在弹出的“运行”对话框的“打开”栏中输入“cmd”,…...
位乘积计数-蓝桥
题目链接:1.位乘积计数 - 蓝桥云课 (lanqiao.cn) 解题思路:10的5次数量级暴力居然过了,看来测试样例很水,直接1遍历到n,再用一个循环判断每位数相乘乘机是否等于m即可。 下面是c代码: #include <iost…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
