登录社区云,与社区用户共同成长
邀请您加入社区
C语言是一种非常经典的编程语言,诞生于20世纪70年代。它被广泛用于操作系统、嵌入式设备、游戏引擎等底层开发中。很多现代编程语言(如Java、Python、C++)都深受C语言的影响。对于编程小白来说,C语言是一个很好的起点。它语法简洁、逻辑清晰,能帮助你理解计算机底层的运行原理,为以后学习其他语言打下扎实的基础。
本文概述了程序的编译与运行环境。编译过程包括预处理(宏替换、文件包含、注释删除)、编译(源码转汇编)、汇编(汇编转机器码)及链接(地址分配、符号解析)。运行需加载至内存,由操作系统管理。预处理详解涵盖预定义符号、define常量与宏、#与##运算符、条件编译、头文件包含规范及#pragma等指令,强调命名规范与命令行参数使用。
本文剖析Kafka通过将消息缓存交由操作系统Page Cache,并结合sendfile零拷贝机制,实现高性能传输。其核心ge C在于:1)摒弃JVM堆内存缓存,避免GC停顿与内存开销;2)统一二进制格式,实现“零转换”;3)利用sendfile在内核态直接将Paache数据经SG-DMA直送网卡,减少上下文切换与CPU拷贝,显著降低延迟、提升吞吐。该设计使Kafka在高并发场景下具备接近原生性能
本文介绍基于GD32H759I-EVAL开发板与RT-Thread v5.2.2操作系统的工控开发环境搭建,选用VS Code + GCC工具链+ SCons构建体系,实现点灯实验。重点对比了RT-Thread与Linux在驱动与线程调度上的差异,强调其在工控场景下的实时性、确定性及工程效率优势,为后续复杂应用开发奠定基础。
基于 STM32F103C8T6 的自平衡小车项目,提供标准库、HAL库及FreeRTOS三版源码,硬件一致,算法相同,仅软件架构不同。通过对比裸机单循环与多任务系统,清晰展示嵌入式开发中不同范式的实现差异与取舍。核心采用级联PID控制,融合MPU6050姿态数据与编码器速度反馈,支持蓝牙在线调参。代码结构清晰,适合学习底层驱动、工程化设计与实时操作系统应用。项目参考江科大教程,开源可复用。
这一版确实成功实现了各个算法,但思路混乱,没有将检查与各个进程本身分离,所有检查由各进程自己实现,无法精细调整各代码段的执行顺序,难以对各个算法进行完整测试。第一版C语言实现。
虚拟地址是由虚拟页号(vpn)和虚拟页偏移(vpo)构成vp指虚拟页,磁盘存放的是虚拟页的数据使用malloc申请内存,发生在用户态,只是做标记;改变页表,发生在缺页中断,操作系统会分配真实的物理内存地址,并改变pte,有效位置1。当内存严重不足或者内核主动回收内存或者页面长时间未使用时,即当物理内存压力比较大,需要为其他页面腾出空间时,操作系统才会将内存的数据放入硬盘交换区,并改变pte,将pt
标准IO实际上是对系统IO的封装,系统IO是更接近底层的接口。文件描述符实质就是一个索引值,Linux下一切皆是文件,普通文件,串口,管道,socket,终端,键盘屏幕统一使用文件描述符进行管理,文件描述符就是用来代表你打开的某个资源。在Linux下,有现成的函数来实现对文件的读取和写入,在操作系统层面上这些专门针对文件的IO接口就被称为系统IO;文件广义的理解就是,可操作的设备或接口都是文件,包
本文介绍 HRTOS 4.0 驱动库中的 06_Storage 存储设备驱动模块,面向 51 单片机 / 8051 平台,主要实现 24C02 EEPROM 存储器驱动及软件 I²C 底层通信。文章从模块结构、24C02 读写流程、I²C 起始与停止信号、字节读写及 ACK 应答机制等方面进行介绍,并结合实际代码说明驱动的使用方法与硬件连接注意事项。该模块采用分层设计,将 EEPROM 上层读写接
C 语言把键盘、显示器、磁盘文件等所有外部 I/O 设备统一抽象成字符流(字节流)流也被定义为有序字节序列有序:数据是一个接着一个存取,不是随机的字节:现代操作系统以字节作为最小IO传输单位(系统不区分一张图片、一段字符,只认字节)为什么需要流?外部 I/O 设备就是输入输出外部设备,是计算机主机(cpu、内存)意外能够与计算机进行数据交换的硬件。每种设备有不同的读写函数,程序员想切换数据源(eg
C/C++程序内存分配的⼏个区域:1. 栈区(stack):在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时 这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中,效率很⾼,但是分配的内 存容量有限。栈区主要存放运⾏函数⽽分配的局部变量、函数参数、返回数据、返回地址等。《函数栈帧的创建和销毁》2. 堆区(heap):⼀般由程序员分配释放,若程序员不释放,程序结束时可能
非分离属性:可以被其他线程回收或者结束的线程成为非分离属性的线程。分离属性:不需要回收的线程,称为具有分离属性的线程,结束时可以被操作系统回收。线程由进程创建,在创建时会在栈区为线程分配独立的栈区空间(默认8M),让线程在条件不满足时安心"睡觉",条件满足时被"叫醒"条件变量 - 等待某个条件成立(必须配合互斥锁)信号量 - 管理资源数量(独立使用,无需互斥锁)在同一个进程中的线程共用堆区、数据区
字符跟数字相加:在计算过程中,计算机会查询 ASCII 码表,查询到这个字符的十进制,变成 int 数据类型,再进行计算。有意思的知识点:按住 ctrl,然后鼠标左键一点,可以反复点,不断找到你想找到 C 语言中层层嵌套的文件,但我很少用🤔。【间隔可以是空格,数字,逗号等,但是同一行输入除了空格可以替换用回车,其他间隔是什么,你就要原封不动写什么】可以在路径栏中输入 cmd,进入控制台,输入可执
本文剖析JVM与操作系统协作下的虚拟内存状态演进:从Unmapped(未映射)经mmap(PROT_NONE)转为Reserved(仅注册VMA),再通过mprotect升级为Committed(仍未分配物理页),最终在写入时触发缺页中断,建立PTE映射并增加RSS。基于HotSpot源码,详解ReservedSpace与os::pd_reserve_memory的底层实现,揭示各阶段页表与物理内
先说明:不同 CPU、编译器、优化级别、操作系统 ABI 的细节不同。现代 64 位系统里,参数通常优先走寄存器,不一定真的全部压栈。但“调用栈 / 栈帧”的整体模型仍然非常重要。栈是一种后进先出的内存结构。可以把它想象成一摞盘子:最后放进去的盘子,最先拿出来。函数调用时,当前函数使用一块栈空间,这一块空间称为:栈帧,Stack Frame。内容说明返回地址call指令压入,ret指令弹出。逻辑上
UDP 服务器创建 udp 套接字填充本机 IP 端口bind()绑定端口recvfrom()等待接收客户端消息sendto()回复消息close 关闭 fdUDP 客户端socket()创建套接字填充目标服务器sendto()发送数据(客户端不用 bind,操作系统自动分配端口)recvfrom()接收服务器应答closeUDP 没有 listen、accept、connect。
功能:初始化一个信号量 参数: sem:信号量对象地址 pshared: 0 : 线程间共享使用!0:进程间共享使用 value:信号量初始值 返回值: 成功:0 失败:!线程的分离属性:不需要被其他线程回收的线程,称为具有分离属性的线程,将来执行结束,由操作系统回收。线程的非分离属性:可以被其他线程结束和回收的线程,称为具有非分离属性的线程。临界资源:多个线程可以同时访问的区域。线程的互斥机制:
大家好,我是CodeStats。一个在底层技术上“考古”了四年的硬核爱好者,也是WWAIC(全周项目 AI 编程)范式的提出者和实践者。我曾手写过一个完整的 Java Web 框架(从 IoC 容器到嵌入式 Tomcat,代码全开源),也喜欢用通俗的语言拆解 CPU、JVM、操作系统的运行本质。本文适合谁?如果你是刚入门的开发者,本文能帮你建立从硬件到软件的全景认知;如果你是有经验的工程师,本文的
Linux 不只是一个操作系统内核,它定义了整个云时代的游戏规则fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;化神法则Android手机操作系统服务器发行版Kubernetes容器编排Docker容器引擎嵌入式WSLWindows上的Lin
其实翻译环境是由编译和链接两个大的过程组成的,而编译又可以分解成:预处理(有些书也叫预编译)、编译、汇编三个过程。词法分析就像扫描器将源代码程序输入扫描器,扫描器的任务就是简单的进行词法分析,把代码中的字符分割成一系列的记号(关键字、标识符、字面量、特殊字符等)。因为在不同的环境会得出不一样的汇编代码,上述是在Windows 11的环境下使用VSCode运行出来的,如果换成Linux那么汇编也会有
线程是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程共享进程的资源(如内存空间、文件描述符等),但拥有各自的栈空间和寄存器状态。POSIX线程(pthread)是C/C++中实现多线程的标准API,在Linux/Unix系统中广泛使用。使用时需包含头文件,编译时需添加-pthread选项。pthread选项的作用1.链接POSIX线
在Linux系统中,进程是资源分配的最小单位,每个进程拥有独立的虚拟地址空间,进程与进程之间天然隔离,不能直接访问对方内存空间。但实际业务开发中,多个进程经常需要交换数据、同步状态、互相通知事件,于是操作系统提供了IPC(InterProcess Communication,进程间通信) 这套机制,用来完成进程之间的数据交互与协同工作。
进程间通信(Inter-Process Communication,IPC)是指在操作系统中,不同进程之间交换数据和信息的技术。由于进程空间是独立的,每个进程独享自己的0-4G虚拟内存空间,因此需要借助特定的机制来实现进程间的数据交换。本文将详细介绍Linux下常用的进程间通信方式。进程空间是独立的,无法直接访问其他进程的内存空间多个进程协同工作需要进行数据交换进程间通信是构建复杂应用程序的基础信
锁的工作原理:互斥锁的本质是保证“同一时刻,只有一个线程能进入临界区”。如果 pthread_exit() 返回的指针指向局部变量(栈上的变量),当线程函数退出时,这块栈内存会被自动回收。互斥锁通过原子操作保证加锁的排他性,一旦某线程加锁成功,其他线程在解锁前都无法获取同一把锁,因而会被操作系统阻塞并让出CPU,直到持有锁的线程执行完临界区并解锁,才唤醒下一个等待线程。pthread_exit()
上一篇说过,进程是"程序动态执行的过程",一个进程从创建、调度到消亡,是操作系统管理多任务的基本单位。但一个进程内部,能不能同时干好几件事?比如一个音乐播放器:一边解码音频、一边刷新界面、一边响应你的点击——这些事如果排成一队串行执行,界面早卡死了。线程就是进程内部的执行流。一个进程至少有一个线程(就是跑main的那个,叫主线程),还可以创建更多线程,让它们在同一个进程空间里并发执行不同的任务。线
C语言是一门古老而强大的编程语言,是计算机科学领域最重要的基石之一。无论是操作系统、嵌入式设备,还是各类底层软件,都离不开C语言的支撑。本文将从C语言的基本概念入手,帮助读者建立对这门语言的初步认识,为后续深入学习打下坚实的基础。例如:以上就是今天要讲的内容,本文仅仅简单介绍了C语言的一些常见概念,帮助大家为更深入的 c语言学习打下基础。
本文介绍如何基于C语言手动实现MQTT3.1.1协议的核心报文封装与解析,适用于STM32等无操作系统的MCU开发环境。内容涵盖:1)定义MQTT协议相关枚举和结构体;2)实现剩余长度的可变字节编解码工具函数;3)详细解析CONNECT、PUBLISH等核心报文的组装过程;4)提供简易的报文解析框架;5)列举裸机开发中的常见问题,如TCP粘包处理、大端字节序转换等。通过底层协议实现,帮助开发者深入
6. 僵尸态:进程已执行结束,但其进程空间尚未被父进程或系统回收,仅保留进程描述符(等待回收状态)。· 进程:是程序动态执行的过程,包括创建、调度和消亡,是操作系统进行资源分配和调度的基本单位。3. 可唤醒等待态(可中断睡眠):进程因等待某资源或事件而挂起,等待过程中可被信号或事件唤醒。· fork调用一次,返回两次:在父进程中返回子进程的PID,在子进程中返回0。· 程序:存放在外存(如硬盘)中
本篇为 Linux 进程基础学习笔记,主要讲解进程的概念、创建、调度、状态与消亡过程,并介绍进程相关常用命令。内容重点围绕 fork() 函数展开,说明父子进程的生成方式、执行流程差异与基础使用逻辑。整体从理论概念到函数接口逐步递进,帮助学习者理解操作系统中进程管理的基本机制,以及如何通过系统调用完成进程创建与控制。
本文带您从零开始写一个最小操作系统内核。文章首先解释了手写OS的意义(理解计算机本质、面试加分、极客掌控感),然后以传统BIOS为主线,梳理了“BIOS引导 → Bootloader加载 → 内核初始化”三步启动流程。核心代码展示了一个C语言编写的最小内核,直接操作VGA显存地址(0xB8000)打印“Hello, My OS!”,无需任何库函数。同时用Python模拟了启动过程,并给出了在QEM
我们写下的 C 代码为什么能够变成可执行文件?可执行文件又是怎样进入内存并被 CPU 执行的?这一章尝试把整条路径串起来。C 源文件(.c) → 预处理文件(.i) → 汇编文件(.s) → 目标文件(.o)→ 链接生成 ELF → 安装或烧写 → 装载与初始化 → CPU 执行本文同时讨论 Linux 等操作系统环境和嵌入式裸机环境。两者前半段的编译、汇编和链接过程相似,但“安装”和“运行”的方
大学里,你完全可以沉下心学技术。把:C/C++、Java/Python、数据结构、操作系统、计算机网络、数据库、Linux、Git……这些基础真正学扎实。没有技术,谈业务就是空中楼阁。但不要把自己训练成一个只会执行需求的“代码机器”。它能解决什么问题?谁需要这个问题被解决?为什么这个问题值得解决?当你开始这样思考的时候,你就不再只是学习“计算机技术”。如何利用计算机创造价值。而这,可能才是计算机学
旅馆信息管理2017 年 3 月 3 日至 2017 年 3 月 18 日。基于 Windows 10 操作系统的 Microsoft Visual Studio 2017。2.
本文完整介绍了基于 C 语言的 CTF 实战系统设计与开发流程:从需求分析与系统架构入手,设计了用户、题目核心数据结构与文本通信协议,详细实现了网络通信、用户认证、Flag 判题、动态分值、排行榜等功能模块,并通过「fork + ptrace」沙箱保障题目运行安全。同时给出了 PWN、逆向、密码学三类典型题目的实现示例,以及构建部署与测试方案。使用 C 语言开发 CTF 系统的过程,本身就是一次深
文件IO是Linux编程的基石,掌握fd和系统调用是理解操作系统资源管理的关键。标准IO通过缓冲机制优化了性能,但在处理设备文件或需要实时性时应慎用。在实际开发中,应根据业务场景(文本处理 vs 二进制流 vs 设备控制)灵活选择 IO 模型。希望本文能助你打通Linux文件操作的任督二脉!
操作系统默认可分配出的文件描述符:0-1023: 总共1024。mode:用户自己、同组用户、其他用户对该文件的读写执行权限。当打开一个文件时,系统会为已打开的文件分配一个文件描述符用来标记该文件。只打开文件,使用完不关闭文件会造成文件描述符泄露。成功:返回当前读写位置到文件开头的偏移量。pathname:要打开的文件的文件名。whence:要偏移的起始位置。成功:截取到的子字符串的首地址。cou
任务切换 = 改寄存器(含 PC):时间片结束 → 把当前任务各寄存器的值(含 PC)保存到该任务创建时分配的任务栈 → 令 PC 指向另一个任务的开头 → 新时间片正常运行 → 再切换时重复保存 → 对已完成的任务"出栈"恢复寄存器,如此循环。RTOS(Real-Time Operating System)是处理实时事件的轻量级操作系统内核,引入"任务(Task)"概念,由任务调度器(Sched
标准IO是有缓存的IO,用户调用标准IO函数后,数据先进入缓存区,满足刷新条件时才将数据传递给内核。:一种特殊的二进制文件,文件中的每个字符都是能够显示在终端的ASCII码字符。:存放在磁盘空间中的一段数据的集合,是操作系统管理数据的基本单位。:文件中包含一些不能在终端直接显示的ASCII码字符。:打开pathname对应的文件,并与之建立一个流。:有方向性、具有连续性的数据通道。:编写程序统计某
保存正在运行的进程的cpu主模块中各个寄存器。操作系统内核中,进程切换通过cpu辅助模块。就是栈的地址,数组第一个元素就是栈底,后面。cpu主模块的寄存器值就保存在进程结构体的。操作系统内核中,每个进程结构体。储存了进程的所有信息,其中就有栈的地址,进程结构体中栈可以通过大数组实现,数组名。也就是进程结构体中的数组中。可以往数组里不断的加数值,也就是入栈。通常也被称为内核栈。关于cpu在进程切换时
程序运行时并不是“直接在内存里随便放东西”:操作系统先给进程一张虚拟地址空间地图,函数调用主要借助栈,动态数据主要来自堆,而运行库负责把大块内存切成程序能使用的小块。
操作系统是一款软件,用于屏蔽底层不同的硬件平台,为上层提供统一的接口,实现通用的软件代码能够在不同硬件上运行。· 系统调用:Linux内核中的函数接口,仅在Linux系统中可用,功能强大但接口简练。· case 语句:根据变量值匹配多个模式,匹配后执行对应语句段,以 esac 结尾。· 库函数:对系统调用的封装,可跨平台移植,具有通用性,能处理更复杂的应用场景。· du:查看文件或目录大小,-m
本文摘要: 操作系统内存管理 4G虚拟地址空间分区:内核空间、栈区(自动管理)、堆区(手动管理)、数据区(.data/.bss/常量)、文本区 堆栈对比:栈自动管理、空间小、效率高;堆手动管理、空间大、需防泄漏 堆内存函数:malloc申请、free释放、calloc初始化申请 动态数组实现和内存泄漏防范 位运算 支持整型的6种位运算符:& | ^ ~ << >> 经典应用场景:位设置/清除/判断
C/C++程序内存分配的几个区域:1. 栈区:在执行函数时,函数内局部变量的存储单元都可以在栈区上创建,函数执行结束时,这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率高,但是分配的内存容量有限。栈区主要存放运行函数中的局部变量、函数参数、返回数据、返回地址等。2. 堆区:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS(操作系统)回收,分配方式类似于链表。3. 数据段
openwifi不是给普通用户刷机的系统,而是把 Wi-Fi 协议摊开的研究平台。OpenWrt 打开操作系统,openwifi 打开的是芯片内部。用 Zynq + AD9361,可以把 802.11a/g/n 做成 Linux 里一张能跑 hostapd 的网卡。代价是停在 Wi-Fi 4,工具链重,频谱法不能当儿戏。CPU 侧的开源已经很多了。空口这一侧,openwifi 给的是一份能上板、能
实验时间:8个小时实验心得:本次实验所花费时间较长,主要时间花费在了对读者优先和写者优先两个程序的debug上。一开始以为这个实验修改输入完成应该是比较顺利的事情。但是在修改输入的过程中发现读者优先和写者优先都存在着问题。修改程序这个过程其实还挺考验人的,因为你要找出是在哪个过程出现了问题,并且需要想办法怎么样修改这个bug。在这个过程其实可以不断对程序有更深的理解和思考,在分析之后得到是什么地方
虽然池子销毁了,但操作系统分配器(glibc)可能没有立即把内存归还给系统,而是保留在Nginx的进程空间里以备复用。的调用链极其规范,核心开发者对内存布局的控制到了“苛刻”的程度。相比于那些依赖第三方库堆叠的应用,Nginx自身的代码极少出现野指针或越界带来的内存损坏。既然你关注到了内存管理,那我顺带提一句:Nginx 的“内存池”虽然解决泄漏,但它有一个天生的弱点——如果你编译了不成熟的第三方
内存地址与基地址内存地址操作系统为每个字节分配一个唯一编号(12位16进制数表示),用于定位内存位置。基地址(首地址)单字节数据:如char,地址就是该字节的编号。多字节数据:如int占4个字节、double占8个字节:地址是所有字节编号中最小的那个,称为基地址或首地址。
又称系统IO,是系统调用,是操作系统提供的函数接口在posix(可以移植操作系统接口)中定义的一组输入输出函数。
只允许从一端进行插入和删除数据的线性存储结构,成为栈结构。数据的插入称为入栈/压栈, 数据的删除称为出栈/弹栈。递归本质就是操作系统栈,递归深度过大 → 栈溢出。数据插入和删除的这端成为栈顶,另一端成为栈底;入栈数据时,栈顶向内存高地址移动,称为增栈,入栈数据时,栈顶向内存低地址移动,称为减栈。队列:FIFO 先进先出,一端入、一端出。,不要用尾部,否则遍历找到尾部开销大。栈顶所在位置一直存有元素
FlexibleButton是一个基于标准C语言的轻量级按键处理库,支持单击、双击、连击、长按等多种按键事件,具有自动消抖和组合按键功能。该库与硬件解耦,可适配任意处理器平台和操作系统(包括裸机)。移植过程分为四步:获取源码、实现硬件读取函数、创建定时扫描任务、初始化与注册按键。库采用经典的三行扫描算法,通过事件回调机制上报按键状态,支持中断和低功耗场景。文中详细介绍了在ESP32平台上的移植步骤