自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 Linux 信号的处理

对于一个进程,有进程的PCB,进程地址空间,以及页表,以及用户在物理内存中的代码和数据,其实这个页表是用户级页表,如何理解呢?之前小编一直在谈地址空间中0~3GB的用户空间,其实这个0~3GB的虚拟地址是通过用户级页表映射到物理内存中用户自己的代码和数据,我们执行用户的代码是在0~3GB的用户的虚拟地址空间中的正文代码开始执行的。

2025-12-29 18:22:02 968

原创 Linux 信号发送和保存

实际执行信号的处理动作称为信号递达(Delivery)信号从产生到递达之间的状态,即此时信号被保存起来了,称为信号未决(Pending)进程可以选择阻塞/屏蔽(Block)某个信号,当信号被阻塞/屏蔽之后,不会处理这个信号,即信号不会被递达如果一个信号此时已经被阻塞,那么当进程收到了这个被阻塞的信号之后,不会处理这个信号,但是仍然会保存这个信号,此时这个信号处于信号未决状态,直到进程解除了对这个信号的阻塞之后,此时这个信号才会被处理,即此时信号才会被递达。

2025-12-28 16:17:36 633

原创 Linux 信号的产生

你在网上买了很多件商品,再等待不同商品快递的到来。但即便快递没有到来,你也知道快递来临时,你该怎么处理快递。也就是你能“识别快递”,当快递员到了你楼下,你也收到快递到来的通知,但是你正在打游戏,需5min之后才能去取快递。那么在在这5min之内,你并没有下去去取快递,但是你是知道有快递到来了。也就是取快递的行为并不是一定要立即执行,可以理解成“在合适的时候去取”。在收到通知,再到你拿到快递期间,是有一个时间窗口的,在这段时间,你并没有拿到快递,但是你知道有一个快递已经来了。

2025-12-28 12:49:04 997

原创 Linux system V 共享内存

共享内存是进程间通信IPC的方式,相对于管道而言,需要经历数据从用户态到内存,内存到用户态的两次拷贝,共享内存则是直接对物理内存进行操作,不需要拷贝,一旦这样的内存映射到共享它的进程的地址空间,这些进程间进行数据传递就不再涉及到内核,换句话来说,进程不再通过执行进入内核的系统调用来完成传递彼此的数据,如何理解呢?请看下图进行进程间通信的本质就是要让不同进程看到同一份资源,那么共享内存又是如何做的呢?请看下图。

2025-12-27 01:54:03 648

原创 Linux 简单日志程序

ap: 这是一个 va_list 类型的对象,是指向可变参数的起始位置指针, last 是最后一个传递给函数的已知的固定参数,即省略号之前的参数。用来提取可变参数列表中的参数的函数是va_arg,使用一次提取一个,每次提取的参数是直接返回的并且该函数提取的同时会自动将ap指向下一个参数。format:包含格式说明符的字符串,它定义了后续参数的输出格式,例: %d,%s。format:包含格式说明符的字符串,它定义了后续参数的输出格式,例: %d,%s。ap: 要销毁的变量。arg:可变参数列表。

2025-12-26 17:29:18 289

原创 Linux 进程间通信---命名管道

1,如果是具有血缘关系的进程,想要通信我们可以使用匿名管道,如果我们想在之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。2.在内核中,操作系统会打开一个文件,即在内核中,仅有一个文件的inode结构体,文件的files_operations结构体,一个内核级别的文件缓冲区,那么由于这两个进程可能会有不同的打开文件的方式,并且两个文件的执行流不同,读取写入到文件的位置可能也不同,所以分别会给这两个进程各自分配一个文件打开对象。

2025-12-25 23:21:45 609

原创 Linux 进程池小程序

【代码】Linux 进程池小程序。

2025-12-21 16:11:12 266

原创 Linux进程间通信---匿名管道

父进程创建匿名管道,同时以读、写的方式打开匿名管道,此时会分配两个 fd,fork 创建子进程,子进程拥有自己的进程系统信息,同时会继承原父进程中的文件系统信息,此时子进程和父进程可以看到同一份资源:匿名管道 pipe因为子进程继承了原有关系,因此此时父子进程对于 pipe 都有读写权限,需要确定数据流向,关闭不必要的 fd,比如父进程写、子进程读,或者父进程读、子进程写都可以。例如,如果父进程要写数据到管道而子进程读取数据,父进程应该关闭管道的读端,子进程应该关闭管道的写端。

