自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 Linux系统编程--线程概念与控制

本文从操作系统角度重新定义了进程和线程的概念:进程是系统资源分配的基本实体,而线程是CPU调度的基本单位。Linux通过独特的轻量级进程(LWP)模型实现线程,多个task_struct共享同一地址空间来模拟多线程。与传统操作系统不同,Linux内核不区分进程和线程,统一使用task_struct进行管理调度。文章还通过"家庭模型"类比,形象说明进程如同资源分配的家庭单位,线程则是共享资源的家庭成员。这种设计使Linux线程实现更高效,完全复用进程管理机制,无需额外线程调度逻辑。

2025-09-25 00:24:41 847

原创 Linux系统编程--进程信号

本文介绍了Linux进程信号的概念与应用。首先通过生活实例类比信号机制,如闹钟、交通灯等,解释信号的核心特性是中断当前任务处理紧急事件。然后通过代码示例展示如何捕捉和处理信号(如Ctrl+C对应的2号信号),并详细阐述了前台与后台进程的区别及管理方法。重点讲解了进程的同步与异步处理机制,说明信号是一种异步通知方式,能够在不阻塞主进程的情况下处理外部事件。文章还介绍了任务控制命令(jobs、fg、bg)和终止后台进程的方法,帮助读者深入理解信号在系统进程管理中的作用。

2025-09-21 11:23:09 899

原创 Linux系统编程--进程间通信

本文介绍了进程间通信(IPC)的概念和实现原理。首先阐述了进程独立性与协作需求之间的矛盾:进程需要独立性保证稳定性,但实际应用中又需要协作完成复杂任务。然后说明了IPC的三个主要目的:数据传输、资源共享和通知控制。文章重点分析了管道这一经典IPC机制,包括其基于文件系统的设计思想,以及匿名管道通过fork()继承文件描述符表和pipe()系统调用实现进程间通信的具体原理。最后强调了标准规范对跨平台IPC实现的重要性,如System V IPC、POSIX标准等。全文围绕"让不同进程看到同一份资源&

2025-09-09 21:38:05 530

原创 Linux系统编程--库的制作与原理

本文介绍了库的概念、分类及制作原理。库是预先编写好的可复用代码,分为静态库(.a/.lib)和动态库(.so/.dll)。重点讲解了静态库的制作流程:首先将源文件编译为目标文件(.o),然后使用ar命令打包成静态库(.a)。使用时通过gcc的-I、-L、-l选项指定头文件路径、库文件路径和库名。最后说明了如何将自定义库安装到系统标准路径,以及用Makefile实现自动化构建。静态库通过直接链接到可执行文件中实现代码复用。

2025-09-05 19:54:47 785

原创 Linux系统编程--Ext系列文件系统

摘要:本文介绍了Ext系列文件系统的概念及其与磁盘结构的关系。首先阐述了文件系统的基本功能——管理未打开文件,随后详细解析了磁盘的物理结构(盘片、磁头、传动臂等)和存储结构(磁道、扇区、柱面)。重点描述了CHS寻址方式和磁盘逻辑结构,将磁盘抽象为三维数组,进而转换为LBA地址。通过对比磁带结构,说明了磁盘数据的线性读取逻辑,并举例说明了LBA地址与CHS定位的转换过程。文章从硬件层到操作系统层,系统性地讲解了磁盘管理的基础原理。

2025-09-04 09:00:00 1096

原创 Linux系统编程--基础IO

文章摘要:本文系统介绍了基础IO操作,重点围绕文件概念展开。首先从狭义和广义层面定义了文件,指出文件本质是内容加属性,并强调所有文件操作都需通过操作系统进行。文章回顾了C语言文件操作接口,如fopen、fwrite等,并通过示例代码演示了读写操作。特别说明程序启动时默认打开stdin、stdout、stderr三个标准流的原因及作用。最后详细解析了C语言中不同文件打开方式的区别,包括r、r+、w、w+、a等模式的功能特点,为理解文件IO操作提供了全面基础。

2025-09-03 10:36:30 616

原创 Linux系统编程--进程控制

本文主要介绍了Linux进程控制的关键技术,包括进程创建、终止和写时拷贝机制。文章首先详细解析了fork函数的工作原理,阐述了内核如何通过复制父进程数据结构并采用写时拷贝技术来高效创建子进程。接着分析了进程退出的三种场景及其意义,并解释了进程终止的本质是释放系统资源。重点剖析了写时拷贝的实现机制及其两大优势:降低进程创建成本、节省物理内存。最后简要提及了fork的常规用法和调用失败的常见原因。这些内容为理解Linux进程管理机制提供了重要基础。

