自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(35)
  • 收藏
  • 关注

原创 Linux:网络层IP协议

MTU是指。

2025-08-22 16:24:28 878

原创 Linux:TCP协议

你可能会疑惑,为什么断开连接时,第二次挥手(服务端应答)和第三次挥手(服务端发送FIN报文)为什么不能合二为一(像三次握手中的第二次握手一样,发送SYN报文的同时捎带应答ACK报文)。这是因为客户端发送FIN报文是表示自己不想再发送数据了,但此时服务端可能还有数据没有发完,需要一些时间。因此,第二次挥手和第三次挥手有一定时间差,不能合二为一;同时,如果在这期间服务端又向客户端发送了数据的话,两次的确认序号也可能不同。

2025-08-17 20:16:59 1202

原创 Linux:套接字

这里还有一个十分重要的细节问题:网络字节序sin_port和sin_addr都必须是网络字节序(大端模式,低地址高字节),一般可视化的数字都是主机字节序(小端模式,低地址低字节)。这里用一个简单的例子来帮助理解:对于数据 0x12345678,假设从地址0x4000开始存放,在大端和小端模式下,存放的位置分别为:总之,我们给sin_port和sin_addr进行初始化时,要进行字节序的转换,这里需要用到两个函数:htons()作用是将端口号由主机字节序转换为网络字节序的整数值。

2025-08-15 18:22:21 993

原创 Linux:网络分层模型

协议是指网络通信中,通信双方(对等层实体)为了实现有效、可靠的数据交换而必须共同遵守的一组规则、标准和约定的集合。关键要素:语法: 定义了数据的结构或格式。例如,数据包中各个字段的顺序、长度、类型(如IP数据包头的版本号、源IP地址、目标IP地址等字段的位置和含义)。语义: 定义了数据和控制信息所代表的含义。通信双方需要理解每个字段或控制信号表示什么操作或响应(例如,TCP包头中的SYN标志位表示“请求建立连接”,ACK标志位表示“确认收到数据”)。

2025-08-15 13:15:25 940

原创 C++:智能指针