2025-12-21 01:29:11 617

原创 Linux 软硬链接和动静态库

硬链接:同一个文件的「多个文件名」,共享同一个inode(相当于给文件起别名)。软链接(符号链接):一个「特殊文件」,内容是目标文件的路径(相当于Windows的快捷方式)。

2025-12-16 16:12:12 905 1

原创 Linux 文件系统与inode结构

上一篇博客我们提到的都是已经打开的文件,那么没有打开的文件都是静静的躺在外存(磁盘)里面,当需要对文件进行访问时,会通过inode值对文件进行访问。通过以下指令查看当前目录中文件的详细信息及 inode 值。ll -i第一个数就是inode值。除了这个指令还有一个可以看到文件的更多信息。

2025-12-07 21:10:10 973

原创 Linux 文件描述符,重定向及缓冲区理解

在对于文件的认识中,文件就等于内容+属性,磁盘上面存储的也就是文件的内容加上属性。文件分为被打开的文件和未打开的文件。文件一般被谁打开呢-->进程,一个进程可以打开多个文件,进程通过调用系统接口来打开文件,在这之前操作系统也会检查你的权限是否支持该操作,返回一个给你,来支持对文件的操作,打开了之后,操作系统会创建一个来描述该文件的相关属性。同时打开文件,文件的内容不会一下子全部被加载到内存,而是通过和的方式。有了上面的认识之后,简单认识运行C语言1.第一个参数表示要打开的文件路径。

2025-12-07 00:35:05 893

原创 Linux 进程替换

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的完全被新程序替换,从新程序的启动例程开始执行。调用exec并,所以调用exec前后该进程的id并未改变。

2025-12-03 23:02:28 563

原创 Linux 进程等待

等待的时候也可以让父进程做一些自己的事情,设置为非阻塞轮询,也就是父进程在调用waitpid等待子进程时,发现子进程还没有结束,就可以让父进程去做别的事情,下次再过来询问子进程好了吗?我们让子进程创建后10秒后再退出,把等待模型设置为非阻塞状态,把for循环设置为6次,前3次由于子进程没有结束,父进程做自己的事情,后三次父进程回收子进程。我们可以使用对位图的&操作来获取到子进程的退出状态,每个进程中都有保存自己的退出码和导致进程终止的退出信号,父进程也就是从子进程的PCB上面去获取。

2025-11-30 21:53:01 673

原创 Linux 进程控制

之前我们对fork函数以及有了初步的理解了,它在应该以及存在的进程中创建应该新的进程,子进程。fork 函数的作用是在当前 进程 下,创建一个 子进程,子进程 创建后,会为其分配新的内存块和将 父进程中的数据结构内容拷贝给子进程,同时还会继承父进程中的。运行结果:这里看到了三行输出,一行before,两行after。进程43676先打印before消息,然后它有打印after。另一个after消息有43677打印的。注意到进程43677没有打印before,为什么呢?如下图所示。

2025-11-30 17:23:35 647

原创 Linux 进程地址空间(初步理解)

在操作系统中,内存管理是一个至关重要的概念。对于开发者来说,理解操作系统如何管理进程的内存空间,不仅能帮助我们写出高效的程序,还能帮助我们更好地理解程序的运行机制。今天,我们将深入探讨虚拟内存、物理内存以及进程地址空间的相关概念,并重点讲解写时拷贝(Copy-on-Write,COW)机制。在 C/C++ 程序中,内存一般可以分为几个主要区域:栈区、堆区、静态区等。每个区域有着不同的用途:栈区:用于存储局部变量以及函数调用的栈帧。堆区:用于动态分配内存(例如通过 malloc、new 等)。

2025-11-26 00:01:13 1583

原创 Linux 环境变量&&进程优先级

寄存器:寄存器有很多种,去保存进程里面很多相关的数据(相当于进程的上下文),当进程被切换,需要做的有保存上下文,和恢复上下文,这样子 cpu 才会知道你接下来该运行哪个部分,和上面的上次运行时的数据,保存上下文,进程要时间片时间到了后,要脱离 cpu,进程的 pcb 会构建一个结构体,里面去存放上下文,到再次要运行的时候,再把数据放到寄存器上面(这个是当前只能这么理解)。为什么我们输入ls,cd,pwd这些指令的时候,就可以直接被执行,但是我们的二进制文件却需要输入./文件名才会被执行呢?

