操作系统编程
文章平均质量分 92
学习操作系统编程技术
大白同学421
C++方向持续学习中
我的gitee账号:https://gitee.com/da-bai-classmate
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
【Linux】线程池
shared_ptr大部分操作(增加引用计数,复制,读取等)都是安全的,因为它的引用计数操作是原子的,但是如果是对指针本身做修改就可能不安全;一个函数是线程安全的意味着:当多个线程同时执行这个函数时,无论操作系统如何调度这些线程,函数总能产生预期的正确结果,不会出现数据竞争、脏读、死锁等问题。A保持自身资源的同时请求B的资源,B保持自身资源的同时又请求A的资源,造成死循环。是指两个或多个进程(或线程)在执行过程中,因争夺资源而造成的一种相互等待的现象,若无外力干涉,这些进程都无法继续推进。原创 2025-11-28 11:30:00 · 1658 阅读 · 0 评论 -
【Linux】日志与策略模式
每次遇到<<都会循环进入<<重载函数,直到<<结束,临时变量就要被析构了,然后调用LogMessage的析构函数进行刷新策略——把前面得到的_loginfo内容通过我们激活的刷新策略刷新出来。所以可以显示当前文件(main.cc)和当前行号(9),然后进入Log类的()重载函数中,得到一个LogMessage临时变量,期间会调用LogMessage的构造函数,且进入<<重载函数中。在大型软件工程中,日志不仅仅是一个文件,它是一个完整的子系统,是系统的“神经系统”,负责将内部状态不断地反馈出来。原创 2025-11-24 20:45:00 · 711 阅读 · 0 评论 -
【Linux】信号量
信号量是一种用于控制多个线程/进程对共享资源访问的同步机制,本质上是一个计数器(记录了资源的剩余数量),配合两个原子操作:P 操作(等待/获取):sem_waitV 操作(发布/释放):sem_post我们申请信号量的本质其实就是预定资源,申请信号量、释放信号量的前提是要看到同一个信号量,那么信号量本身共享资源,所以PV操作必须有原子性,信号量其实就是相当于资源的锁。原创 2025-11-21 06:00:00 · 758 阅读 · 0 评论 -
【Linux】线程同步
当队列满时,往队列⾥存放元素的操作也会被阻塞,直到有元素被从队列中取出(以上的操作都是 基于不同的线程来说的,线程在对阻塞队列进程操作时会被阻塞)(假如顾客去超市买东西的时候刚好是供应商供货给超市的时候,而你要买的东西虽然在供应的货物里面但还没上架,那么你还是买不到你想要的东西,如果你强行拿了,可能导致超市的货物数量出错)我们前面的示例传递的是整数类型的数据,但是我们线程间通信的时候不仅可以传递整数、浮点数、字符这样的数据,还可以传递函数、类对象这样的数据,从而实现给线程派发任务的功能。原创 2025-11-18 05:00:00 · 1426 阅读 · 0 评论 -
【Linux】线程互斥
经过分析,我们能够明白,真正加锁的步骤就是xchgb,但lock的每一步都可能会切换线程,如果在xchgb执行后切换线程,锁资源会被抢夺吗?我们可以设想:假如线程A刚执行完xchgb这一步CPU就切换到线程B,那么线程A要保存自己的上下文数据(下一步要执行if语句,寄存器%al数据=1......),并且此时的mutex中的数据被交换后变成了0,所以此时线程B再执行加锁步骤时,%al寄存器和mutex中的数据都是0,则会加锁失败,直到切回线程A,才能进入if语句。这样的情况是合理的,但是导致了饥饿问题。原创 2025-11-16 19:59:28 · 930 阅读 · 0 评论 -
【Linux】初识线程
当进程第一次访问某个虚拟地址,但该地址对应的数据还在磁盘上(比如程序的代码段、数据段),会触发缺页异常,操作系统需要将磁盘上的对应数据加载到物理内存,建立虚拟地址到物理内存的映射;页表也是内核中的一个数据结构,本身也是要占内核空间的,如果将虚拟地址空间和物理空间按照字节单位来映射,假如内核空间为4GB,那么就是4*1024*1024*1024字节,页表每一项至少要存储虚拟地址空间地址(四字节)和物理地址(四字节),每个页表项就占8字节,整个页表要占8*4GB大小,这都超过内核空间大小了,所以这肯定不行。原创 2025-11-13 19:40:50 · 1003 阅读 · 0 评论 -
【Linux】信号处理
操作系统的所有活动,从进程调度到设备管理,都是由这些中断所触发。:ISR(Interrupt Service Routine中断服务程序,一个处理中断事件的函数) 一开始通常会用汇编指令继续保存所有通用寄存器的值,形成一个完整的“陷阱帧”(一个在内核栈上完整保存了被中断的任务在陷入内核前一瞬间的CPU所有寄存器值的数据结构)。时钟中断可以理解为一种固定在每个CPU核心上的“警报器”,这个警报器以固定的时间间隔(例如10ms)响一次,每次一响,CPU就必须停下手中的活,立刻去执行操作系统内核的调度代码。原创 2025-11-10 07:00:00 · 882 阅读 · 0 评论 -
【Linux】信号保存
在进程控制块 (task_struct) 中维护了两个位图来表示每个信号的未决(pending)和阻塞(block)状态,每个位图的比特位位置对应信号的编号(如1对应SIGHUP,2对应SIGINT),其中pending位图记录该信号是否已送达进程但尚未处理(1表示信号待处理),block位图则标识该信号是否被进程屏蔽(1表示信号被阻塞)。当信号产生时,系统会检查block位图,若未被阻塞则根据handler表中的处理方法处理信号,若被阻塞则在pending位图的对应信号位置为1,待解除阻塞后再行处理。原创 2025-11-06 18:20:54 · 845 阅读 · 0 评论 -
【Linux】信号产生
用一段比较官方的话来说就是:当程序执行除零、访问野指针等这类非法操作时,会触发CPU级别的硬件异常,操作系统接收到这些异常后,会向违反规则的进程发送相应的信号(如SIGFPE用于算术错误,SIGSEGV用于内存访问违规),而默认的信号处理行为就是终止进程并生成核心转储,因此程序表现为崩溃。有的时候我们是因为程序出错了导致的异常退出,程序因自身bug出错导致退出,这个时候我们通过信号可以知道出了什么错,但我们还想知道出错的位置在哪里,即。底层操作系统监控这些条件,并在条件满足时自动向进程发送相应的信号。原创 2025-10-31 21:01:29 · 426 阅读 · 0 评论 -
【Linux】初识进程信号
进程之所以会产生,本质上还是用户的操作导致的,因为用户想要做某些操作,所以开启了一个个进程,所以进程操作其实就是为了实现人的操作。这些信号发生的时候我们就明白应该做什么,这说明我们能够识别这些信号,而我们之所以知道这些信号代表的意思,是因为我们被教育/训练过,所以记住了这些信号的特征以及处理方法,并且在没有信号产生的时候,我们就知道这些信号应该怎么处理。从根本上说,信号是为了在一种“异步”的场景下,让一个进程知道发生了某件重要的事情,并催促它立即去处理,所以信号是由事件通知产生的。原创 2025-10-27 11:34:56 · 599 阅读 · 0 评论 -
【Linux】进程间通信
在 Linux 世界中,进程是资源分配和调度的基本单位。通常情况下,每个进程都拥有自己独立的虚拟地址空间,这意味着一进程无法直接访问另一个进程的数据。但现实中的复杂任务往往需要多个进程协同工作,这就引出了一个核心需求——进程间通信。本文将深入探讨 Linux 下的几种经典 IPC 机制,理解它们的目的、发展历程以及工作原理。原创 2025-10-25 20:43:15 · 886 阅读 · 0 评论 -
【Linux】动静态库
我们在使用ldd命令时,可以看到我们可执行程序所依赖的标准库,说明系统应该默认会去标准库路径(/lib64)下查找我们所使用到的库,那么我们想要系统或加载器能识别到我们自己的库,是不是只要把我们自己的库文件和头文件拷贝到标准路径下就可以了呢?我们通过-I、-L以及-l选项是在告诉编译器我们的库文件和头文件所在位置,我们的系统并不知道,当我们的程序编译链接形成可执行文件时,已经和编译器没有关系了,所以我们的系统去找库的时候找不到我们自己的库。结果是会报错找不到库,我们静态链接的前提是必须有静态库。原创 2025-10-19 12:56:06 · 653 阅读 · 0 评论 -
【Linux】动态链接和动态加载
内核:你在Shell中输入 ./my_program 后,内核的加载器首先工作。它读取ELF文件头,发现这是一个动态链接的可执行文件(因为包含INTERP 段)。内核为进程创建虚拟地址空间,并将程序本身的代码段(.text)、数据段(.data)等LOAD 段映射到内存中。内核根据INTERP 段指定的路径,将动态链接器(例如 /lib64/ld-linux-x86-64.so.2)这个特殊的共享库加载到内存。内核不执行程序的 _start,而是直接将控制权跳转到动态链接器的入口点。原创 2025-10-14 10:37:03 · 878 阅读 · 0 评论 -
【Linux】理解链接过程
ELF文件中的每个LOAD类型Segment(需要加载的段)在程序加载时,都会在内核中创建一个对应vm_area_struct结构体,该结构体继承了Segment的虚拟地址范围、访问权限和文件偏移等关键信息,成为该段内存在内核中的运行时管理单元。这里的两次call就是指我们调用了两次函数(printf 和 run),前面的数字e8其实就是用十六进制代表call命令,后面跟着的一串零其实应该是调用的函数地址(暂时为0),因为此时编译器是不知道函数地址的,和其他的模块链接后才知道函数地址。原创 2025-10-12 18:30:19 · 767 阅读 · 0 评论 -
【Linux】认识ELF格式文件
ELF(Executable and Linkable Format)是Linux系统中可执行文件(.exe)、目标文件(.o)、共享库(.a)和核心转储的标准文件格式。ELF头(ELF Header):描述文件的基本属性,如目标架构、入口地址、段头表和节头表的位置程序头表(Program Header Table):列举了所有有效的段(segments)和他们的属性。原创 2025-10-09 20:23:49 · 738 阅读 · 0 评论 -
Ext2文件系统
当需要读写大量连续数据时,如果数据都存储在同一个柱面上,硬盘就可以在第一个盘面读写完后,无需移动磁头臂,直接切换到第二个盘面的磁头继续读写,然后再切到第三个...这样大大减少了磁头寻道的时间,极大地提高了读写速度。有时候编译项目时,我们可能会访问几百个文件,如果我们每次访问文件都要做一次完整的路径解析,而路径解析需要读取磁盘上的目录内容,那就意味着要做很多次磁盘访问,磁盘I/O操作比内存操作慢数万倍!如果这个文件时目录文件的话,那么就存储的是目录的结构信息(即文件名到 inode 号的映射关系)。原创 2025-10-04 20:43:04 · 1003 阅读 · 0 评论 -
【Linux】基础 I/O
打开文件的方式不仅仅是fopen,ifstream等流式,语言层的方案,其实系统才是打开文件最底层的方案,fopen、fwrite...都是封装的系统文件。这是因为我们把1号文件描述符重定向到普通的磁盘文件中,刷新方式从行缓冲变成了全缓冲,我们写的内容肯定没有装满缓冲区,所以没有刷新,此时我们可以手动刷新一下,就可以让内容刷新出来了。这里我们重新写了一个重定向的文件,本来是想实现和前面一样的功能,将printf打印的内容打印到log.txt文件中,但是这里我们什么都没看到,这是为什么呢?原创 2025-09-30 15:01:28 · 793 阅读 · 0 评论 -
【Linux】再识进程(Ⅱ)
父进程需要知道子进程的终止状态(比如它是正常退出还是被信号杀死的,退出码是多少),否则子进程可能会变成“僵尸进程”,占用系统资源导致资源的浪费。理解 exec 最关键的一点是:它并不创建新的进程,而是将当前进程的内存空间(包括代码、数据、堆栈等)完全清空,然后加载并执行一个新的程序文件,所以进程的id并不改变。:创建一个新的进程(子进程),子进程是父进程的副本,拥有和父进程相同的代码、数据段(若读写数据:写时拷贝)、堆栈等。进程终止的本质是释放系统资源,释放进程申请的相关内核数据结构和对应的数据和代码。原创 2025-09-26 14:00:20 · 1505 阅读 · 0 评论 -
【Linux】初识进程(Ⅰ)
冯诺依曼体系的核心思想就是存储思想:计算机的程序和程序所处理的数据一样,都以二进制的形式存储在同一个存储器中。功能: 负责执行所有的算术运算和逻辑运算。例子: 加减乘除、与或非比较等操作。功能: 是整个计算机的指挥中心。它从存储器中读取指令,进行分析,然后向其他部件发出控制信号,协调各部件步调一致地工作。运算器 + 控制器 = 中央处理器,也就是我们常说的 CPU。功能: 用于存放程序和数据。所有信息(指令和数据)都以二进制形式存储在此。原创 2025-09-22 19:36:08 · 1031 阅读 · 0 评论 -
Linux开发者三剑客:git、gdb、cgdb
目录1. 下载git/gdb/cgdb2. 认识git/gdb/cgdb2.1 git2.1.1 创建项目2.1.2 git三板斧2.2 gdb2.3 cgdb3. gdb/cgdb的基本操作3.1 操作总结这个命令大家可以直接AI,下面是我用Deepseek生成的,大家直接根据自己的系统下载就行,有问题也可以问AI。git 是一个开源的分布式版本控制系统(Distributed Version Control System, DVCS)。它由 Linus Torvalds 为管理 Linux 内核开发而创原创 2025-09-16 09:25:02 · 763 阅读 · 0 评论 -
【Linux】编辑器vim的使用
我们可以直接用键盘上的光标来上下左右移动,但正规的vim是用写英文字母「h」、「j」、 「k」、「l」,分别控制光标左、下、上、右移⼀格。• 「#」:「#」号表示⼀个数字,在冒号后输入⼀个数字,再按回车键就会跳到该行了,如输入数字 15,再回车,就会跳到文章的第15行。• 「/关键字」:先按「/」键,再输入想寻找的字符,如果第⼀次找的关键字不是想要的,可以 ⼀直按「n」会往后寻找到您要的关键字为止。」键,再输入想寻找的字符,如果第⼀次找的关键字不是想要的,可 以⼀直按「n」会往前寻找到您要的关键字为止。原创 2025-08-15 13:05:11 · 1343 阅读 · 0 评论 -
【Linux】关于权限的概念
注:但实际上所创建的文件和目录权限往往不是你上面设置的,因为创建文件或目录的时候还会收到umask的影响。假如默认权限是mask,但实际创建的文件权限是:mask&~umask。写(w—write):对文件来说,修改文件的权限;读(r—read):对文件来说,读取文件内容的权限;执行(x—execute):对文件来说,执行文件的权限;文件和文件目录的所有者所在组的用户:g --- Group。注:只有文件的拥有者和roo才可以改变文件的权限。- : 向权限范围取消权限代号所表示的权限。原创 2025-08-12 09:04:24 · 404 阅读 · 0 评论 -
【Linux】基础指令(Ⅲ)
r 递归处理,将指定目录下的所有文件和子目录一起压缩。将../show/test.tar.gz目录下的文件解压缩到当前文件。语法:zip 选项 压缩包名.zip 目录/文件。:指定文件名,f后面直接跟文档名,不要加别的选项。-d 指定解压目录(默认当前目录)语法:whereis 命令名/二进制文件。用于在目录树中根据指定条件查找文件或目录。-a 全部信息,综合以上所有信息。语法:find 选项 文件/目录。语法:tar 选项 文件/目录。原创 2025-07-28 14:06:24 · 480 阅读 · 0 评论 -
【Linux】基础指令(Ⅱ)
与more类似,但less可以随意浏览文件,而more仅能向下(前)移动,却不能向上(后)移动,而且less在查看之前不会加载整个文件。该指令相当于输出命令,可以直接输出内容,也可以借助输出重定向符号,将内容输出到指定文件内,如果文件不存在就直接生成一个新文件。-n 规定输出行数,按向下键就会n行n行的输出,直到输出完文件中的内容就能自动退出,或者按q直接退出。用来显示开头或结尾某个数量的文字区块,head用来显示档案的开头至标准输出中,而tail就是看档案的结尾。原创 2025-05-14 21:01:17 · 890 阅读 · 0 评论 -
【Linux】基础指令(Ⅰ)
本篇示例使用的都是红帽Linux系统。原创 2025-05-06 21:17:00 · 925 阅读 · 0 评论
分享