在传统的 C++ 中,使用new分配内存后,程序员必须在适当的时机使用delete来释放这块内存。忘记delete会导致内存泄漏;过早delete(例如在还有指针指向该内存时就释放了)会导致悬空指针(Dangling Pointer),后续访问该指针会引发未定义行为(通常是程序崩溃);重复delete同一块内存也会导致严重错误。解决方案:智能指针(Smart Pointers)智能指针是 C++ 标准库(主要在<memory>头文件中)提供的类模板。它们的设计目标是自动化内存管理,特别是动态分配(

2025-07-29 14:38:30 959

原创 Linux:线程同步与线程互斥

可以看到,lock函数首先将0赋值给了一个寄存器,该寄存器内容属于线程上下文,不会被其他线程访问到,随后执行xchgb操作,该操作是一个硬件指令,含义为交换后面的两个操作数,也就是交换寄存器中的值(0)和mutex(mutex是一个共享内容),若寄存器中的内容>0则执行完毕,否则将线程挂起等待,到被唤醒时再次回到lock开头。对于实践而言,用第一种实现是最好的。而由于寄存器属于线程上下文,一个线程new了一个对象,修改了寄存器,并不会影响其他线程,这样其他线程也会new对象,造成内存泄漏。

2025-07-28 22:59:48 829

原创 Linux:线程控制

线程(Thread)是进程(Process) 中的一个执行单元,是操作系统能够进行运算调度的最小单位。线程也被称为“轻量级进程”(Lightweight Process, LWP)。一个进程可以包含多个线程,这些线程共享该进程所拥有的全部资源(后续展开解释)。为什么认为线程是轻量级进程,主要有两方面:1.线程创建:创建线程不产生新的进程地址空间,也就不需要创建对应的页表2.线程切换:(1)由于进程地址空间不同,进程切换时无法从高速缓存中读取数据,只能从较慢的内存中读取数据,而线程由于共享地址空间,更有可能直

2025-07-20 22:36:40 1013

原创 Linux:信号

信号是进程之间事件异步通知的⼀种⽅式,属于软中断。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。。我们先熟悉常用信号,并初步了解信号处理方法。再根据信号的生命周期来了解信号机制运作的全过程。

2025-07-12 22:36:03 637

原创 Linux:库与链接

库是预先编译好、可执⾏的⼆进制码,可以被操作系统加载到内存中执⾏。库有两种:静态库:.a(Linux)、.lib(Windows)动态库:.so(Linux)、.dil(Windows)

2025-05-20 22:49:46 1149

原创 Linux:文件系统

本文主要介绍文件系统如何将文件存储于在磁盘上,以及文件系统如何访问磁盘上的文件。

2025-05-14 12:53:36 989

原创 Linux:文件操作

在C语言中,我们可以使用fopen() fclose() fread() fwrite()等接口进行文件操作,而由于文件是储存于磁盘中的,且磁盘是由操作系统来管理的,因此在用户层面对文件的操作必然要调用操作系统对文件的操作。我们接下来就要了解操作系统是如何描述、组织文件并进行操作的,以及C语言是如何对这些操作进行封装,把封装好的接口提供给用户的操作系统获取文件路径:执行结果:在/home/nexus/daily_study/file下,myfile被创建。

2025-04-30 20:08:04 878

原创 Linux:进程:进程控制

我们之前虽然用fork创建了子进程,但是子进程和父进程执行的还是同样的代码,很多时候我们创建子进程就是为了去专门执行某一任务,这就需要用到进程替换,进程替换是通过特定的接⼝,把磁盘上另外的⼀个程序的代码和数据加载到调⽤原先进程的地址空间中。(查看进程的退出码)为了判断进程终止是哪种情况,进程在结束时会将退出码和退出信号返回给父进程,其中,退出信号用于判断进程是否异常,退出码用于判断进程运行结果是否正确。fork函数是Linux中的一个系统调用,用于创建一个新的进程,创建的新进程是原来进程的子进程。

2025-04-21 23:43:31 1024

原创 Linux:虚拟地址空间

程序经过编译后,变成了可执行的文件,可执行文件主要包括代码和数据两部分,代码是只读的,数据则是可读可写的。可执行文件由操作系统加载到内存中,交由CPU去执行,现在问题来了,CPU怎么去访问代码和数据?,访问的方式经历过四个阶段:1.直接访问2.段基址+段偏移地址3.段选择子+段偏移地址4.虚拟地址现代操作系统采用的是虚拟地址,这也是本篇文章阐述的重点,但虚拟地址是由前三阶段发展而来的,所以也有必要阐述前三种访问方式。

2025-04-18 22:49:56 808

原创 Linux:命令行参数、环境变量

执行程序时,可以从命令行传值给 C 程序。这些值被称为,它们对程序很重要,特别是当我们想从外部控制程序,而不是在代码内对这些值进行硬编码时,就显得尤为重要了。在 C 语言中,命令行参数是一种从命令行获取输入的方法,可以用于运行程序时传递信息给程序。命令行参数通过 main 函数的参数传递给程序。: 表示命令行参数的数量,包括程序名本身。因此,argc至少为1argv: 是一个指向字符串数组的指针,其中每个字符串是一个命令行参数。数组的第一个元素(即argv[0])通常是程序的名称。

2025-04-18 11:02:21 1098

原创 Linux:进程:进程调度

即bitmap[5]是一个整形数组,大小为160bit,我们只需要前120个bit,每一个bit对应一个queue[i],1表示queue[i]不为空,0表示为空,这样我们可以通过高效的位运算来找到PRI最低的task_struct链表。当进程运行将指令传给CPU,CPU靠指令集分析指令运行对应代码,当进程的时间片结束后,操作系统将保存此时CPU中寄存器内的数据,当再次轮到这个进程后操作系统将原本数据加载到寄存器中,eip就可以通过下一条指令地址让代码继续运行。这就完成了进程切换。

2025-04-17 23:22:02 1016

原创 Linux:进程:进程状态

进程是一个负责分配系统资源(CPU时间,内存)的实体。进程=内核数据结构(用于描述和组织进程)+代码数据(实际内容)

2025-04-17 15:23:23 775

原创 Linux:Makefile

预处理指令是以#号开头的代码⾏。

2025-04-16 23:31:47 1010

原创 C++: unordered_map、unordered_set

unordered_set/map和set/map的第⼀个差异是对key的要求不同,set/map要求Key⽀持⼩于⽐较,而unordered_set/map要求Key⽀持转成整形且⽀持等于⽐较unordered_set/map和set/map的第⼆个差异是迭代器的差异,set/map的iterator是双向迭代器,unordered_set/map是单向迭代器,其次set/map底层是红⿊树,红⿊树是⼆叉搜索树,中序遍历是有序的,所以set迭代器遍历是有序+去重。

2025-04-10 14:31:19 1003

原创 C++:红黑树

红⿊树是⼀棵⼆叉搜索树,他的每个结点增加⼀个存储位来表⽰结点的颜⾊,可以是红⾊或者⿊⾊。通过对任何⼀条从根到叶⼦的路径上各个结点的颜⾊进⾏约束,红⿊树确保没有⼀条路径会⽐其他路径⻓出2倍,因⽽是接近平衡的。

2025-03-19 17:12:38 655

原创 C++:AVL树

二叉搜索树在最优情况下高度为log2^N,但在最差情况下高度为N,导致查找的时间复杂度为O(n),为了解决这一问题,需要通过平衡根节点的两边来将高度维持在logNAVL树是最先发明的⾃平衡⼆叉查找树,AVL是⼀颗空树,或者具备下列性质的⼆叉搜索树:它的 左右⼦树都是AVL树,且左右⼦树的⾼度差的绝对值不超过1。AVL树是⼀颗⾼度平衡搜索⼆叉树, 通过控制⾼度差去控制平衡。

2025-03-19 13:53:59 1073

原创 Linux权限管理

root:Linux管理员(仅一个且拥有最高权限)普通用户(可以有多个)root用户在root根目录下操作文件普通用户在home家目录下所创建的一个目录(该目录名为用户名)下操作文件普通账户不能切换为其他普通账户普通账号切换为root账号需要输入root账号的密码root账户可以直接切换为普通账户但是要注意:默认新用户不被操作系统信任,无法使用sudo命令:解决方法:输入“visudo”进入sudo文件:一直下翻找到这一行:在下面按照以上格式添加新用户即可,随后保存退出。

2025-03-04 18:38:01 393

原创 C++: map和set

set的作用类似于现实中的存包柜,用于存放不重复的元素,可以用来去掉重复元素和检验元素是否存在class set;(T就是关键字的类型)set默认要求T⽀持⼩于⽐较,如果不⽀持或者想按⾃⼰的需求⾛可以⾃⾏实现仿函数传给第⼆个模 版参数set底层存储数据的内存是从空间配置器申请的,如果需要可以⾃⼰实现内存池,传给第三个参 数。⼀般情况下,我们都不需要传后两个模版参数。set底层是⽤红⿊树实现,增删查效率是的O(logN),迭代器遍历是⾛的搜索树的中序,所以是有序。

2025-03-03 19:03:30 729

原创 C++:多态

多态是⼀个继承关系的下的类对象,去调⽤同⼀函数,产⽣了不同的⾏为。⽐如Student继承了Person。Person对象买票全价,Student对象优惠买票。必须用基类的指针或者引⽤来调⽤虚函数被调⽤的函数必须是虚函数,并且完成了虚函数重写/覆盖。

2025-02-28 19:37:36 886

原创 C++:二叉搜索树

⼆叉搜索树⼜称⼆叉排序树,具有以下性质:1.若它的左⼦树不为空,则左⼦树上所有结点的值都⼩于等于根结点的值2.若它的右⼦树不为空,则右⼦树上所有结点的值都⼤于等于根结点的值3. 它的左右⼦树也分别为⼆叉搜索树⼆叉搜索树中可以⽀持插⼊相等的值(也叫支持冗余),也可以不⽀持插⼊相等的值,具体看使⽤场景定义,map/set/multimap/multiset系列容器底层就是⼆叉搜索树,其中map/set不⽀持插⼊相等 值,multimap/multiset⽀持插⼊相等值。

2025-02-28 16:12:21 840

原创 C++:继承

4. 使⽤关键字class时默认的继承⽅式是private,使⽤struct时默认的继承⽅式是public,不过最好显⽰的写出继承⽅式。

2025-02-24 11:20:44 801

原创 STL:stack queue

3.优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue 提供一组特定的成员函数来访问其元素。默认情况下,如果没有为特定的priority_queue 类实例化指定容器类,则使用vector。1.优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。2.类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶 部的元素)4.底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。empty():检测容器是否为空。