2025-11-25 01:11:11 784

原创 Linux 进程状态

R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。操作系统为了管理那些已经就绪,等待被cpu处理的进程,有一个运行队列的结构体,来管理这些已经就绪的进程,当一个进程已经就绪后,就会被放入到运行队列里面,排队等待cpu处理,但是不是非要把一个进程执行完毕后,才从cpu上面剥离,会有时间片的概念,时间片到了,就从cpu上面剥离下来,cpu处理下一个进程,进程被拿上去,拿下来的动作叫做进程切换。

2025-11-24 20:29:08 811

原创 Linux 进程概念

所以对于进程,当一个程序被加载到内存时,在成为真正的进程前,操作系统作为软硬件的管理者,对程序的代码和数据创建一个task_struct结构体来描述他,方便进行管理,进程可以理解为由task_struct和代码+数据构成的。ps:操作系统对于PCB的结构体采用双向链表的方式管理起来。当我们编写代码后,代码运行起来后就相当于以及形成了一个进程。

2025-11-22 17:42:44 1083 1

原创 Linux 权限管理

Linux严格意义上说的是一个操作系统,我们称之为“核心(kernel)“ ,但我们一般用户,不能直接使用kernel。而是通过kernel的“外壳”程序,也就是所谓的shell,来与kernel沟通。如何理解?为什么不能直接使用kernel?从技术角度,Shell的最简单定义:命令行解释器(command Interpreter)主要包含:将使用者的命令翻译给核心(kernel)处理。同时,将核心的处理结果翻译给使用者。

2025-11-22 00:06:49 810

原创 Linux 常见指令

ls [选项][目录或文件]:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息。-a 列出目录下的所有文件,包括以 . 开头的隐含文件。-d 将目录象文件一样显示,而不是显示其下的文件。如:ls –d 指定目录-i 输出文件的 i 节点的索引信息。如 ls –ai 指定文件-k 以 k 字节的形式表示文件的大小。ls –alk 指定文件-l 列出文件的详细信息。-n 用数字的 UID,GID 代替名称。(介绍 UID, GID)

2025-11-21 17:20:46 782

原创 C++ 类型转化

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败2.显示类型转化:需要用户自己处理。

2025-11-20 21:04:58 808

原创 C++ 特殊类的设计

拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。

2025-11-20 17:20:31 559

原创 C++ 智能指针

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。// 1.内存申请了忘记释放// 2.异常安全问题Func();// 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放.

2025-11-17 00:38:45 867

原创 C++ 11

在C++98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法。int main()// 默认按照小于比较,排出来结果是升序// 如果需要降序,需要改变元素的比较规则return 0;{}//仿函数int main()vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 3 }, { "菠萝", 1.5, 4 } };

2025-11-15 17:33:49 1221

原创 C++ 布隆过滤器

这里我们可以发现插入“baidu”和“tencent”这两个生产出的哈希值都存在4,所以不同的值通过哈希函数求出来的哈希值是会冲突的,当插入的值多了之后,比如我们又插入一个“bit”,假设bit的3个映射位为1,4,8,这三个位置的位置上面都置为1,所以就会存在误判,布隆过滤器是降低误判概率,而不是没有误判,所以对于一个元素的映射的位置如果都为1,我们只能说它可能存在,如果映射的位置有一个不为1,那么它肯定存在。给两个文件,分别有 100 亿个 query,我们只有 1 GB 内存,如何找到两个文件交集?

2025-11-12 18:59:31 662

原创 C++ 位图

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。【腾讯】如果要按照正常的想法的话,创建一个数组全部存储进去,那么一个无符号整数是4个字节,40亿个就是160亿字节,大约是15个g的内存,运行内存就需要15个g来处理,那么其他的进程呢?指针方法显然是不合适的。同时数据也是无序的,如果查找的话,时间复杂度是O(N)级别的,查找的时间成本也非常高。那么我们就需要一种查找速度快,使用内存还少的方法来解决这问题:位图。

2025-11-12 00:22:18 692

原创 C++ 闭散式和开散式的模拟实现

