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

「OC」源码学习——对象的底层探索

「OC」源码学习——对象的底层探索

前言

上次我们说到了源码里面的调用顺序,现在我们继续了解我们上一篇文章没有讲完的关于对象的内容函数,完整了解对象的产生对于isa赋值以及内存申请的内容

函数内容

先把_objc_rootAllocWithZone函数的内容先贴上来

static ALWAYS_INLINE id
_class_createInstance(Class cls, size_t extraBytes,int construct_flags = OBJECT_CONSTRUCT_NONE,bool cxxConstruct = true,size_t *outAllocatedSize = nil)
{ASSERT(cls->isRealized());//断言确保类已加载并完成内存布局(即 "realized" 状态)bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor(); //查看父类是否存在C++的析构函数bool hasCxxDtor = cls->hasCxxDtor();//查看是否存在C++的析构函数bool fast = cls->canAllocNonpointer();//是否支持指针优化size_t size;size = cls->instanceSize(extraBytes);//计算所需要的字节数if (outAllocatedSize) *outAllocatedSize = size;//返回计算的字节数id obj = objc::malloc_instance(size, cls);//根据类对象申请对应的内存if (slowpath(!obj)) {if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {return _objc_callBadAllocHandler(cls);}return nil;}if (fast) {obj->initInstanceIsa(cls, hasCxxDtor);//如果是优化的isa指针先进入进行判断再进入initIsa} else {// Use raw pointer isa on the assumption that they might be// doing something weird with the zone or RR.obj->initIsa(cls);}if (fastpath(!hasCxxCtor)) {return obj;//没有析构函数就可以直接返回了}construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;//添加一个flagreturn object_cxxConstructFromClass(obj, cls, construct_flags);
}

我们来看看instanceSize这个函数究竟实现了什么,按照instanceSize->fastInstanceSize->align16,依次步入,我们可以看到一下内容

static inline size_t align16(size_t x) {return (x + size_t(15)) & ~size_t(15);
}

这个程序就是一个16字节对齐的算法,先抛开这个算法,若是由我们来设计这个算法我们的思路是什么呢?最简单的就是

(x + 15) / 16 * 16

当然很快我们就意识到了,使用乘法和除法运算的效率和位运算相比实在太低了,正好16是2的4次方,位运算一样的解决啊

(x + 15) >> 4 << 4

OK现在设计完了我们在来看看苹果设计的代码

(x + 15) & ~15