2025-02-19 20:07:45 775

原创 STL:list

list类似于数据结构中的带头结点的双向循环链表。

2025-02-14 20:50:50 655

原创 const

变量是可以修改的,通过指针也可以修改这个变量如果我们不希望⼀个变量被修改时,就需要用const来修饰变量,被const修饰的变量具有常性注意:被const修饰的变量只能在初始化时赋值结果:n确实被修改了,但是n要被const修饰,就是为了不能被修改如果p拿到n的地址就能修改n,这样就打破了const的限制,这是不合理的,所以应该让p拿到n的地址也不能修改n,这就需要用const来修饰指针变量。

2025-02-10 16:05:01 547

原创 STL:vector

这意味着它可以存储int,也可以存储string类,甚至可以存储vector<int>类,这时vector<vector<int>>就相当于一个二维数组,与C语言中直接定义的二维数组(实质仍是一个一维数组)相比,它在存储方式上更接近于二维数组,而要用C语言实现类似的二维数组,则要用到二级指针,创建和使用都非常麻烦。

2025-02-10 15:04:38 894

原创 STL: string

string类是标准库中的一种数据结构在使用string类时,必须包含#include头文件以及using namespace std。

2025-02-06 12:39:14 798

原创 内存管理、模板

new的原理1. 调用operator new函数申请空间2. 在申请的空间上执行构造函数,完成对象的构造delete的原理1. 在空间上执行析构函数,完成对象中资源的清理工作2. 调用operator delete函数释放对象的空间new T[N]的原理1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对 象空间的申请2. 在申请的空间上执行N次构造函数delete[]的原理。