2025-08-30 10:33:13 912

原创 Linux系统编程--进程概念(全文六万五千字精讲!!)

本文介绍了进程的基本概念和基本操作。进程是程序的一个执行实例,从内核角度看是分配系统资源的实体。Linux系统中使用task_struct结构体描述进程信息,并通过双向链表组织管理。操作方面,介绍了查看进程的多种方法(ps命令、/proc目录查看),以及结束进程的两种方式(Ctrl+C、kill命令)。最后说明了通过系统调用getpid()和getppid()获取进程标识符的方法,并附有示例代码演示如何获取并打印进程ID和父进程ID。进程管理本质上是操作系统通过先描述后组织的方式对进程信息进行管理。

2025-08-23 21:11:13 1210 1

原创 树莓派5终极指南:从零开始配置国内源与OpenCV开发环境

本文详细介绍了树莓派5在国内环境的配置指南,主要包括两个核心内容:1)更换国内镜像源(推荐清华大学镜像源)以解决软件安装缓慢问题,包括备份原文件、修改apt和pip配置的完整步骤;2)配置OpenCV开发环境,重点解决依赖包安装问题,并推荐使用Python虚拟环境进行开发。文章针对配置过程中可能遇到的"libjasper-dev缺失"等常见错误提供了解决方案,帮助用户快速搭建高效的开发环境。

2025-08-20 11:57:37 1630

原创 Linux系统编程--计算机的体系结构

本文主要介绍了计算机体系结构中的冯诺依曼体系和操作系统的基本概念。冯诺依曼体系由输入设备、输出设备、运算器、存储器和控制器五部分组成,CPU通过内存间接访问外设,所有程序必须加载到内存才能运行。操作系统作为管理软硬件资源的软件,通过系统调用接口为用户提供服务,其管理方法是对被管理对象先描述再组织,本质是对数据的管理。文章还通过层状结构展示了软硬件之间的访问关系,解释了操作系统设计的核心目的和功能,包括进程管理、文件系统、内存管理和驱动管理等模块。

2025-08-09 22:51:43 889

原创 Linux系统编程--基础开发工具

本文介绍了Linux基础开发工具中的软件包管理器及其生态。主要内容包括:1)Linux下三种软件安装方式(源码编译、rpm安装、yum安装),重点说明yum作为常用包管理器的优势;2)Linux软件生态的构成要素(社区、文档、软件体系等)及其良性循环机制;3)国内外软件源镜像站的介绍,包括阿里云、清华等国内镜像源;4)软件包依赖问题的解决方案。文章还详细讲解了yum的具体操作命令,如查看软件包列表等。通过类比手机应用商店,帮助理解Linux软件包管理机制。

2025-08-07 22:32:31 448

原创 Linux系统编程--权限管理

本文介绍了Linux系统的权限管理机制,主要内容包括: Shell命令运行原理:Shell作为命令行解释器,负责将用户指令传递给内核执行,并返回结果。它通过创建子进程执行命令,避免自身崩溃。 Linux用户分类与切换:系统分为超级用户(root)和普通用户,可通过su命令切换,支持sudo临时提权机制。 文件权限管理: 文件访问者分为所有者(u)、所属组(g)和其他用户(o) 文件属性包含类型标识(d目录、-普通文件等)和权限(rwx) 权限由三组rwx组成,分别对应所有者、组和其他用户的读写执行权限 特殊

2025-08-07 22:05:02 1203

原创 C++11

C++11 引入了重要的新特性,包括统一的列表初始化和 initializer_list 容器。列表初始化允许使用 {} 对任意对象进行初始化,支持内置类型和自定义类型,编译器会自动优化构造过程。initializer_list 类封装了常量区数据,使 STL 容器能够通过列表初始化构造对象。这些改进使 C++ 更加现代化,简化了容器的初始化操作,提升了代码简洁性和性能。C++11 作为重大更新版本,为后续 C++14/17/20 的发展奠定了基础。

2025-07-20 22:09:40 949

原创 C++--哈希表封装实现 unordered_map 和 unordered_set