enum STATEEXIST,EMPTY,DELETE用一个结构体来表示当前的存储状态,存在,空,还是删除过的。//记录有效值的个数使用vector数组包含一个个HashData对象,_n来记录有效个数的值,为后续扩容做准备。T _data;{}哈希表需要维护一个单链表,需要把一个个的节点串起来,所以需要一个指针来指向下一个节点。//存储有效数字个数因此数组里面的存储类型也就变成了节点指针。

2025-11-10 21:37:42 1063

原创 C++ 哈希

在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到log N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是。

2025-11-10 17:42:09 1249

原创 C++ map和set的实现和封装

map和set都是基于红黑树去实现的。

2025-11-04 23:06:05 613

原创 C++ 红黑树

红黑树不再像二叉树一样使用平衡因子来严格控制平衡,使用对节点用红黑两种颜色来进行控制平衡。, _kv(kv){}为什么要初始化为红色呢?

2025-11-01 01:01:11 972

原创 C++ AVL树

二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。AVL树在二叉搜索树的基础上面加上了平衡因子bf和父亲指针。

2025-10-30 23:23:14 684

原创 C++ 异常

实际使用中很多公司都会自定义自己的异常体系进行规范的异常管理,因为一个项目中如果大家随意抛异常,那么外层的调用者基本就没办法玩了,所以实际中都会定义一套继承的规范体系。这样大家抛出的异常调用基类来进行调用就可以了。public::Exception(errmsg, id)//调用基类的构造{}virtual string what() const//定义为虚函数,分别多态的使用。

2025-10-29 23:15:13 828

原创 C++ map和set使用

map:一种键值对(Key-Value) 集合,键(Key)唯一且可对应任意类型的值(Value),好比带标签的收纳盒,每个标签(Key)只能对应一个盒子(Value),通过标签能快速找到盒子。set:一种无重复元素的集合,只存储单个值(Value)且值不重复,类似去重后的清单,比如记录已打卡的景点,不会出现同一个景点被重复记录的情况。

2025-10-29 12:22:30 1130 1

原创 C++ 二叉搜索树

它或者是一棵空树,或者是具有以下性质的二叉树:若它的左子树不为空,则左子树上所有节点的值都小于根节点的值,若它的右子树不为空,则右子树上所有节点的值都大于根节点的值,它的左右子树也分别为二叉搜索树。

2025-10-26 19:03:20 697

原创 C++ 多态

多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。虚函数:被virtual修饰的类成员就称为虚函数。cout << "半价" << endl;打印出来的结果是多少:答案是8。

2025-10-25 16:09:09 806

原创 C++ 继承

我们可以看到,Person是父类,也称为基类,Student是子类,也成为派生类。

2025-10-23 18:28:37 971

原创 C++ stack和queue

1.队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

2025-10-21 17:23:04 685

原创 C++ list

list是C++的一个序列容器,插入和删除元素的效率较高,时间复杂度为常数级别,list容器的底层数据结构为带头双向循环链表,这使得 list的元素可以存储在非相邻的内存中,在list内部,不同元素之间通过指向前一个元素的指针以及指向后一个元素的指针相关联。list 容器与其他序列容器如vector deque array相比,由于其底层数据结构为带头双向循环链表,因此 list 在插入删除元素方面很有优势,在列表的任意位置进行插入和删除操作的时间复杂度为O(1)。

2025-10-19 14:49:37 1111

原创 C++ vector

vector是C++标准模板库(STL)中的一个序列容器。它能够存储相同类型的元素序列,并且这些元素在内存中连续存储。vector可以存储一个动态数组,即它可以在运行时改变其大小,以存储任意类型的对象(包括内置类型如int、double等,以及用户自定义的类型如类对象)。vector提供了许多方便的成员函数来管理其存储的元素,比如添加、删除、访问元素等(动态顺序表)。

2025-10-17 22:41:55 713

原创 C++ string

深拷贝则会复制指针指向的实际数据,从而确保每个对象都有自己独立的内存空间。C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。构造函数:开辟空间,如果是根据string类或者是字符串来构造就开辟一样的空间,有效字符长度和空间的总大小进行赋值,如果是构造空的string类对象,开辟1个字节的空间,有效字符长度和空间的总大小都为0。

2025-10-17 13:26:44 620

空空如也

空空如也

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

TA关注的人

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