自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 死锁问题以及读写锁和自旋锁介绍【Linux操作系统】

死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而日处于的 一种永久等待状志例如:如果想要访问一个临界区,需要申请两把锁(a锁和b锁)才能访问申请一把锁是原子的,但是连续申请两把锁就不一定是原子的了线程1抢到了锁a,线程2抢到了锁b而线程1还想要锁b,线程2还想要锁a所以他们就互相进入了彼此的锁的等待队列中,而它们手上的这两把锁就永远不可能被释放了死锁的情况不要局限于上面这一种单线程甚至都有可能出现死锁比如下面的3种情况。

2025-07-15 21:27:01 1155 22

原创 基于生产者消费者模型的线程池【Linux操作系统】

线程池是一种线程使用模式线程过多会带来调度开销,进而影响缓存局部性和整体性能而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价线程池不仅能够保证内核的充分利用,还能防止过分调度可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量需要大量的线程来完成任务,且完成任务的时间比较短比如WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。

2025-07-11 21:18:49 1137 21

原创 生产者消费者模型【Linux操作系统】

1.对于工厂来说,消费者如果直接来买商品,一个消费者一次购买的商品数量非常有限,而且一个工厂的产品种类一般并不多,所以消费者还得去不同工厂买东西,工厂为了防止卖不完,只能减少商品的生产,即。但是如果只有互斥,那么消费者如果不知道有没有数据,就只能不断地去轮询检测,每次轮询都要申请锁,那生产者线程就可能很难抢到锁,就一直生产不了数据,消费者线程就一直拿不到数据,造成恶性循环。设置条件变量,让消费者线程在条件变量的等待队列中等,当生产者线程生产数据之后,才唤醒消费者线程,去读取数据。

2025-07-05 10:29:07 1188 24

原创 线程同步【Linux操作系统】

全局条件变量可以使用。

2025-07-02 12:29:08 804 17

原创 线程互斥【Linux操作系统】

因为它会变成3条汇编指令,一条汇编指令虽然是原子的,但是3条汇编指令和在一起的操作就不是原子的了所以在CPU在执行这3条汇编指令期间,都有可能进行线程切换。比如:ticketnum=1了,线程a把1读取到寄存器之后,线程a就切换了,还没去–ticketnum线程b也来读取了,也把ticketnum=1读到寄存器里了这个时候,线程a和线程b就都会判断,ticketnum>0,就都进去抢了而且。

2025-06-29 09:44:40 1112 26

原创 线程(下)【Linux操作系统】

变量,数组,对象都可以传递过去这样就可以一次传递多个信息,也可以更好地支持C和C++混合编写我们可以定义一个任务类,里面存储一些基本信息和分配给这个新线程的任务函数即设计一个任务类,里面的成员变量就是任务函数,以及任务函数对应的参作用:创建一个线程。

2025-06-11 11:29:45 1313 27

原创 内存管理【Linux操作系统】

操作系统管理(使用)物理内存的基本单位是页框【】为什么一般是4kb大小?因为计算机科学家研究出4kb效率最高就像操作系统文件管理时,使用磁盘空间的基本单位也是数据块(一般也是4kb)一样所以磁盘中的数据加载到物理内存,就非常方便了,只需要对应的数据块中的内容,加载到对应页框里面就行了而不是需要多少,就分配多少?操作系统中存在非常多的页框,每个页框的使用情况,属于谁,是否要释放等等信息操作系统都要知道所以操作系统一定要管理页框为了描述页框,操作系统内定义了:因为页框的个数很多,所以struct pag

2025-06-04 11:42:58 1283 29

原创 线程(上)【Linux操作系统】

一个进程中的所有线程会共享进程的资源但是每个线程也有自己也有自己私有一份(即其他线程看不见)的资源①线程的id(LWP)②CPU切换线程时,线程会保存自己的上下文③线程虽然共享地址空间,但是每个线程都有自己独立的栈因为每个线程都可以调用函数,就要申请栈桢,如果共享同一个栈,操作系统太不好管理了而且每个线程有自己独立的栈,就可以做到局部性的线程之间互不影响④每个线程都有自己的errno(错误码)为了方便形成各自的日志,方便debug。

2025-05-31 11:32:21 944 29