~有按位取反的意思通过按位与操作,将低 4 位(二进制 1111)清零,得到最近的 16 的倍数。用size(15)是为了兼容32位和64机型,因为size_t 是无符号整数类型,其位数由平台决定(32 位系统为 4 字节,64 位系统为 8 字节)。当 xsize_t 类型时,size_t(15) 确保运算中的右操作数(15)与左操作数(x类型一致,避免隐式转换带来的风险

内存内容探究

GGObject *obj = [GGObject alloc];
NSLog(@"%lu", sizeof(obj));
NSLog(@"%lu", class_getInstanceSize(obj.class));
NSLog(@"%lu", malloc_size((__bridge const void*)(obj)));

根据这个内容我们可以看到自定义类对应的大小

image-20250424205643745

当我们的类被编译了之后,底层会类编译成 isa + 成员变量,所以在给类的实例分配内存的话这个内存块存储的就是 isa + 成员变量的值

内存对齐

学过C语言我们都知道,结构体是有内存对齐这个概念的,当然不同的排列所实现的内存对齐是不同的,例如

struct Mystruct1{char a;     //1字节double b;   //8字节int c;      //4字节short d;    //2字节
}Mystruct1;struct Mystruct2{double b;   //8字节int c;      //4字节short d;    //2字节char a;     //1字节
}Mystruct2;//计算 结构体占用的内存大小
NSLog(@"%lu-%lu",sizeof(Mystruct1),sizeof(Mystruct2));// 打印:24 - 16

结构体安排的顺序会关系到结构体内存的大小,我们知道OC之中的对象其实就是由结构体构成的,那我们来探究一下不同的属性对对象的内存是否有影响呢

内存重排

对象的本质 = isa + 成员变量的值。

#import <Foundation/Foundation.h>
@interface MyPerson : NSObject
// isa 8字节
@property (nonatomic, copy) NSString *name; // 8字节
@property (nonatomic, copy) NSString *hobby; // 8字节
@property (nonatomic, assign) int age; // 4字节
@property (nonatomic, assign) double height; // 8字节
@property (nonatomic, assign) short number; // 2字节
@end

一共38字节,16字节内存对齐得到总的字节数为48字节,在探究内存问题之前,先学几个lldb命令

lldb指令:p   输出10进制p/x 输出16进制p/0 输出8进制p/t 输出2进制p/f 输出浮点数x   输出地址x/4gx  输出4个字节地址x/6gx  输出6个字节地址

现在我们用lldb进行调试

 MyPerson *p = [GGObject alloc];p.name = @"bb";p.hobby = @"吃吃睡睡喝喝";p.height = 1.80;p.age = 26;p.number = 123;

其实尝试着将类之中的属性内容,打印出来可以看到,无论属性怎么排列,这个MyPerson类age和number这两个属性永远会排在一起,这个就是编译器的内存优化,对属性进行重排

image-20250425194336343

我们看到在类的内部,我们的属性会通过重新排列获得最小内存,接下来我们看看能能不能重排父类的属性和子类属性吧

image-20250425200345352

还是可以看到子类属性并不会跟父类属性合并

@interface JCTestObject : NSObject
{@publicint count;// 若count在此处,为JCTestSubObject实例实际需要40字节,系统为实例分配48字节NSObject *obj1;NSObject *obj2;
//    int count; // 若count在此处,为JCTestSubObject实例实际需要32字节,系统为实例分配32字节}
@end
@interface JCTestSubObject : JCTestObject
{@publicint count2;
}

isa走向

之前学习过关于isa指针的部分内容,

img

结论:

类的实例isa --> 类对象;
类对象isa --> 元类对象;
元类对象isa --> 根元类对象;
根元类对象isa --> 根元类对象自己。

objc_class 与 `objc_object

objc_object 是所有 Objective-C 对象的底层结构体,其定义如下

struct objc_object {isa_t isa;  // 指向类对象或元类的指针
};

objc_class 是类的底层结构体,类对象(如 [LGPerson class])和元类(metaclass)均为此类型。其继承自 objc_object,定义如下:

struct objc_class : objc_object {Class superclass;          // 父类指针cache_t cache;             // 方法缓存(哈希表)class_data_bits_t bits;    // 指向类信息(如方法列表、属性等)
};

1

img

class_getClassMethodclass_getInstanceMethod

先定义模版类

@interface JCObject : NSObject
{int _sum;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) double height;
@property (nonatomic, assign) short number;
- (void)speak;
- (void)sayHello;
+ (void)walk;
@end@implementation JCObject- (void)speak {NSLog(@"%s", __func__);
}
+ (void)walk {NSLog(@"%s", __func__);
}-(void) sayHello {NSLog(@"%s", __func__);
}

在完成两个函数

void jcInstanceMethod_classToMetaclass(Class pClass){const char *className = class_getName(pClass);Class metaClass = objc_getMetaClass(className);Method method1 = class_getInstanceMethod(pClass, @selector(speak));Method method2 = class_getInstanceMethod(metaClass, @selector(speak));Method method3 = class_getInstanceMethod(pClass, @selector(walk));Method method4 = class_getInstanceMethod(metaClass, @selector(walk));NSLog(@"%s - %p-%p-%p-%p",__func__,method1,method2,method3,method4);
}void jcClassMethod_classToMetaclass(Class pClass){const char *className = class_getName(pClass);Class metaClass = objc_getMetaClass(className);Method method1 = class_getClassMethod(pClass, @selector(speak));Method method2 = class_getClassMethod(metaClass, @selector(speak));Method method3 = class_getClassMethod(pClass, @selector(walk));Method method4 = class_getClassMethod(metaClass, @selector(walk));NSLog(@"%s-%p-%p-%p-%p",__func__,method1,method2,method3,method4);
}//main函数
JCObject *person = [JCObject alloc];
Class pClass = object_getClass(person);
jcObjc_copyMethodList(pClass);
jcInstanceMethod_classToMetaclass(pClass);
jcClassMethod_classToMetaclass(pClass);

得到的结果

image-20250502230010829

jcInstanceMethod_classToMetaclass

要了解jcInstanceMethod_classToMetaclass之中的内容就要从理解class_getInstanceMethod开始,顾名思义class_getInstanceMethod这个方法,主要是用于获取实例方法,如果在传入的类或者类的父类中没有找到指定的实例方法,则返回NULL。从实例方法存储在类中,类方法存储在元类中可以得知,JCObject的方法列表打印结果只有sayHello方法

jcClassMethod_classToMetaclass

需要先了解class_getClassMethod这个方法,看该方法的源码实现,可以得出class_getClassMethod的实现是获取类的类方法,其本质就是获取元类的实例方法,最终还是会走到class_getInstanceMethod

//获取类方法
Method class_getClassMethod(Class cls, SEL sel)
{if (!cls  ||  !sel) return nil;return class_getInstanceMethod(cls->getMeta(), sel);
}⬇️
//获取元类
//在getMeta源码中,如果判断出cls是元类,那么就不会再继续往下递归查找,会直接返回this,其目的是为了防止元类的无限递归查找
Class getMeta() {if (isMetaClass()) return (Class)this;else return this->ISA();
}

img

所以我们再来看看结果

对于speak方法存在于类对象之中,而walk方法存在于元类对象之中,所以使用class_getInstanceMethod可以在类对象之中找到speak方法,而在元类对象之中找到walk的类方法

而对于class_getClassMethod来说如果不是元类会先找到元类,然后再在元类之中查找类方法

iskindOfClass & isMemberOfClass

  • iskindOfClass & isMemberOfClass 类方法调用
//-----使用 iskindOfClass & isMemberOfClass 类方法
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];       //
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];     //
BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];       //
BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];     //
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
  • iskindOfClass & isMemberOfClass 实例方法调用
//------iskindOfClass & isMemberOfClass 实例方法
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];       //
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];     //
BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];       //
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];     //
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);

img

  • isKindOfClass
    检查对象是否属于指定类或其继承链中的任意父类。例如,若对象是 Person 类的子类实例(如 Student),则 [student isKindOfClass:[Person class]] 返回 YES
//--isKindOfClass---类方法、对象方法
//+ isKindOfClass:第一次比较是 获取类的元类 与 传入类对比,再次之后的对比是获取上次结果的父类 与 传入 类进行对比
+ (BOOL)isKindOfClass:(Class)cls {// 获取类的元类 vs 传入类// 根元类 vs 传入类// 根类 vs 传入类// 举例:LGPerson vs 元类 (根元类) (NSObject)for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {if (tcls == cls) return YES;}return NO;
}//- isKindOfClass:第一次是获取对象类 与 传入类对比,如果不相等,后续对比是继续获取上次 类的父类 与传入类进行对比
- (BOOL)isKindOfClass:(Class)cls {
/*
获取对象的类 vs 传入的类 
父类 vs 传入的类
根类 vs 传入的类
nil vs 传入的类
*/for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {if (tcls == cls) return YES;}return NO;
}
  • isMemberOfClass
    严格检查对象是否直接属于指定类,不包含继承链。例如,Student 实例调用 isMemberOfClass:[Person class] 会返回 NO,因为其直接类是 Student 而非 Person
//-----类方法
//+ isMemberOfClass : 获取类的元类,与 传入类对比
+ (BOOL)isMemberOfClass:(Class)cls {return self->ISA() == cls;
}
//-----实例方法
//- isMemberOfClass : 获取对象的类,与 传入类对比
- (BOOL)isMemberOfClass:(Class)cls {return [self class] == cls;
}

参考文章

iOS-底层原理 09:类 & isa 经典面试题分析

相关文章:

「OC」源码学习——对象的底层探索

「OC」源码学习——对象的底层探索 前言 上次我们说到了源码里面的调用顺序&#xff0c;现在我们继续了解我们上一篇文章没有讲完的关于对象的内容函数&#xff0c;完整了解对象的产生对于isa赋值以及内存申请的内容 函数内容 先把_objc_rootAllocWithZone函数的内容先贴上…...

从0开始学习大模型--Day01--大模型是什么

初识大模型 在平时遇到问题时&#xff0c;我们总是习惯性地去运用各种搜索引擎如百度、知乎、CSDN等平台去搜索答案&#xff0c;但由于搜索到的内容质量参差不齐&#xff0c;检索到的内容只是单纯地根据关键字给出内容&#xff0c;往往看了几个网页都找不到答案&#xff1b;而…...

202533 | SpringBoot集成RocketMQ

SpringBoot集成RocketMQ极简入门 一、基础配置&#xff08;3步完成&#xff09; 添加依赖 <!-- pom.xml --> <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version&g…...

大模型学习专栏-导航页

概要 本专栏是小编系统性调研大模型过程中沉淀的知识结晶&#xff0c;涵盖技术原理、实践应用、前沿动态等多维度内容。为助力读者高效学习&#xff0c;特整理此导航页&#xff0c;以清晰脉络串联核心知识点&#xff0c;搭建起系统的大模型学习框架&#xff0c;助您循序渐进掌握…...

互联网大厂Java面试:从Java SE到微服务的全栈挑战

场景概述 在这场面试中&#xff0c;谢飞机&#xff0c;一个搞笑但有些水的程序员&#xff0c;面对的是一位严肃的大厂面试官李严。面试官的目的是考察谢飞机在Java全栈开发&#xff0c;特别是微服务架构中的技术能力。面试场景设定在内容社区与UGC领域&#xff0c;模拟一个社交…...

2024年408真题及答案

2024年计算机408真题 2024年计算机408答案 2024 408真题下载链接 2024 408答案下载链接...

【datawhaleAI春训营】楼道图像分类

目录 图像分类任务的一般处理流程为什么使用深度学习迁移学习 加载实操环境的库加载数据集&#xff0c;默认data文件夹存储数据将图像类别进行编码自定义数据读取加载预训练模型模型训练&#xff0c;验证和预测划分验证集并训练模型 修改baseline处理输入数据选择合适的模型Ale…...

Unity:输入系统(Input System)与持续检测键盘按键(Input.GetKey)

目录 Unity 的两套输入系统&#xff1a; &#x1f50d; Input.GetKey 详解 &#x1f3af; 对比&#xff1a;常用的输入检测方法 技术底层原理&#xff08;简化版&#xff09; 示例&#xff1a;角色移动 为什么会被“新输入系统”替代&#xff1f; Unity 的两套输入系统&…...

day04_计算机常识丶基本数据类型转换

计算机常识 计算机如何存储数据 计算机底层只能识别二进制。计算机底层只识别二进制是因为计算机内部的电子元件只能识别两种状态&#xff0c;即开和关&#xff0c;或者高电平和低电平。二进制正好可以用两种状态来表示数字和字符&#xff0c;因此成为了计算机最基本的表示方…...

rvalue引用()

一、先确定基础:左值(Lvalue)和右值(Rvalue) 理解Rvalue引用,首先得搞清楚左值和右值的概念。 左值(Lvalue):有明确内存地址的表达式,可以取地址。比如变量名、引用等。 复制代码 int a = 10; // a是左值 int& ref = a; // ref也是左值右值(Rval…...

【Web3】上市公司利用RWA模式融资和促进业务发展案例

香港典型案例 朗新科技&#xff08;充电桩RWA融资&#xff09; 案例概述&#xff1a;2024年8月&#xff0c;朗新科技与蚂蚁数科合作&#xff0c;通过香港金管局“Ensemble沙盒”完成首单新能源充电桩资产代币化融资&#xff0c;募资1亿元人民币。技术实现&#xff1a;蚂蚁链提供…...

什么是IIC通信

IIC(Inter-Integrated Circuit),即IC,是一种串行通信总线,由飞利浦公司在1980年代开发,主要用于连接主板、嵌入式系统或手机中的低速外围设备1。IIC协议采用多主从架构,允许多个主设备和从设备连接在同一总线上进行通信。 IIC协议的工作原理: IIC协议使用两根信号线进…...

网络原理 TCP/IP

1.应用层 1.1自定义协议 客户端和服务器之间往往进行交互的是“结构化”数据&#xff0c;网络传输的数据是“字符串”“二进制bit流”&#xff0c;约定协议的过程就是把结构化”数据转成“字符串”或“二进制bit流”的过程. 序列化&#xff1a;把结构化”数据转成“字符串”…...

掌纹图像识别:解锁人类掌纹/生物识别的未来——技术解析与前沿数据集探索

概述 掌纹识别是一种利用手掌表面独特的线条、纹理和褶皱模式进行身份认证的生物识别技术。它具有非侵入性、高准确性和难以伪造的特点,被广泛应用于安全认证领域。以下将结合提供的链接,详细介绍掌纹识别的技术背景、数据集和研究进展。 提供的链接分析 香港理工大学掌纹数…...

【FPGA开发】Xilinx DSP48E2 slice 一个周期能做几次int8乘法或者加法?如何计算FPGA芯片的GOPS性能?

Xilinx DSP48E2 slice 在一个时钟周期内处理 INT8&#xff08;8 位整数&#xff09;运算的能力。 核心能力概述 一个 DSP48E2 slice 包含几个关键计算单元&#xff1a; 预加器 (Pre-Adder): 可以执行 A D 或 A - D 操作&#xff0c;其中 A 是 30 位&#xff0c;D 是 27 位。…...

APP 设计中的色彩心理学:如何用色彩提升用户体验

在数字化时代&#xff0c;APP 已成为人们日常生活中不可或缺的一部分。用户在打开一个 APP 的瞬间&#xff0c;首先映入眼帘的便是其色彩搭配&#xff0c;而这些色彩并非只是视觉上的装饰&#xff0c;它们蕴含着强大的心理暗示力量&#xff0c;能够潜移默化地影响用户的情绪、行…...

残差网络实战:基于MNIST数据集的手写数字识别

残差网络实战&#xff1a;基于MNIST数据集的手写数字识别 在深度学习的广阔领域中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;一直是处理图像任务的主力军。随着研究的深入&#xff0c;网络层数的增加虽然理论上能提升模型的表达能力&#xff0c;但却面临梯度消失、…...

科学养生,开启健康生活新篇章

在快节奏的现代生活中&#xff0c;健康养生成为人们关注的焦点。科学合理的养生方式&#xff0c;能帮助我们远离疾病&#xff0c;提升生活质量&#xff0c;无需依赖传统中医理念&#xff0c;也能找到适合自己的养生之道。​ 饮食是养生的基础。遵循均衡饮食原则&#xff0c;每…...

如何扫描系统漏洞?漏洞扫描的原理是什么?

如何扫描系统漏洞?漏洞扫描的原理是什么&#xff1f; 漏洞扫描是网络安全中识别系统潜在风险的关键步骤&#xff0c;其核心原理是通过主动探测和自动化分析发现系统的安全弱点。以下是详细解答&#xff1a; 一、漏洞扫描的核心原理 主动探测技术 通过模拟攻击者的行为&#xf…...

Scrapy分布式爬虫实战:高效抓取的进阶之旅

引言 在2025年的数据狂潮中,单机爬虫如孤舟难敌巨浪,Scrapy分布式爬虫宛若战舰编队,扬帆远航,掠夺信息珍宝!继“动态网页”“登录网站”“经验总结”后,本篇献上Scrapy-Redis分布式爬虫实战,基于Quotes to Scrape,从单机到多机协同,代码简洁可运行,适合新手到老兵。…...

开元类双端互动组件部署实战全流程教程(第1部分:环境与搭建)

作者&#xff1a;一个曾在“组件卡死”里悟道的搬砖程序员 在面对一个看似华丽的开元类互动组件时&#xff0c;很多人以为“套个皮、配个资源”就能跑通。实际上&#xff0c;光是搞定环境配置、组件解析、控制端响应、前后端互联这些流程&#xff0c;已经足够让新手懵3天、老鸟…...

【实验笔记】Kylin-Desktop-V10-SP1麒麟系统知识 —— 开机自启Ollama

提示: 分享麒麟Kylin-Desktop-V10-SP1系统 离线部署Deepseek后,实现开机自动启动 Ollama 工具 的详细操作步骤 说明:离线安装ollama后,每次开机都需要手动启动,并且需要保持命令终端不能关闭;通过文档操作方法能实现开机自动后台启动 Ollama 工具 一、前期准备 1、离…...

Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡

Redis&#xff1a;现代服务端开发的缓存基石与电商实践-优雅草卓伊凡 一、Redis的本质与核心价值 1.1 Redis的技术定位 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存数据结构存储系统&#xff0c;由Salvatore Sanfilippo于2009年创建。它不同于传…...

认识并理解什么是链路层Frame-Relay(帧中继)协议以及它的作用和影响

帧中继(Frame Relay)是一种高效的数据链路层协议,主要用于广域网(WAN)中实现多节点之间的数据通信。它通过**虚电路(Virtual Circuit)**和统计复用技术,优化了传统分组交换网络(如X.25)的性能,特别适合带宽需求高、时延敏感的场景。 一、帧中继的核心设计目标 简化协…...

Python基本语法(类和实例)

类和实例 类和对象是面向对象编程的两个主要方面。类创建一个新类型&#xff0c;而对象是这个 类的实例&#xff0c;类使用class关键字创建。类的域和方法被列在一个缩进块中&#xff0c;一般函数 也可以被叫作方法。 &#xff08;1&#xff09;类的变量&#xff1a;甴一个类…...

Netty的内存池机制怎样设计的?

大家好&#xff0c;我是锋哥。今天分享关于【Netty的内存池机制怎样设计的&#xff1f;】面试题。希望对大家有帮助&#xff1b; Netty的内存池机制怎样设计的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Netty的内存池机制是为了提高性能&#xff…...

Python学习之路(七)-绘画and动画

Python 虽然不是专为图形设计或动画开发的语言,但凭借其丰富的第三方库,依然可以实现 2D/3D 绘画、交互式绘图、动画制作、游戏开发 等功能。以下是 Python 在绘画和动画方面的主流支持方式及推荐库。建议前端web端展示还是用其他语言好╮(╯▽╰)╭ 一、Python 绘画支持(2D…...

【HarmonyOS 5】鸿蒙应用数据安全详解

【HarmonyOS 5】鸿蒙应用数据安全详解 一、前言 大家平时用手机、智能手表的时候&#xff0c;最担心什么&#xff1f;肯定是自己的隐私数据会不会泄露&#xff01;今天就和大家唠唠HarmonyOS是怎么把应用安全这块“盾牌”打造得明明白白的&#xff0c;从里到外保护我们的信息…...

动态指令参数:根据组件状态调整指令行为

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

Linux:权限的理解

目录 引言&#xff1a;为何Linux需要权限&#xff1f; 一、用户分类与切换 1.1、用户角色 1.2、用户切换命令 二、权限的基础概念 2.1、文件属性 三、权限的管理指令 3.1、chmod&#xff1a;修改文件权限 3.2、chown与chgro&#xff1a;修改拥有者与所属组 四、粘滞位…...

/etc/kdump.conf 配置详解

/etc/kdump.conf 是 Linux kdump 机制的核心配置文件&#xff0c;用于定义内核崩溃转储&#xff08;vmcore&#xff09;的生成规则、存储位置、过滤条件及触发后的自定义操作。以下是对其配置项的详细解析及常见用法示例&#xff1a; 一、配置文件结构 文件通常位于 /etc/kdu…...

Redis 中简单动态字符串(SDS)的深入解析

在 Redis 中&#xff0c;简单动态字符串&#xff08;Simple Dynamic String&#xff0c;SDS&#xff09;是一种非常重要的数据结构&#xff0c;它在 Redis 的底层实现中扮演着关键角色。本文将详细介绍 SDS 的结构、Redis 使用 SDS 的原因以及 SDS 的主要 API 及其源码解析。 …...

GPIO引脚的上拉下拉以及转换速度到底怎么选

【摘要】本文讲述在进行单片机开发当中&#xff0c;新手小白常常为GPIO端口的种种设置感到迷惑&#xff0c;例如到底设置什么模式&#xff1f;它们之间的区别是什么&#xff1f;到底是设置上拉还是下拉电阻&#xff0c;有什么讲究&#xff1f;端口的输出速度又该如何设置&#…...

day16 numpy和shap深入理解

NumPy数组的创建 NumPy数组是Python中用于存储和操作大型多维数组和矩阵的主要工具。NumPy数组的创建非常灵活&#xff0c;可以接受各种“序列型”对象作为输入参数来创建数组。这意味着你可以将Python的列表&#xff08;List&#xff09;、元组&#xff08;Tuple&#xff09;…...

深入探索 51 单片机:从入门到实践的全面指南

深入探索 51 单片机&#xff1a;从入门到实践的全面指南 一、引言 在嵌入式系统发展的漫长历程中&#xff0c;51 单片机犹如一颗璀璨的明星&#xff0c;虽然诞生已有数十年&#xff0c;但至今仍在众多领域发挥着重要作用。它以结构简单、易于学习、成本低廉等优势&#xff0c…...

架构思维:构建高并发读服务_热点数据查询的架构设计与性能调优

文章目录 一、引言二、热点查询定义与场景三、主从复制——垂直扩容四、应用内前置缓存4.1 容量上限与淘汰策略4.2 延迟刷新&#xff1a;定期 vs. 实时4.3 逃逸流量控制4.4 热点发现&#xff1a;被动 vs. 主动 五、降级与限流兜底六、前端&#xff0f;接入层其他应对七、模拟压…...

时间同步服务核心知识笔记:原理、配置与故障排除

一、时间同步服务 在 Linux 系统中&#xff0c;准确的时间至关重要。对于服务器集群&#xff0c;时间同步确保各节点间数据处理和交互的一致性&#xff0c;避免因时间差异导致的事务处理错误、日志记录混乱等问题。在分布式系统中&#xff0c;时间同步有助于协调任务调度、数据…...

三种石墨烯(Graphene)拉伸模拟方法对比

免责声明:个人理解,仅供参考,若有问题欢迎讨论! 一、原理解释 1、fix deform 法——整体拉伸的理想模型 📌 模拟逻辑: 使用 fix deform 指令,对模拟盒子整体在 x 方向均匀伸长; 同时施加 npt 控制,使 y 和 z 方向维持零压状态(自由弛豫); 整个石墨烯结构在形变…...

Linux系统编程--基础指令(!!详细讲解+知识拓展)

第一讲 基础指令 ​ 我们现如今自己使用的电脑大部分是用的都是windows或者macOS&#xff0c;并配合上由微软和苹果开发的图形化界面&#xff0c;所以使用鼠标再屏幕上进行点击即可完成许多任务。但是作为操作系统的学习者&#xff0c;在linux的基础上不再使用图形化界进行操作…...

Python10天冲刺《Pydantic 是一个用于数据验证和设置管理的 Python 库》

Pydantic 是一个用于数据验证和设置管理的 Python 库&#xff0c;其核心功能围绕 数据验证、类型检查 和 模型配置 展开。以下是 Pydantic 的主要功能分类及其简要说明和示例&#xff1a; 1. 数据验证与类型检查 Pydantic 的核心功能是自动验证数据的类型、格式和约束条件。 …...

【工具】adverSCarial评估单细胞 RNA 测序分类器抵御对抗性攻击的脆弱性

文章目录 介绍代码参考 介绍 针对单细胞 RNA 测序&#xff08;scRNA-seq&#xff09;数据中健康细胞类型与病变细胞类型的检测&#xff0c;已有多项机器学习&#xff08;ML&#xff09;算法被提出用于医学研究目的。这引发了人们对于这些算法易受对抗性攻击的担忧&#xff0c;…...

机场围界报警系统的研究与应用

机场围界报警系统的研究与应用 摘要 本论文围绕机场围界报警系统展开深入研究,阐述了机场围界报警系统的重要性,对当前主流的机场围界报警技术原理、特点及应用场景进行详细分析,并探讨了现有系统存在的问题,最后对未来发展趋势进行了展望。研究表明,机场围界报警系统对…...

嵌入式操作系统

嵌入式操作系统是一种用途广泛的系统软件&#xff0c;通常包括与硬件相关的底层驱动软件、系统内核、设备驱动接口、通信协议、图形界面、标准化浏览器等。嵌入式操作系统负责嵌入式系统的全部 软、硬件资源的分配、任务调度&#xff0c;控制、协调并发活动。  嵌入式实时…...

预测性维护与传统维护成本对比:基于技术架构的量化分析

在工业 4.0 的技术演进浪潮中&#xff0c;设备维护模式正经历从经验驱动向数据驱动的变革。传统维护模式依赖固定周期巡检与故障后抢修&#xff0c;犹如 “蒙眼驾车”&#xff1b;而预测性维护借助物联网&#xff08;IoT&#xff09;、机器学习&#xff08;ML&#xff09;等技术…...

定位理论第一法则在医疗AI编程中的应用

引言 定位理论的核心在于通过明确目标、界定边界和建立差异化优势来占据用户心智中的独特位置。在医疗AI领域,定位理论的应用尤为重要,尤其是在医疗AI编程中,如何通过科学的定位确保技术与医疗本质的深度协同,而非技术主导的颠覆,是一个需要深入探讨的课题。本研究将深入剖…...

【macOS常用快捷键】

以下是 macOS 最常用快捷键列表&#xff0c;按使用频率由高到低分类整理&#xff0c;涵盖日常操作、效率工具及系统控制&#xff0c;助你快速提升使用效率&#xff1a; 一、基础高频操作 快捷键功能说明Command C复制选中内容Command V粘贴Command X剪切Command Z撤销上一…...

【Flask】ORM模型以及数据库迁移的两种方法(flask-migrate、Alembic)

ORM模型 在Flask中&#xff0c;ORM&#xff08;Object-Relational Mapping&#xff0c;对象关系映射&#xff09;模型是指使用面向对象的方式来操作数据库的编程技术。它允许开发者使用Python类和对象来操作数据库&#xff0c;而不需要直接编写SQL语句。 核心概念 1. ORM模型…...

信息安全导论 第八章 入侵检测技术

目录 一、入侵检测系统概述 二、入侵检测技术 三、入侵检测系统实例 1. Snort简介 2. Snort架构 3. Snort规则示例 4. 检测流程 四、入侵防御系统 1. IPS vs. IDS 2. IPS分类 3. IPS核心技术 4. IPS优势 5.总结 一、入侵检测系统概述 定义 检测、识别和隔离对系统…...

每日c/c++题 备战蓝桥杯(P1886 滑动窗口 /【模板】单调队列)

洛谷P1886 滑动窗口【模板】单调队列详解 题目描述 给定一个长度为n的整数序列&#xff0c;要求输出所有长度为k的连续子数组的&#xff1a; 最小值&#xff08;第一部分输出&#xff09;最大值&#xff08;第二部分输出&#xff09; 数据范围&#xff1a; 1 ≤ k ≤ n ≤…...

GStreamer开发笔记(三):测试gstreamer/v4l2+sdl2/v4l2+QtOpengl打摄像头延迟和内存

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/147714800 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、O…...