登录社区云,与社区用户共同成长
邀请您加入社区
本文介绍使用Python脚本自动生成跨平台兼容的Makefile,解决不同操作系统及Shell对Makefile语法支持差异带来的编译配置难题。通过自动扫描项目中.c和.h文件,动态生成源文件列表与头文件路径,实现高效、可移植的编译配置,显著提升开发效率。
程序运行时,内存里有一块专门的区域叫"栈段"。你可以把它想成一摞盘子:CPU 里有一个专门的寄存器叫 RSP(stack pointer,栈指针),它的作用只有一个:始终记录当前栈顶的地址。程序刚开始运行时,操作系统会把 RSP 设置成栈内存区域里最后一个位置的地址。这里有一个很反直觉但很重要的事实:x86-64 的栈是向低地址增长的。也就是说,往栈里放数据,RSP 的值会变小;从栈里拿数据,RS
基础建图、DFS/BFS、最短路、拓扑排序、最小生成树、并查集、二分图染色、欧拉路。本讲义只覆盖 CSP-J(入门组)复赛范围,并明确标注哪些内容。邻接表 vector 为核心,DFS/BFS 最高频模板可直接默写,题链均指向洛谷原题。
IPC(Inter-Process Communication)是进程间通信机制。不同进程通常拥有独立的虚拟地址空间,因此需要操作系统提供数据传输和同步手段。
游戏引擎底层基础系统就像大楼地基,平时业务开发很少直接关注,但是一旦地基存在缺陷,上层所有模块都会遭殃😱。通过封装操作系统 API,提供跨平台统一接口,隔离 Windows、Android、iOS 平台差异;时间、线程同步、文件日志、图片解析,构成引擎最基础工具集;Debug 内存管理器依靠双向链表 + 前后魔数保护 + 调用堆栈捕获,高效定位内存泄漏、缓冲区越界;符号解析,把机器指令地址还原为
数控系统一般是。
之前谈论的都是已打开文件在操作系统的中的管理,但是还有更多的文件没有被打开,被存在磁盘中,如何管理这些磁盘中的文件,就是本篇的学习目标。
"用实现 socket 多线程通信"的经典做法是"一连接一线程":主线程反复accept,每接到一个连接就交给新线程处理,自己回去等下一个。连接数不大、存活时间较长时它足够好用。两个前提先说清。第一,socket 不是 C++ 标准库的东西,而是操作系统的 API:本文用 POSIX sockets,头文件是<unistd.h>只能在 Linux / macOS / BSD 上编译;Windows
new和delete是 C++ 里被重载次数最多的两个关键字,也是初学者最容易混为一谈的一组概念。new不是一个关键字吗,关键字怎么能重载?还有人写delete p之后以为内存立刻还给了操作系统,于是拿它去衡量内存占用的变化,结果怎么都对不上。同一个new这个拼写,在 C++ 里至少代表了四种截然不同的东西——new 表达式(new-expression)、分配函数、定位 new(placemen
C++ 标准里没有任何 CPU 亲和性(CPU affinity)的 API。标准库的不提供"把这个线程绑到第 N 个核"的能力,也只能告诉你逻辑处理器大概有几个。用管理线程, 再通过拿到平台原生句柄, 调用操作系统的亲和性接口完成绑定。离开操作系统 API,这件事在纯标准 C++ 里做不到。典型误解有两个。第一,以为存在某个——不存在的。第二,以为绑核就是"独占这个核"——不是。亲和性只是限定调
生产者—消费者模型里,队列是线程之间最常见的交接点。「有锁队列」和「无锁队列」经常被拿来比较,但很多介绍把两者讲成了「慢」和「快」的关系,这是不准确的:它们的差别主要在阻塞语义、内存序约束和内存回收代价,而不是一条绝对的性能排序。脱离场景谈谁更快没有意义——在争用激烈时,一个设计良好的互斥量队列完全可能跑赢一个写得不讲究的无锁队列。无锁真正换来的性质是:某个线程被操作系统换出调度时,不会把其他线程
对象与「线程」是两样东西:对象是你在 C++ 里持有的句柄,线程是操作系统里真正在跑的执行流。的析构函数有一个硬性规定——如果对象在析构时仍然joinable()(也就是还关联着一个执行流),析构会直接调用,程序当场结束。所以每个join()等它跑完,或者detach()与它脱钩。detach()把执行流与句柄分离,让线程独立地跑下去,句柄不再管它。分离之后joinable()变成false,析构
死锁(deadlock)是并发程序里最难排查的一类问题:它不会崩溃、不会报错,只会让程序静止——CPU 占用为零,日志停在某一行,重启后又可能不复现。很多人以为死锁检测是操作系统内核的事,但在用户态自己实现一套检测机制,对定位线上问题、验证锁设计、甚至做自研调度器都非常有价值。加锁顺序检测(静态)超时检测(动态)等待图环检测(运行时),最后给一份可编译运行的等待图检测实现。死锁成立的四个必要条件中
C++由Bjarne Stroustrup开发,融合面向对象与泛型编程,兼具高效性与抽象能力。相比C语言,其在封装、内存管理、异常处理及标准库(如STL)方面显著增强。历经C++98至C++23的演进,持续优化性能与安全性。广泛应用于操作系统、游戏引擎、嵌入式系统、高性能计算及人工智能等领域。通过命名空间、函数重载、默认参数、内联函数等机制提升代码组织与效率。建议掌握基础后深入学习现代C++特性与
C++自1983年诞生以来,一直是工业级软件开发的中流砥柱。它既保留了C语言的高效性,又引入了面向对象等现代特性。游戏开发(如Unreal引擎)操作系统(如Windows、Linux内核)嵌入式系统(如智能设备、车载系统)机器学习引擎(如TensorFlow底层)金融系统(如高频交易平台)如果你希望深入理解计算机系统,或者从事高性能软件开发,C++是绕不开的语言。学习C++是一场马拉松,不是短跑。
C++编译器会对函数名、变量名进行编码,以支持重载、命名空间、类成员等特性。不同编译器的名字修饰规则完全不同。ABI(Application Binary Interface)应用程序二进制接口作用:规定二进制程序、动态库、操作系统之间底层交互规范(函数调用约定、内存布局、符号规则、系统调用等),保证二进制文件无需重新编译即可跨程序兼容。
虚拟地址访问首先需要转换到物理地址,首先虚拟地址分成高位的虚拟页号和低位的页内偏移,首先检查 TLB 是否存在虚拟页号到物理页号的映射,如果存在就直接组成真实地址,如果不存在就检查页表是否存在,如果页无效就首先把数据从磁盘拷贝到内存并更新页表,然后访问。malloc 和 new 的不同是前者是 c 的后者是 cpp 的,前者返回的是 void*后者是具体类型的指针,malloc 和 free 对应
通常情况下,程序员习惯直接使用 new、delete、malloc、free 等API申请分配和释放内存,这样导致的后果是:当程序长时间运行时,由于所申请内存块的大小不定,频繁使用时会造成大量的内存碎片从而降低程序和操作系统的性能。内存池则是在真正使用内存之前,先申请分配一大块内存(内存池)留作备用,当程序员申请内存时,从池中取出一块动态分配,当程序员释放内存时,将释放的内存再放入池内,再次申请池
程序运行时,操作系统为其分配虚拟内存空间并严格划分为多个区域:代码区(只读指令)、数据区(已初始化全局/静态变量)、BSS区(未初始化变量)、堆区(动态内存)、内存映射段(共享库)、栈区(函数调用)和内核区。这种划分基于不同数据的安全需求、生命周期和管理方式:代码区防止篡改,数据区/BSS区管理全局变量,堆区支持动态内存,栈区实现高效函数调用。分区设计保障了程序安全性(隔离内核/代码)、内存效率(
本文分析了Project Loom通过在JVM用户态实现Continuation与ForkJoinPool调度器,将虚拟线程(VirtualThread)与操作系统线程解耦,构建M:N调度模型。其核心是stackChunkOop堆内栈结构,支持动态链式扩容,实现纳秒级上下文切换。挂起(Freeze)时保存执行状态至堆内存,恢复(Thaw)时重建栈帧并跳转指令地址,由GC通过OopMap扫描栈帧引用
本题将单词链转化为有向图欧拉路径问题:每个单词为一条从首字母到尾字母的边。通过统计各字母出入度差,判断是否存在欧拉路径(至多一个出度比入度大1的起点,一个入度比出度大1的终点)。将单词按字典序排序,优先选择字典序小的边进行DFS搜索,确保找到字典序最小的完整词链。若无解则输出***。时间复杂度为$O(n \log n)$,适用于$n \leq 1000$。
本文结合代码 Demo 与 Linux0.11 内核源码,系统讲解 Linux 进程信号机制。信号是软件层面模拟硬件中断的异步通信方式,例如 Ctrl+C 会向前台进程发送 SIGINT 信号。文章介绍信号的三种处理动作:默认处理、忽略、自定义捕捉,梳理信号四类产生途径。同时解析内核 PCB 中 block、pending 位图原理,区分阻塞与忽略,详解信号捕捉时用户态、内核态切换流程,帮助理解操
🎬 艾莉丝的简介:2.2.2 thread.cpp(线程子类实现)2.2.3 widget.h(主窗口头文件)2.2.4 widget.cpp(主窗口实现)2.3 程序时序流程Widget 构造函数执行,调用,操作系统创建子线程。子线程调度执行,循环执行,每 1 秒发射信号。信号跨线程投递,放入主线程事件队列。主线程事件循环取出事件,执行槽函数,更新 LCD 数字。for 循环执行 10 次结束
最近笔者在做位运算相关的算法题,以及学习操作系统信号的三张表时,遭遇了许多关于位图的问题。遂作此篇,系统地补充一下位图缺失方面的知识点。
难度项目语言核心学习点入门TinyhttpdC网络编程、多线程入门CJSONC指针、数据结构入门2048 游戏C数组、状态机进阶SQLiteCB-Tree、SQL 解析进阶RedisC事件驱动、数据结构进阶LevelDBC++RAII、跳表挑战Linux 内核C操作系统核心挑战FFmpegC音视频、模块组织挑战C++张量、算子调度选择项目时,建议遵循「跳一跳够得着」的原则:选一个比当前水平略高、但
量是否恒定数学原因p˙\dot{p}p˙✅LERP 是线性函数ωb\omega_bωb✅指数映射保持生成元不变ωs\omega_sωs✅绕固定轴旋转不改变轴方向插值方式角速度均匀?无奇异性?结果合法?四元数 SLERP✅✅✅旋转矩阵线性插值❌✅❌(需正交化)欧拉角线性插值❌❌(万向锁)⚠️(一般情况合法)p˙常数ωb常数ωs常数。
这里面藏着 C++ 工具链最核心的一条流水线:源码文本先经过预处理展开成完整的翻译单元,再由编译器转成汇编代码,汇编器把汇编转成目标文件的机器码,链接器再把目标文件和库拼成操作系统能直接加载的可执行文件。预处理把分散的头文件合并成一个完整的翻译单元,编译把翻译单元转成汇编代码,汇编把汇编转成目标文件的机器码,链接把目标文件和库拼成操作系统能加载的可执行文件。像一个项目经理,接到“把这份源码变成可执
非法内存访问(如空指针解引用、越界写)属于未定义行为,由硬件与操作系统直接处理,触发SIGSEGV/SIGBUS等信号,而非C++语言异常。C++的try/catch仅捕获语言层异常(如throw),无法拦截进程级崩溃。因性能、安全与设计哲学考量,标准不强制检查指针合法性,也不允许可靠恢复。捕获此类错误既不可靠也无意义。正确做法是使用智能指针、边界检查工具(如std::span、AddressSa
CEF控件(CefControl)是nim_duilib对libcef(Chromium Embedded Framework)的封装,将Chromium浏览器功能集成到duilib界面库中。该控件支持HTML5渲染、JavaScript执行等现代网页功能,提供窗口模式和离屏渲染两种实现方式。使用时需下载对应版本的libcef二进制文件(32位/64位)放置到指定目录,并通过属性文件或手动配置工程
7、了解分布式系统设计与开发、负载均衡技术,系统容灾设计,高可用系统等知识;6、全面、扎实的软件知识结构,掌握操作系统、数据结构、网络等专业知识;1. 参与交易平台的设计、开发与测试,实现交易策略、风控等需求;4、编程基本功扎实,熟练C/C++开发语言、常用算法和数据结构;#幻方#明汯#九坤#鸣石#天演#进化论#佳期#量化研究员#C++5、熟悉TCP/UDP网络协议及相关编程、进程间通讯编程;春招
你简历中明确写了:EtherCAT 任务本地/SSH 执行。实际上就是:程序占着这个终端。你可能无法直接继续使用当前终端。但真正的工程部署通常不会简单依靠。systemd这就会进入真正的工程部署。这才是你真正应该建立的 Linux 思维。
协程是一种用户态轻量级线程,它由程序员显式控制挂起(yield)与恢复(resume),不依赖操作系统内核调度。与线程不同,协程在同一时刻只有一个在执行,因此无需考虑数据竞争与锁问题。:创建一个协程,参数为协程主体函数。:恢复(或首次启动)协程,可传入参数。:挂起当前协程,可向外传递返回值。:查询协程状态(suspended / running / normal / dead)。:以函数形式封装协
C 语言并不是凭空出现的,它是从一门更早的语言"B 语言"演化来的。B 语言诞生于 1971 年,运行在一台叫 PDP-11 的大型机器上,作者是贝尔实验室的研究员 Ken Thompson,他还用 B 语言写出了 UNIX 操作系统。但是 B 语言功能太简单,很多事情做不了,所以 1972 到 1973 年间,同样在贝尔实验室工作的 Dennis Ritchie 在 B 语言的基础上,设计出了
最快在O(n)复杂度筛出n以内的所有素数
学完 Ext2 之后,我觉得最重要的不是死记几个结构,而是把它们之间的关系真正串起来。Partition↓多个 Block Group├── GDT文件名↓目录↓inode↓文件属性数据块映射↓↓真正的文件内容把磁盘上的各种资源组织起来,让操作系统能够快速找到文件,同时知道哪些资源已经使用、哪些资源还可以继续分配。以前看到inode这些名词的时候,感觉都是零散的知识点。现在把它们放到一起之后,就能
前面章节里我们一直在用 vTaskDelay,但没讲透它背后的系统。这一章把 ESP-IDF 自带的实时操作系统 FreeRTOS 讲清楚:任务是什么、调度器怎么决定谁先跑、为什么"阻塞"比"空转"好、任务之间怎么安全地传数据(队列)、怎么互斥(信号量/互斥锁)。这是"只看一本书就能做真实项目"的关键一章。
本文简要介绍C++语言的基础知识,涵盖其发展历程、特点与应用领域,如游戏开发、操作系统及高频交易系统。内容包括开发环境搭建、基本语法、数据类型、运算符、控制结构、函数、数组、指针及面向对象编程(类、对象、继承)。通过实例演示了程序编写与运行流程,并涉及文件操作。文章适合初学者入门,系统梳理C++核心概念,为深入学习奠定基础。
大家好,我是小凉,大三物理专业学生,正跨考计算机研究生。博客将记录我的计算机学习历程,分享知识框架。我坚持费曼学习法,力求用通俗语言讲清核心概念,巩固自身理解。后续将更新C语言、数据结构、操作系统、计算机网络、机器学习与深度学习等考研及AI相关内容,欢迎一起进步!
可以通过解引用的方式找到地址指向的内存 {指针前加*} 通过*操作指针变量指向的内存。内部编号都是从0开始记录的 一般用16进制数字表示可以利用指针变量保存地址。在32位操作系统下 占用4个字节空间。(解引用):按地址找里面的内容。(取地址):拿出变量的地址。可以通过指针间接访问内存。语法 数据类型*变量名。让指针记录某变量的地址。指针变量的定义和使用。64位下 占8个字符。
CPU处理进程与线程的核心机制是操作系统通过状态管理、任务调度和资源分配实现并发执行。进程是资源分配的最小单位,拥有独立内存空间;线程是CPU调度的最小单位,共享进程资源。进程/线程经历新建、就绪、运行、阻塞、终止五种状态流转,操作系统通过短程调度算法(如FCFS、RR、优先级)在就绪队列中选择任务分配CPU时间片。线程实现模型分用户级(轻量但无法利用多核)、内核级(支持多核但开销大)和混合级(折
SDL3— 提供图形窗口、事件处理(鼠标/键盘)能力,模拟嵌入式 LCD 显示屏FreeRTOS— 实时操作系统内核,在一个独立的 Windows 线程中启动调度器,运行 RTOS 任务LVGL— 轻量级嵌入式 GUI 库,通过 SDL3 渲染显示Nimmake— Python 编写的构建工具,自动化管理编译、链接与依赖通过这种方式,你可以在没有硬件开发板的情况下,在 PC 上直接开发、调试和验证
LRU(最近最少使用)是一种高效缓存淘汰策略,核心思想是优先淘汰最久未访问的数据。通过“哈希表+双向链表”结构实现,支持O(1)时间复杂度的get和put操作。哈希表快速定位节点,双向链表维护访问顺序,头部为最近使用,尾部为最久未使用。广泛应用于操作系统页面置换、Redis内存淘汰、数据库缓冲池及浏览器缓存等场景。该算法基于局部性原理,提升缓存命中率,是工程与面试中的经典算法。
本文在前面信号篇的基础上,继续深入研究信号捕捉以及操作系统底层的执行机制。文章首先分析信号从递达到处理函数执行的完整流程,重点解释为什么处理函数结束后仍需返回内核,以及用户态与内核态之间是如何切换的。随后从CPU、硬件和中断控制器入手,梳理硬件中断进入操作系统的全过程,并结合中断向量表、时钟中断和时间片理解操作系统的运行机制。最后进一步区分异常与陷阱,并追踪系统调用从用户态进入内核态的执行过程。
对其他线程间通讯方式,编写测试代码,根据实测结果及系统源码机制探究,梳理所有线程间通信方式,在实例对象delete()后,阻塞wait()线程间通信方式是否可被唤醒唤醒后返回状态二进制信号量✅️计数型信号量✅️互斥信号量✅️读写信号量✅️消息队列✅️事件集✅️条件变量✅️。
虚拟地址空间是一个非常抽象的概念,先根据字面意思进行解释:它可以用来加载程序数据(数据可能被加载到物理内存上,空间不够就加载到虚拟内存中)它对应着一段连续的内存地址,起始位置为 0。之所以说虚拟是因为这个起始的0地址是被虚拟出来的, 不是物理内存的0地址。虚拟地址空间的大小也由操作系统决定,32位的操作系统虚拟地址空间的大小为 2^32 字节,也就是4G,64位的操作系统虚拟地址空间大小为2^64
欧拉函数定义,性质和例题(附代码)
程序活在逻辑地址的“有序幻象”中,硬件工作在物理地址的“无序现实”里,而地址映射机制(MMU + 页表)是连接这两个世界的唯一桥梁。理解了这一点,你就理解了为什么现代操作系统能同时安全、高效地运行成百上千个进程;理解了什么是虚拟内存;也理解了为什么“指针”在C语言中既强大又危险——因为你操作的永远是逻辑地址,而真正的物理真相,被操作系统牢牢地藏在幕后。下次再看到类似的映射图,不妨试着沿着箭头走一遍
默认情况下,使用malloc分配的主机内存是可分页的,操作系统可能将其换出到磁盘,导致数据在物理内存中不连续。在进行 H2D 或 D2H 拷贝时,CUDA 驱动需要先将可分页内存复制到一个临时的页锁定缓冲区,然后再通过 DMA 传输到设备,增加了额外开销。**页锁定内存(Pinned Memory,也称 Page‑Locked Memory)**是使用或分配的主机内存,它不会被操作系统换出,物理地