2025-01-30 21:58:26 780

原创 类和对象(下)

如果这个成员在声明位置给了缺省值,初始化列表会⽤这个缺省值初始化。如果你没有给缺省值,对于没有显示在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显示在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构造会编译错误。

2025-01-29 23:40:18 830

原创 类和对象(中)

如果这个成员变量,没有默认构造函数,那么就会报错,我们要初始化这个成员变量,需要⽤ 初始化列表才能解决,初始化列表,我们之后再解决。构造函数用于对对象的初始化(不是为对象开辟空间),由于对象里的数据基本都是private的我们不能直接访问,因此就需要一个函数来对对象进行初始化——析构函数,可以认为它有C语言中Init函数的作用。7. 如果类中没有申请资源或默认⽣成的析构可以⽤时,析构函数可以不写,直接使⽤编译器⽣成的默认析构函数,但是有资源申请时,⼀定要写析构,否则会造成资源泄漏。

2025-01-24 20:20:53 454

原创 类和对象(上)

首先函数被编译后是⼀段指令,对象中没办法存储,这些指令 存储在⼀个单独的区域(代码段),那么对象中一定要存储的话,只能是成员函数的指针。而函数的指针也是不需要存储的,因为调⽤函数这一操作会被编译成汇编指令 [call 函数地址],而编译器在编译链接时,就要找到函数的地址,不是在运⾏时找,只有动态多态是在运行时找,这时就需要存储函数地址。如果嵌套了结构体的情况,嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处,结构体的整体⼤⼩ 就是所有最⼤对⻬数(含嵌套结构体的对⻬数)的整数倍。

2025-01-23 15:18:48 899

原创 C++:1.命名空间、缺省参数、函数重载、引用、内联函数、nullptr

1.命名空间是一个域,可以包含变量,函数和类型等,由于不同的域中可以定义同名变量,因此可以利用命名空间来防止命名冲突。1.C++允许定义多个函数名相同但是函数形参不同(数量或类型不同)的函数,但只有返回值不同则无法构成重载函数,这样在调用函数时会匹配形参和实参的类型,使得调用函数更方便。3.引用和指针的区别:定义一个引用必须初始化,定义一个指针则不需要;命名空间中可以继续定义命名空间,如果两次定义了同一个命名空间,则二者会合为一个命名空间。1.类型& 引用别名=变量名,引用与引用的变量共用一个空间。

2025-01-21 21:12:09 217

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除