原创 操作系统运行原理以及用户态和内核态相关知识【Linux操作系统】

时间片的本质就是进程PCB中的一个计数器因为时钟源发送时钟中断的时间间隔是固定的所以只需给每个进程的时间片,都设置成时钟源发送时钟中断的间隔的整数倍每次接收到时钟中断的时候,CPU先保护进程上下文之后,执行中断处理流程之前,会先执行一下内核中的进程调度的函数进程调度的函数就是:①判断正在CPU上的进程的时间片是否为0②不为0,则对时间片(计数器)-=时钟源发送时钟中断的间隔③为0就直接执行进程切换的代码这样。

2025-05-28 11:31:59 989 22

原创 进程信号(下)【Linux操作系统】

①因为信号一般就是用来终止进程的,信号的默认处理方法不是退出就是暂停,同一个信号根本不需要执行多次一个信号的默认处理方法执行了,也没机会再执行其他的信号的处理方法了②如果不串行执行,而是嵌套执行,那么如果因为出现异常,一直再发送同一个信号/多个信号只要调用了信号处理方法pending表中这个信号就会1→0]并且这些信号都被自定义捕捉了那么就可能执行某个信号处理方法的过程中,因为一次时钟中断,进入内核态出来的时候,看见pending表有1,就一直递归执行信号处理方法,很容易导致栈溢出。

2025-05-24 11:11:56 859 23

原创 进程信号(上)【Linux操作系统】

所以这个进程就算没有退出,CPU只要执行它的代码,就会发现状态寄存器有标志位为1,就会告诉操作系统,操作系统又会发信号杀它。操作系统作为硬件的管理者,当硬件出现问题时,就会向操作系统发送硬件中断,操作系统就自然会知道了。信号被触发(接收到信号)的时候,操作系统会把接收到的信号的编号,自动传给这个int类型的形参。进程可以阻塞(屏蔽)某个信号,屏蔽那个信号之后,即使进程接收到了这个信号,这个信号将。进程a执行2号信号的处理方法时,1,2,3,4信号都会被block表屏蔽。

2025-05-21 11:30:12 1129 23

原创 进程间通信--信号量【Linux操作系统】

比如两个进程同时看见信号量还剩一个,它们同时去抢,同时抢到手,count同时=0。我们生活中,不管是看电影还是坐高铁,都要买票,因为它们的名额都是需要竞争的资源。而且票的个数也有限,因为资源的个数有限,不能出现两个人用同一个资源的情况,存在就返回shmid。只能先分配16个进程,等一些进程使用丸了,再让剩下的进程进来用。让计数器等于分区数,这样一个进程要使用共享资源前,都先判断一下。我们上面所说的进程竞争使用共享资源的分区,本质也是如此。即:申请信号量的时候,申请的是一个/多个信号量。

2025-05-18 11:38:46 1088 20

原创 进程间通信--共享内存【Linux操作系统】