本文介绍了哈希表封装实现 unordered_map 和 unordered_set 的方法。主要内容包括: 分析了SGI-STL30版本中哈希表的实现框架,hash_map和hash_set通过复用同一个hashtable实现key和key/value结构。 模拟实现了unordered_map和unordered_set的底层哈希表框架: 使用模板参数T控制哈希节点数据类型 通过仿函数MapKeyOfT/SetKeyOfT获取键值 解决string类型取模问题,特化HashFunc仿函数 关键点: 哈希

2025-07-16 12:02:12 1115

原创 C++--哈希

哈希是一种通过哈希函数建立关键字与存储位置映射关系的数据组织方式,可实现快速查找。关键概念包括负载因子(衡量空间利用率与冲突概率)、哈希函数设计原则(如直接定址法、除留余数法等)以及哈希冲突解决方法(闭散列的线性/二次探测和开散列的链地址法)。闭散列通过探测空位解决冲突,而开散列通过链表链接冲突元素。文中还探讨了不同哈希函数的适用场景及其优缺点,强调设计高效哈希函数以减少冲突的重要性。

2025-07-15 19:15:35 359

原创 C++--unordered_set和unordered_map的使用

Key 就是 unordered_set 底层关键字的类型。unordered_set 默认要求 Key 支持转换为整形,如果不支持或者想按自己的需求实现可以将 Key 转成整形的哈希函数传给第二个模板参数。unordered_set 默认要求 Key 支持比较相等,如果不支持或者想按自己的需求实现可以将 Key 比较相等的函数传给第三个模板参数。unordered_set 底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第四个参数。

2025-07-13 22:57:09 825

原创 C++--红黑树封装实现set和map

为了让 end() 能够指向最右节点的下一个节点, stl 源码中增加了一个哨兵位的头结点,该节点的 left 指向这棵树的最左节点,也就是 begin(),right 指向这棵树的最右节点,parent 指向 nullptr,然后让根的父节点指向它,最右节点的 right 也指向它,所以在 stl 源码的实现中这个哨兵位头结点就是 end()。如图:it指向11,11右为空,11是8的右,11所在子树访问完了,8所在子树也访问完了,继续往上找,8是13的左,那么下一个访问的结点就是13。

2025-07-13 20:41:23 792 1

原创 牛客 OR36.链表的回文结构

题目描述:对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。创建新的数组,遍历原链表,将链表节点中的值放入数组,在数组中判断是否为回文结构。,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。给定一个链表的头指针。

2025-07-11 15:40:05 389

原创 C++--红黑树

红黑树是一种平衡二叉搜索树,但和 AVL 树使用高度来控制平衡不同,红黑树在每个结点上增加一个存储位来表示结点的颜色,可以是Red或Black,然后通过对任何一条从根到叶子的路径上各个结点着色方式的限制来达到接近平衡。红黑树通过对每个节点颜色的限制,从而使得整棵树的最长路径不超过最短路径的两倍 (注意是整棵树,对子树没有要求),这样红黑树就可以达到接近平衡。注意:因为红黑树只要求整棵树中最长路径是最短路径的两倍,所以红黑树是近似平衡的,即子树中某一路径可能比另一条路径长两倍不止;

2025-07-11 15:39:08 1533

原创 牛客 CM11.链表分割

给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。题目描述:现有一链表的头指针 ListNode*

2025-07-10 19:06:30 252

原创 C++--异常

实际上很多公司都会自定义自己的异常体系统进行异常管理。公司中的项目一般会进行模块划分,让不同的程序模块或小程序完成不同的模块,如果不对抛出异常事件进行规划,那么负责模块层抛出异常的程序员将无法知道因为需要抛出各类型的异常。因此实际公司定义了一套集中的规范体系,首先定义一个最基础的异常类,所有人抛出的异常都必须继承该类异常的最低类型,因为异常处理可以仅基类异常抛出的最低类型异常,因此最基础类的异常类型就抛出了。

2025-07-10 19:05:18 689

原创 LeetCode 21. 合并两个有序链表

以上代码中在插入 l1 和 l2 的时候分链表为空和不为空的代码十分冗余,可以先通过malloc 为链表分配一个哨兵位就可以解决这个问题,最后再将哨兵位给释放掉即可。新链表是通过拼接给定的两个链表的所有节点组成的。题目描述:将两个升序链表合并为一个新的。

2025-07-08 17:19:33 284

