- 博客(31)
- 收藏
- 关注
原创 无处不在的生产者与消费者模型
街角的工厂里,机器日夜运转,工人们忙碌不停。他们生产着各种各样的商品,比如面包、饮料、日用品等。工厂的任务就是不停地制造这些商品,保证供应充足。
2025-03-17 22:32:18
750
原创 互斥与同步
先看结果:以下代码是我模拟创建线程抢票,由于不加锁导致票抢到了负数由于我封装了pthread,奉上Thread.hpp造成以上结果的原因就是在1、if()操作不是原子操作2、线程的调度切换原子性:不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成数据被多次拿到的对策就是一次只允许一个人可以使用这一份资源。那么底层的原理就是有一个东西类似与这个令牌。但是我又怎么保障拿到这个令牌的时候别人不来抢呢?这时候我们就要保证拿令牌这个操作是原子操作了。
2025-03-17 21:41:54
394
原创 线程--轻量化进程
库函数-用户级线程:pthread_create (线程id,线程属性,函数指针,喂给线程函数的参数) 返回值成功为0,失败为错误码;进程的多个线程,很多书都说线程有独立栈,但是其实其它线程想访问也是能做到的,所以线程大多数都是共享的。线程创建出来,时间片也要瓜分,比如一个进程10hs,创建了5个线程,瓜分10hs,每个2毫秒。• 线程是进程的执⾏分⽀,线程出异常,就类似进程出异常,进⽽触发信号机制,终⽌进程,进程。线程有取消的函数,但是不建议取消,因为不知道线程的状态取消了的返回值是-1。
2025-03-10 20:22:00
772
原创 分页式存储管理--虚拟地址和多级页表
但 TLB 容量⽐较⼩,难免发⽣ Cache Miss ,这时候 MMU 还有保底的⽼武器⻚表,在⻚表中找到之后 MMU 除了把地址发到总线传给内存,还把这条映射关系给到TLB,让它记录⼀下刷新缓存。⻚太⼩,虽然可以减⼩⻚内碎⽚的⼤⼩,但是⻚太多,会使得⻚表太⻓⽽占⽤内存,同时系统频繁地进⾏⻚转化,加重系统开销。那么系统中共有⻚⾯ 1048576 个(1兆个),所以描述这么多⻚⾯的page结构体消耗的内存只不过40MB ,相对系统 4GB 内存⽽⾔,仅是很⼩的⼀部分罢了。⼀个⻚的⼤⼩等于⻚框的⼤⼩。
2025-03-10 19:52:08
792
原创 Linux操作系统--信号
pending表和block表的检测在3~4之间,这样就可以在处理,自定义信号的时候再次接受新来的信号,也只能同时接受俩信号。- 阻塞特定信号,信号产生了,一定把信号要进行pending(保存),永远不递送,除非我们解除阻塞。- 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递送,而忽略是在递送之后可选的一种处理动作。- 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递送的动作。SIG_DFL default:默认。无论以什么方式发送信号,最终,都是转换到OS,让OS写入信号的。
2025-02-18 21:20:27
706
原创 Linux 操作系统中的管道与共享内存
Linux 操作系统中的管道和共享内存是强大的进程间通信机制。匿名管道适用于具有血缘关系的进程之间的单向通信,具有自动的同步互斥保护机制。命名管道是一种真正的文件,可以被多个进程访问,实现了更灵活的 IPC。共享内存提供了最快的通信速度,但需要用户自己实现保护机制。在实际应用中,根据不同的需求选择合适的 IPC 机制,可以提高系统的性能和可靠性。
2024-12-16 18:40:54
798
原创 搓个shell命令行!
本地变量表 : a=100 这种不能通过环境变量和命令行参数传给子进程,但是可以echo$a所以echo也是内建命令。所以得出有些命令必须由子进程执行,有些命令,要由shell自己执行—内建命令 built command。cd命令有问题,因为子进程执行完cd我们退出来是在父进程,还是原来的路径,要改的是父进程的pwd。shell自己执行命令,本质是shell调用自己的函数,内建命令很少差不多占5%所以要加一个步骤,检查是否是内建命令,是就自己执行,作为一个shell,获取环境变量应该从系统的配置来。
2024-11-20 21:09:41
385
原创 操作系统OS--进程
阻塞挂起状态,在内存严重不足的时候,代码和数据会换入到磁盘的swap分区,只有,取到数据进入运行队列的时候将数据换入,效率慢了,时间换空间。因为操作系统的底层是C语言写的,所以接口只能是C语言的接口,所有软件的底层,都必须和c直接或间接相关。命令行中,执行命令/执行程序,本质是bash的进程,创建的子进程了,由子进程执行我们的代码。使用系统调用,创建进程。对软硬件之间进行交互:对上要给用户提供一个稳定的,高效的,安全的运行环境(目的!对下软硬件资源的管理,稳定的,高效的,安全的,能进行良好的工作(手段)
2024-11-13 16:42:43
1007
原创 Linux 中 Git 的使用方法及代码备份
在软件开发过程中,版本控制是至关重要的一环。Git 作为一款强大的去中心化分布式版本控制软件,为我们提供了高效的代码管理方式。尤其是在 Linux 系统中,Git 更是开发者们的得力助手。然而,当我们面临重装系统的情况时,可能会面临数据丢失的风险。本文将介绍在 Linux 中如何使用 Git,并结合 Gitee(码云)进行代码备份,以确保数据的安全性。
2024-10-30 14:15:20
1135
原创 C++ 智能指针:高效的内存管理利器以及sharp_ptr模拟实现
C++ 的智能指针是一种强大的工具,可以帮助我们更有效地管理内存资源。通过 RAII 原理,智能指针在构造函数中获取资源,在析构函数中释放资源,确保资源的正确管理。不同类型的智能指针(和)提供了不同的功能,可以根据具体的需求选择合适的智能指针。在使用智能指针时,我们需要注意避免一些常见的陷阱,如循环引用等问题,以确保程序的正确性和稳定性。
2024-10-21 20:30:44
1113
原创 C++11 异常处理:优势、劣势与规范
C++11 异常处理是一种强大的错误处理机制,它具有清晰的错误信息、简化错误处理、第三方库和测试框架支持等优点。然而,它也存在执行流混乱、性能开销、资源管理问题、标准库异常体系混乱和规范使用困难等缺点。在使用 C++11 异常处理时,我们需要充分考虑其优缺点,并遵循规范,以确保程序的稳定性和可靠性。
2024-10-21 19:02:33
769
原创 C++ 右值引用深入理解:特性、优化与底层
在 C++ 中,左右值的区分对于理解语言的行为至关重要。一般来说,可以取地址的是左值,不可以取地址的是右值。同时,被const修饰的通常也被视为左值。10。
2024-10-15 19:54:59
1230
原创 红黑树:强大的数据结构之插入详解,附图
红黑树是一种自平衡二叉查找树,具有以下性质:节点要么是红色要么是黑色;根节点是黑色;每个叶子节点(NIL 节点)是黑色;每个红色节点的两个子节点都是黑色;从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。在插入新节点时,新节点初始颜色为红色,这样可以尽量减少对树结构的影响。但如果新节点的父节点也是红色,就会违反红黑树的性质,此时需要进行调整。新节点位于根节点:若新节点位于根节点,其没有父节点时,将该节点直接设为黑色即可。新节点的父节点已然是黑色。
2024-09-23 21:49:14
1144
2
原创 AVL--平衡二叉搜索树详图分析
对于 AVL 树中的任何节点,其平衡因子只能是 - 1、0 或 1。当平衡因子为 0 时,表示该节点的左子树和右子树高度相等;当平衡因子为 1 时,表示左子树比右子树高 1;当平衡因子为 - 1 时,表示右子树比左子树高 1。如果在插入或删除操作后,某个节点的平衡因子超出了这个范围(即小于 - 1 或大于 1),则树的平衡被破坏,需要进行调整操作来恢复平衡
2024-09-19 22:18:38
1014
3
原创 搜索二叉树--C++思路及实现
这个类定义了二叉搜索树的节点。它包含了键值对(_key和_value)以及指向左右子节点的指针(_left和_right构造函数允许用户在创建节点时指定键值对,也可以使用默认值。插入操作首先创建一个新节点。如果树为空,则新节点成为根节点。如果树不为空,从根节点开始遍历,根据键的大小决定向左子树或右子树移动,直到找到合适的插入位置。如果要插入的键已经存在于树中,则返回false,表示插入失败。图形解释:假设要插入键值对(5, "value5")到一个已有的二叉搜索树中。
2024-09-10 16:33:08
411
原创 《C++中继承与多态的深入剖析》
但需要注意的是,重写函数的缺省值仍然是父类中的设定。2. 赋值兼容转换:子类对象可以赋值给父类对象,但父类对象不能赋值给子类对象,这是由于子类可能包含父类所没有的额外信息。2. 多继承:一个子类拥有两个及以上的直接父类,这种形式可能会导致一些复杂的问题,如棱形继承带来的数据冗余和二义性。在 C++的编程世界中,继承与多态是两个至关重要的概念,它们为代码的组织、复用和灵活性提供了强大的支持。希望通过这篇博客,能让您对 C++中的继承与多态有更清晰的理解和掌握,从而编写出更加高效和灵活的代码。
2024-08-09 14:26:04
278
原创 C++初阶:泛型编程简介及模板的使用
泛型编程是一种编程范式,其核心思想是编写与特定数据类型无关的代码,使得代码具有更广泛的适用性和复用性。在C++中,泛型编程主要通过模板来实现。
2024-05-07 08:36:06
388
1
原创 C++初阶--类和对象(下)
当创建const变量,调用函数时,会报错,权限放大的问题我们可以在函数后加const使this变成const的 void Date :: Print () const 这个const修饰的是*this。3.若未显式定义,编译器会生成默认的拷贝构造函数。友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。传值返回, 先构造一个临时的后定义的先析构全局的,main函数之前就构造了 静态变量,第一次调用时才会构造。
2024-04-29 20:33:47
550
原创 C++初阶--类和对象(上)
以及两个构造函数:一个是无参构造函数,另一个是带参数的构造函数。传引用的效率比传值的效率高 类型转换会先生成临时变量,表达式也会产生临时变量,临时变量有常性,引用时引用的是临时变量所以要加const修饰。:在同一作用域的名字相同的参数列表(参数个数 或 类型 或 类型顺序)不同的函数,当不重载的俩名字相同的函数同时调用会调用歧义。是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务。同一类的对象的成员变量是不一样的,成员函数是一样的,使用同一的函数地址。
2024-04-15 19:48:58
593
1
原创 C语言--数据结构:堆排序(超详细简图!)
当我们创建小堆的时候我们会得到最小值,然后我们将最小值与最后一个数据交换,并将传入向下调整的堆元素个数-1,这样我们就可以保存好最大值;堆排序是一种高效的排序算法,具有稳定的时间复杂度和较低的空间复杂度。它适用于大规模数据的排序,并且相比于其他排序算法,堆排序不需要额外的存储空间。堆排序的主要思想是先将待排序的数组构建成一个堆,然后逐步将堆顶元素与堆的最后一个元素交换,并重新调整堆,使其满足堆的性质,最终得到有序序列。堆的构建和调整操作的时间复杂度均为 O(logn),而总共需要进行 n 次这样的操作。
2024-03-18 20:40:55
411
原创 C语言--数据结构:堆(完全二叉树)
堆是一种完全二叉树,其特点在于它分为大堆和小堆。:在堆中,根节点的值总是大于或小于其子节点的值,这个性质使得堆能够快速找到最大或最小值。:对于具有n个节点的堆,其高度为log2(n),这使得堆的插入和删除操作具有较好的时间复杂度。:通常使用数组来表示堆,其中根节点位于索引0,而子节点i的父节点位于索引floor((i-1)/2)。
2024-03-17 21:42:19
1821
1
原创 C语言--数据结构:树
树的概念不用记,清楚加粗的和了解其它的即可。树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。我们这里就简单的了解其中最常用的孩子兄弟表示法。
2024-03-15 09:00:00
2261
1
原创 C语言--数据结构: 栈
栈的使用就是先进后出,那么使用什么结构进行先进后出?以及先进后出用什么作用呢?编程语言使用栈来管理函数调用和返回。当一个函数被调用时,其局部变量、参数和返回地址被压入栈中,当函数执行完毕时,这些数据被弹出栈。操作系统使用栈来管理进程的内存分配和释放。每个进程通常都有自己的栈空间,用于存储函数调用、局部变量和其他临时数据。在表达式求值中,栈常用于将中缀表达式转换为后缀表达式,以便更容易进行计算。栈可以用于逆序输出数据。例如,当需要逆序输出字符串或者逆序遍历一个数据结构时,可以使用栈来实现。
2024-03-13 20:14:53
377
原创 C语言--数据结构:单链表
什么是链表,顾名思义就像一个个环环相扣的圈。那我们怎么使用编程语言实现这个链表呢?以及它的作用是什么呢?单链表是一种线性数据结构,由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。节点按顺序排列,通过指针链接在一起,形成链表。单链表可以用来存储各种类型的数据,例如整数、浮点数、字符串等等。单链表的节点可以动态分配内存,这意味着它可以根据需要灵活地增加或减少节点,不像数组一样需要在初始化时确定大小。在单链表中,插入和删除元素的操作非常高效,只需要修改节点的指针即可,无需移动其他元素。
2024-03-12 19:17:16
1728
1
原创 C语言指针:探索内存与数据的连接,基础入门(超详细!)
const修饰指针是C语言中非常有用的一个概念,它指定了一个指针变量为只读,防止对所指向的数据进行修改。通过使用const修饰指针,我们可以提供数据保护、提高代码可读性和可维护性,并允许编译器进行一些优化。在实际编程中,合理使用const修饰指针可以使代码更加健壮和可靠。同时,也应该注意使用const修饰指针的注意事项,以避免潜在的错误。继续学习和实践,你会逐渐掌握const修饰指针的使用技巧,并写出更高质量的代码。在C语言中,野指针是指指针变量存储的地址没有被正确初始化,或者指向了无效的内存地址。
2023-11-22 22:19:01
128
原创 扫雷(简易版)
₍ᐢ.ˬ.⑅ᐢ₎ 也就是说,如果我们要创建9*9的棋盘我们就要扩大成11*11的棋盘,但是我们只打印9*9的棋盘就ok。同时在玩家输入一个一个坐标排雷的时候,我们的程序要在坐标周围排雷,边界上可能会溢出,需要判断重新写代码,所以我们可以设置一个更大的棋盘来搭载空数据,来防止越界。初始结束后我们要将我们的展示棋盘打印出来,再加上坐标,也创建一个函数(这个打印函数也可以在我们敲代码时打印地雷棋盘,以便查找错误。所以我们需要俩二维数组:一个放雷的信息:地雷棋盘,一个展示给玩家看到的棋盘:展示棋盘。
2023-11-03 12:01:25
78
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人