如果用户申请的物理内存不是4kb的整数倍(比如用户申请了5kb),那么操作系统依然会以4kb的整数倍给用户(即给用户8kb的物理内存)但是会以类似权限的方式,让用户看不到,用不了那多出来的空间(但是进程B想和进程A通信,进程B调用shmget的时候,得先知道进程A创建的共享内存是哪一块呀!是共享内存1,2还是3?最后,一个进程向自己的共享区中的共享内存读,一个进程向自己的共享区中的共享内存写,就可以实现进程间通信了。然后把它的起始地址通过进程的页表,与要通信的进程的共享区建立映射关系。

2025-05-17 11:43:46 973 24

原创 进程间通信--管道【Linux操作系统】

进程间通信的本质是打破进程隔离性数据流动:传递信息,支持协作资源共享:避免冗余,提升效率行为协调:同步操作,防止竞态条件选择合适的 IPC 机制需权衡性能需求、开发复杂度、系统架构本地高性能:优先共享内存 + 信号量跨网络扩展:选择套接字或 RPC简单通知:使用信号或管道。

2025-05-10 11:59:19 1123 33

原创 可执行文件格式(ELF格式)以及进程地址空间第二讲【Linux操作系统】

⑤PC寄存器把。

2025-05-07 10:46:25 1044 24

原创 动静态库【Linux操作系统】

例第三方库:libsss.a。

2025-05-04 10:06:57 874 23

原创 软连接和硬连接【Linux操作系统】

灵活性:软链接提供了跨文件系统和目录链接的灵活性,这对于管理和访问文件系统非常有用。即使目录被移动或重命名,只要路径正确,软链接仍然可以指向正确的目标。如果软链接指向的路径是一个循环,文件系统在解析链接时能够发现并报错,而不是陷入无限循环。数据备份:创建硬链接,确保即使文件名被删除,文件内容仍然可以通过其他硬链接访问。用户创建的目录的名字五花八门,Linux也不可能针对性的进行处理。,包含指向目标文件的路径。因此,即使软链接指向的是一个目录,软链接出来的文件是一个独立的文件,它有自己的inode。

2025-05-02 10:48:56 843 21

原创 磁盘文件系统【Linux操作系统】

因为每个组的inode个数固定,所以GDT记录了其起始inode号之后,也就知道自己的inode号的范围了。①找到文件所处的目录,先使用目录的上级目录中存储的该目录自己的inode号,找到该目录的inode。要查找a.txt的inode号,就要找到它所处的目录的inode号,也就是目录xyz的inode号。这样下次用户再查找这个目录下的文件时,就直接查找内存中缓存的多叉路径树,不需要再去磁盘中进行查找了。然而,对于那些从未被访问过的文件,尤其是在大型的文件系统中,可能不会有对应的。

2025-04-30 11:23:09 1563 16

原创 重定向和语言级缓冲区【Linux操作系统】

因为操作系统检测的是文件类型,是存储在struct file中的,重定向的时候相当于把struct file换掉了。进程的PCB不变,进程PCB中的struct files_struct*类型的指针指向的结构体变量不变。printf的时候,底层就用变量中存储的文件描述符调用write对文件描述符为1的文件进行写入。就是把文件描述符表中,下标为参数①的元素中存储的地址,拷贝覆盖到参数②下标对应的元素中。①函数完成之后,第一个参数fd1下标中,存储的地址不变,所以指向的文件不变。

2025-04-26 10:26:44 1207 23

原创 文件【Linux操作系统】

在磁盘中的文件:文件=内容+属性文件什么时候才会被打开?文件只有在代码编译形成可执行程序,可执行程序加载到内存变成进程,运行到打开文件的函数时文件才会被打开访问文件的是谁?是进程是进程打开文件,再使用函数封装的系统调用对文件进行访问的文件在打开之前,在磁盘中进程运行的本质是:进程对文件读取/写入时,本质是数据流转(拷贝),所以这个操作也是由CPU执行但是根据冯诺依曼体系结构,CPU是不能直接访问磁盘的,因为这样太慢了所以文件必须加载到内存之后,才能直接访问所以打开文件的本质是把文件加载到内

2025-04-23 11:34:29 1223 29

原创 进程控制(下)【Linux操作系统】

要替换上来的可执行程序在命令行如何执行[即:命令行参数argv数组的元素,最后必须以nullptr结尾]

2025-04-19 11:56:18 1389 23

原创 进程控制(上)【Linux操作系统】

子进程被创建的时候:会继承父进程的mm_struct和页表①父进程在使用fork创建子进程之前,就会这样子进程继承到的页表中的数据区就也是只读的②当子进程/父进程尝试修改数据区中的数据时,就是修改只读数据项,③系统发现缺页中断之后,就会检测1,如果发现用户要修改的这个区域一定是只读的,就把进程杀掉2,如果这个区域一定是读写的,只是页表中的权限设置成只读的了,此时系统就会进行写时拷贝所以:不止创建子进程写时拷贝的时候是这种原理。

2025-04-16 12:19:30 1466 21

原创 类型转换【C++】

这个很简单,和C语言的一样,之前已经讲过了,不必多说:主要就是通过把内置类型传给,自定义类型的构造函数实现转换语法上,在转换的时候内置类型传给构造函数构造出临时对象,再由临时对象进行赋值语法:只要一个参数就能调用构造函数时:类名+对象名=那唯一的参数值例:A a=100要多个参数才能调用或者需要使用多个参数类名+对象名={多个参数}例: A a={110,200}实际上呢,编译器很可能会优化:例隐式类型转换[在声明前构造函数前加关键字,可以阻止隐式类型转换,但是阻止不了显示(强制)类型

2025-04-12 10:03:44 1042 29

原创 智能指针【C++】

把一个shared_ptr a拷贝给另一个shared_ptr b的时候,a会让b会指向同一份资源,资源的引用计数就会++但是weak_ptr的赋值重载和拷贝构造的参数可以直接接收shared_ptr,去指向这个shared_ptr指向的资源。因为这样的话每个shered_ptr对象都有一个自己的引用计数,看到的和修改的都不是同一个,这记个蛋的数?而它们指向的两个new出来的节点内部,都有一个(多个)的shared_ptr的成员变量,设分别为px和py。

2025-04-06 11:48:05 929 21

原创 异常【C++】

异常总体而言,利大于弊,所以工程中我们还是鼓励使用异常的。所有高级语言基本都是用异常处理错误,这也可以看出这是大势所趋。

2025-04-05 11:37:26 1216 25

原创 lambda和function还有bind【C++】

因为全局变量在lambda中本来就能直接使用,没必要捕捉而局部变量根本捕捉不了。

2025-04-02 12:01:29 1375 21

原创 右值和右值引用【C++】

左值是一个表示数据的表达式它最主要的特点就是:①可以取地址②生命周期比较长,最短都是局部变量的生命周期③可以出现在=左边,即可以被修改然后把地址给引用或者指针,就可以通过引用或者指针改变这个左值左值引用就是给左值取别名左值可以出现在=的左右两边。

2025-03-29 16:11:09 867 22

原创 进程地址空间(上)【Linux】

子进程又会继承父进程的mm_struct和页表,而且不修改的时候,里面的值是完全一样的,虚拟地址和物理地址也是一样的。而且一次时间片使用完之后,这个进程等待时,还要把使用完的加载到内存的这一部分在释放掉,节约内存。但是因为页表的映射,在虚拟内存中所有的代码和数据是在一起的,进程使用的时候也十分方便。所以子进程能通过自己的页表,找到父进程全局变量对应的物理地址,也就能看见里面的值了。如果只有r权限,那它就只能读,不能被修改。进程因为操作系统给它画的大饼(进程地址空间)它就认为我想干嘛是一定有内存的,

2025-03-20 11:08:18 1298 26

原创 命令行参数和环境变量【Linux操作系统】

记录当前用户的家目录bash的cwd是会跟着用户的工作路径的变化而变化的。

2025-03-15 11:51:34 1064 27

原创 进程(下)【Linux操作系统】

就像考进一个学校,再拿到录取通知书之前你的信息就已经被学校记录在学生管理系统里面了,所以在你人进入学校之前,就有了你对应的数据对象了。CPU调用进程的时候从左往右进行调用,如果一个桶中有进程,就直接拿着桶里的第一个元素调度(插入进程也是头插)进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。如果一个用户把自己的一个进程的优先级调的特别高,那么其他用户的进程就有可能一直无法调度。一般修改的是它的nice(NI)值,通过这个间接修改进程的优先级。

2025-03-12 14:59:45 1526 29

原创 进程(上)【Linux操作系统】

pid:唯一标识一个进程记录该进程是由磁盘中的那个可执行文件生成的,记录了它的绝对路径例:进程A是被test生成的,那么exe存储的就是test的绝对路径(/home/xyc/dir/test)cwd:当前进程在那条路径下运行一般是继承父进程的cwd进程在哪条路径下启动,那么它的cwd最开始就是那条路径例我在路径/home/xyc这条路径下启动了进程test那么test最开始的cwd就是/hone/xyc。

2025-03-09 11:39:02 1029 30

原创 冯诺依曼体系结构的理解和操作系统的极简介绍【Linux操作系统】

操作系统本质是一个进行软硬件资源管理的软件用户只需要发出命令,操作系统接收到命令之后就会自动地把命令执行完毕。

2025-03-06 15:33:06 1229 26

原创 Linux的用户和权限【Linux操作系统】

但是这个时候因为目录是共享的,所有人都对共享目录具有rwx权限,就意味着所有人都可以删除共享目录下的所有文件。并把文件设置成只有所属组拥有rwx的权限,这样就只有b能修改和看这个文件了。③再按字母i,进入插入模式,把root改成要添加到白名单的用户的用户名。即把u(拥有者)和g(所属组)对test的三个权限全部都改为没有权限。把o(other)的x权限改为可执行,r和w为不可执行。普通用户更改文件的所属组和拥有者时,是不能直接修改的。即可让g(所属组)对文件test.c的r和x的权限。

2024-12-04 21:23:23 2566 54

原创 Linux基本指令【Linux系统】

显示指定[指定方式 :]路径中的文件使用语法: ls的常用选项Linux中,文件名以开头的文件是隐藏文件显示用户当前所处的路径语法: 切换到指定路径下语法: 任何一个目录[包括根目录/]中都有两个默认的目录,即 和 ,这两个默认目录类似于指针, .指向目录自己, …指向目录的上一级目录注意:,因为根目录没有上级目录了我们可以使用切换到上级路径Linux系统中,磁盘上的⽂件和⽬录被组成⼀棵,每个节点都是⽬录或⽂件理解路径存在的意义:树状组织⽅式,都是为了保证快速定位查找到指定的⽂件,⽽定位⽂

2024-11-24 11:28:03 1255 45

原创 平衡二叉搜索树之 红黑 树的模拟实现【C++】

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,只能是Red或Black。通过对任何一条从根到空节点的路径上各个结点着色方式的限制红黑树确保没有一条路径会比其他路径长出俩倍,即最长路径的长度最多是最短路径长度的两倍,这样的话就能保证红黑树是接近平衡的树红黑树类的成员变量只有一个,就是指向红黑树的根节点的指针为什么红黑树新插入的节点【或者新节点】一定是红色的?其实就是维护成本的问题:1.如果新插入的节点为黑色因为插入之前,这棵树一定是红黑树。

2024-11-16 10:28:13 2255 63

原创 平衡二叉搜索树之 AVL 树的模拟实现【C++】

我上一篇文章提到的普通二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。AVL树就可以解决上述问题,让搜索树的查找效率在任何情况下都能稳定是O(logN)保证每个结点的左右子树高度之差的绝对值不超过1这样就能保证树中的节点分布接近满二叉树,高度非常接近logN【N为树中节点的个数】,进而让一次查找的效率为O(logN)为什么是保证每个结点的左右子树高度之差的绝对值不超过1,而不是保证左右子树高度一样呢?

2024-10-05 14:22:42 1766 68

原创 普通二叉搜索树的模拟实现【C++】

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

2024-09-28 11:22:32 1772 62

原创 多态(下)【C++】

纯虚函数是一种特殊的虚函数,它是没有函数体的虚函数class <类名>public:virtual <类型><函数名>(<参数表>) = 0;纯虚函数的特点:子类继承父类的纯虚函数之后,可以对它进行重写,在子类中被重写的纯虚函数就拥有函数体,并能正常使用了纯虚函数只有声明,没有具体的实现。它为子类提供了一个统一的接口,具体的实现细节则由各个子类根据需要来定义。纯虚函数的声明以必须以= 0结尾,表明该函数没有实现,它只是一个接口。不能直接调用没有被重写的纯虚函数,因为它们没有实现。

2024-09-16 10:50:42 1423 72

原创 多态(上)【C++】

在C++中,虚函数是使用virtual关键字修饰的非静态成员函数。虚函数的主要作用是允许在派生类中重新定义基类的函数,从而实现多态。关于虚函数的一些注意点:虚函数就是为了实现多态而存在的,而且支持虚函数是需要付出一定代价的所以如果不实现多态,就不要定义虚函数静态成员函数不能做虚函数因为①虚表指针存在对象里,但是静态成员的生命周期比对象长,而且静态成员函数里面没有this指针,就找不到对象②因为静态的特性:在以该父类为起始的整个继承体系中只有一份,如果实行多态的话就有多份了,这不符合静态的特性。

2024-09-13 15:27:24 1787 63

原创 继承(下)【C++】

举个例子数据冗余:即D类里面有两份A的成员,而且这两份完全重复,没有必要都存在访问会有二义性:因为D类里面有两份A的成员,那么通过D类的对象访问A类的成员就不知道要访问这两份中的那一份。

2024-08-22 17:48:19 1915 91

空空如也

空空如也

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

TA关注的人

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