原创 C++--AVL树

在前面学习二叉搜索树时提到,二叉搜索树的查找效率为 O(N),因为当数据有序或接近有序时,构建出来的二叉搜索树是单分支或接近单分支的结构,此时树的高度接近 n,所以最坏情况下二叉搜索树的查找效率为 O(N)。为了应对上面这种情况,两位俄罗斯的数学家 G.M.Adelson-Velskii 和 E.M.Landis 在1962年提出了一种解决办法,当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1 (需要对树中的结点进行调整来实现),即可降低树的高度,从而减少平均搜索长度。

2025-07-08 17:18:15 1208

原创 LeetCode 面试题 02.02. 返回倒数第 k 个节点

题目描述:实现一种算法,找出单向链表中倒数第 k 个节点。

2025-07-07 20:11:11 236

原创 C++--map和set的使用

set 是按照一定次序存储元素的容器,其底层是一棵平衡二叉搜索树 (红黑树),由于二叉搜索树的每个节点的值满足左孩子 < 根 < 右孩子,并且二叉搜索树中没有重复的节点,所以 set 可以用来排序、去重和查找,同时由于这是一棵平衡树,所以 set 查找的时间复杂度为 O(logN),效率非常高。同时,set 是一种 key 模型 的容器,也就是说,set 中只有键值 key,而没有对应的 value,并且每个 key 都是唯一的。

2025-07-07 20:09:53 1244

原创 LeetCode 876. 链表的中间结点

当你遇到一个链表问题时,可以问自己以下几个问题来判断是否适用快慢指针:我是不是在寻找一个特殊位置的节点,而不是特定值的节点?这个问题能否通过两个指针的“追及”或“相对距离”来解决?我能否通过让一个指针比另一个走得快,或者先走几步,来创造出解决问题的有利条件?如果答案是肯定的,那么快慢指针很可能就是解决问题的金钥匙。

2025-07-06 09:08:18 169

原创 C++--二叉搜索树

给一个单词word,判断该单词是否拼写正确,可以将 K 的类型定义为 string,然后将英语词库中的所有单词作为 key,构建一颗二叉搜索树,然后在二叉搜索树中对用户写出的每一个单词进行查找,如果找不到,则说明该单词拼写错误。那么这样的效率显然是无法满足需求的,后面需要继续了解二叉搜索树的变形,平衡二叉搜索树AVL树和红黑树,才会适用在内存中存储和搜索数据。,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文 <word, chinese> 就构成一种键值对;

2025-07-06 09:05:44 1185

原创 LeetCode 206. 反转链表

*注意:**这个解法仍有内存泄漏的问题,因为就链表的内存没有办法释放。,请你反转链表,并返回反转后的链表。: 指向当前需要反转的节点,初始为。题目描述:给你单链表的头节点。的下一个节点,防止链表断裂。: 指向前一个节点,初始为。遍历链表,对于每个节点。

2025-07-04 23:51:02 277

原创 C++--多态

下面所提及的多态都是运行时多态(动态多态)。以下程序输出结果是什么( )A: A->0 B: B->1 C: A->1 D: B->0 E: 编译出错 F: 以上都不准确class Apublic:public:p->test();return 0;在主函数中首先观察到**创建了一个子类指针p用来指向一个子类对象B**,然后通过p调用父类的test()函数。这里可以看到test函数中调用了func函数,但是这里是由this去调用的func。

2025-07-04 23:47:27 1226

原创 C++--继承

继承(inheritance)机制是面向对象程序设计使代码可以复用的重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称为派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前接触的复用都是函数复用,而继承便是类设计层次的复用。下面在没有学习到继承之前设计了两个类Student和TeacherStudent和Teacher都有姓名、年龄等成员变量,都有Print这个成员函数,然而这些内容在这两个类中是重复出现的,设计到两个类里面就是冗余的。

2025-07-01 13:43:39 821

原创 C++--模版进阶

本文介绍了C++模板的进阶应用,主要包括非类型模板参数、模板特化和分离编译。非类型模板参数允许使用常量作为模板参数,类似宏定义但更灵活。模板特化分为函数模板特化和类模板特化,其中类模板特化又分为全特化和偏特化,用于处理特殊类型的情况。分离编译模式下,模板的声明和定义通常需要放在同一文件中以避免链接错误。文章通过示例代码展示了这些概念的具体应用,帮助读者更好地理解和使用C++模板的高级特性。

2025-06-11 00:22:45 1040

原创 C++--stack和queue的使用及其模拟实现

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。Java 语言非常关注设计模式,而 C++ 并没有太关注,但是一些常见的设计模式还是要学习。迭代器模式其实在前面学习stringvector和list时就已经接触过设计模式了。迭代器就是一种设计模式。迭代器模式是封装后提供统一的接口iterator在不暴露底层实现细节的情况下,使得上层能够以相同的方式来访问不同的容器。适配器模式适配器模式则是将一个类的接口转换成客户希望的另外一个接口,即根据已有的东西转换出想要的东西。

2025-06-09 20:59:57 948

原创 C++--list的使用及其模拟实现

可以看到,list sort 的效率远低于 vector sort,甚至于说,直接使用 list sort 的效率都不如先将数据拷贝到 vector 中,然后使用 vector sort,排序之后再将数据拷贝回 list 中快。至此也能明白为什么 list sort 接口使用的非常少了。**注意:**在 release 版本下测试软件或算法性能得到的结果要比在 debug 版本下得到的结果具有参考意义。

2025-06-07 21:16:40 883

原创 C++--vector的使用及其模拟实现

迭代器失效一定会导致错误,所以在平时使用迭代器的时候为了保证程序的跨平台性,统一认为迭代器失效之后,必须更新后才能再次使用。

2025-06-04 22:24:36 868

原创 C++--string的使用及其模拟实现

C++中的string类简介 C++标准库提供的string类解决了C语言字符串操作中的诸多问题,如内存管理、边界检查等,并遵循面向对象思想。string本质上是一个模板类basic_string<char>,支持多种编码方式。 VS和g++编译器对string的实现不同:VS采用固定16字节小缓冲区优化,以空间换时间;g++则使用写时拷贝技术提高效率。string类提供了丰富的接口,包括构造函数、迭代器、运算符重载等。 C++11引入的auto关键字和范围for循环简化了string的遍历操作

2025-05-30 11:06:21 1107

原创 C++--STL简介

STL(标准模板库)是C++标准库的核心部分,提供了一系列可复用的数据结构和算法框架。STL起源于惠普实验室的原始版本,随后衍生出多个版本,如P.J.版本、RW版本和SGI版本,其中SGI版本因其可移植性和高可读性被广泛采用。STL包含六大组件,极大地简化了C++编程,避免了重复造轮子,提升了开发效率。由于其重要性,STL在C++学习、面试和实际工作中都是重点考察内容,掌握STL是C++程序员的基本要求。

2025-05-20 23:18:01 321

原创 C++--模版初阶

在C++中,存在这样一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的铸件(即生成具体类型的代码)。泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。函数模版类模版。

2025-05-20 23:16:53 1452

原创 C++--内存管理

C++动态内存管理和C语言动态内存管理最大的不同在于二者对自定义类型的处理:C语言 malloc/calloc/realloc 函数只负责开辟空间,free 函数只负责销毁空间。而C++在申请自定义类型的空间时,new 会调用构造函数,delete 会调用析构函数,完成对应对象的初始化和销毁。class Apublic://构造函数: _a(a)cout << "A 构造" << this << endl;//析构函数~A()cout << "A 析构" << this << endl;

2025-05-19 23:16:32 811

原创 C++--类和对象

class 为定义类的关键字,className为类的名字(由程序员自行决定)同样也是类的类型,{} 中为类的主体,注意类定义结束时后面分号不能省略。类体中的成员称为类的成员:类中的变量称为属性或成员变量;类中的函数称为方法或成员函数。//类体:由成员变量和成员函数组成 };//注意后面的分号为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或后面加 m 开头,注意 C++ 中这个并不是强制的,只是一些惯例,要看具体的要求。

2025-05-18 15:01:30 630

原创 LeetCode 27.移除元素

这中方法虽然简单易懂,但仍然后很多小细节需要注意。而且这种方法并不能通过leetcode的平台测试,因为其空间复杂度为ON2O(N^2)ON2,超出了时间限制不合符题意。双指针法是一种非常常见的算法技巧,特别适用于处理数组、链表或字符串等序列结构的问题,尤其是涉及到原地修改或者查找特定条件的元素对时。

2025-05-05 23:45:04 625

空空如也

空空如也

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

TA关注的人

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