Linux---内核态&用户态

一、核心本质:为什么要区分内核态 / 用户态?

1. 核心目标:安全与隔离

早期操作系统(如 DOS)无态的区分,用户程序可直接操作硬件 / 修改内核内存,一个程序的错误(如误写内存)会直接导致整个系统崩溃。

Linux 设计两种状态的核心目的:

  • 权限隔离 :将 "危险操作"(硬件访问、内存修改、进程调度)限定在内核态 ,用户程序只能在用户态执行普通逻辑;
  • 故障隔离:用户态程序崩溃(如段错误)仅影响自身,不会波及内核和其他进程;
  • 资源管控:内核统一管理硬件 / 内存资源,用户程序需通过 "合法接口"(系统调用)申请资源,避免资源滥用。

2. 本质定义

状态 核心描述 通俗比喻
用户态 CPU 执行用户空间程序代码(如你的 C++/Python 应用、Shell 命令),处于低特权级,所有操作受内核限制 普通用户操作电脑,只能用软件,不能拆硬件
内核态 CPU 执行内核空间代码(如系统调用、中断处理、进程调度),处于最高特权级,可直接操作所有硬件 / 内存 管理员操作电脑,可拆硬件、改系统配置

CPU 当前的执行态 :内核态 / 用户态 的信息,实时存储在 CPU 的段寄存器(CS)的低 2 位(硬件层面);而进程的 "执行态快照"(比如进程上次被切换时的状态),则存储在内核的进程控制块(PCB)中。

底层支撑:CPU 特权级 & 内存地址空间

内核态 / 用户态的实现依赖两大硬件 / 系统机制:CPU 特权级内存地址空间划分

1. CPU 特权级(硬件层面的权限基础)

x86 架构的 CPU 设计了 4 个特权级(Ring 0~3),Linux 仅使用其中两个:

  • Ring 0:内核态,最高特权级,可执行所有 CPU 指令(包括特权指令,如操作内存管理单元 MMU、读写控制寄存器),访问所有硬件资源;
  • Ring 3:用户态,最低特权级,仅能执行普通指令(如加减运算、逻辑判断),禁止执行特权指令,禁止直接访问硬件。

为什么不用 Ring1/Ring2?Linux 追求简洁,内核态(Ring0)直接掌控所有核心资源,中间级别的特权级无实际价值,反而增加复杂度。

关键硬件寄存器(态的标识)

CPU 通过寄存器标记当前特权级:

  • CS 寄存器(代码段寄存器):低 2 位表示 "请求特权级(CPL)",0 = 内核态,3 = 用户态;
  • CR0 寄存器:PE 位(保护模式位)开启后,CPU 才会启用特权级检查(Linux 启动后始终开启)。

2. 内存地址空间划分(空间层面的隔离)

Linux 为每个进程分配独立的 "虚拟地址空间",该空间被划分为用户空间内核空间两部分,且内核空间对所有进程共享。

(1)32 位 Linux 地址空间(4GB 总容量)
区域 地址范围 所属状态 核心特征
用户空间 0~3GB 用户态 每个进程独立(如进程 A 的 0x1000≠进程 B 的 0x1000)
内核空间 3GB~4GB 内核态 所有进程共享(映射到物理内存的同一区域)
(2)64 位 Linux 地址空间(实际可用 48 位地址,256TB 总容量)
区域 地址范围 所属状态 核心特征
用户空间 0~0x7FFFFFFFFFFF(128TB) 用户态 每个进程独立
内核空间 0xFFFF800000000000~...(128TB) 内核态 所有进程共享

关键要点:

  • 进程在用户态时,只能访问自身的用户空间,无法直接访问内核空间;
  • 进程进入内核态后,可同时访问内核空间当前进程的用户空间(内核需读取用户程序传递的参数时会用到);
  • 内核空间是 "共享的":所有进程的内核空间映射到物理内存的同一区域,保证内核代码 / 数据的唯一性。

内核态 vs 用户态:核心差异(全维度对比)

对比维度 用户态 内核态
CPU 特权级 Ring 3(低特权) Ring 0(最高特权)
可执行指令 仅普通指令(如算术运算、逻辑判断) 所有指令(含特权指令:如操作 MMU、读写 CR 寄存器)
地址访问范围 仅自身用户空间 内核空间 + 当前进程用户空间
硬件操作 禁止直接操作(如读写磁盘、网卡) 可直接操作所有硬件
崩溃影响 仅进程自身崩溃(如段错误) 可能导致系统宕机(如内核 panic)
上下文类型 进程上下文(可被调度) 进程上下文 / 中断上下文(中断上下文不可调度)
内存分配 调用 malloc(依赖内核 brk/mmap) 调用 kmalloc/__get_free_pages
系统调用权限 只能发起调用,不能执行调用逻辑 执行系统调用的核心逻辑
信号处理 接收信号,在用户态执行处理函数 内核态完成信号的投递和触发

内核态 ↔ 用户态:切换机制(核心重点)

CPU 在两种状态间的切换是 "被动 / 主动触发" 的,切换过程需经过内核严格校验,且伴随 "现场保护 / 恢复",是系统开销的重要来源。

1. 用户态 → 内核态(3 种触发方式)

这是 "用户程序请求内核服务" 或 "系统处理紧急事件" 的过程,核心是 "陷入内核(Trap to Kernel)"。

(1)主动触发:系统调用(最常见)

用户程序需要使用内核资源(如读写文件、创建进程)时,主动调用内核提供的 "接口",触发态切换。

详细流程(以 64 位 Linux 调用 read() 为例):
  1. 用户态准备参数 :用户程序将 read 的参数(文件描述符、缓冲区地址、长度)存入寄存器(如 RDI、RSI、RDX);
  2. 触发系统调用 :执行 syscall 指令(32 位是 int 0x80 中断),该指令会:
    • 将当前 CPU 特权级从 Ring3 改为 Ring0;
    • 保存用户态的现场(PC、SP、通用寄存器)到内核栈;
    • 跳转到内核的系统调用入口(sys_call_table);
  3. 内核执行逻辑 :内核根据系统调用号(如 read 对应 0),从 sys_call_table 找到 sys_read 函数,执行读文件的核心逻辑(直接操作磁盘 / 缓冲区);
  4. 返回准备 :内核将 read 的返回值存入寄存器,准备恢复用户态现场。
(2)被动触发:硬件中断(异步)

硬件完成工作后(如键盘按下、磁盘读写完成),触发中断控制器向 CPU 发信号,强制切换到内核态处理中断。

详细流程(以键盘输入为例):
  1. 硬件触发中断:键盘完成输入,向 IO APIC 发送中断请求(中断号 1);
  2. CPU 响应中断:CPU 暂停当前用户程序的执行,关中断,保护用户态现场(保存寄存器到内核栈);
  3. 切换到内核态:CPU 将特权级改为 Ring0,根据中断号查中断向量表(IDT),跳转到键盘中断处理程序;
  4. 内核处理中断:内核读取键盘输入数据,存入内核缓冲区,标记 "待处理";
  5. 准备返回:恢复用户态现场,开中断,准备切回用户态。
(3)被动触发:异常(同步)

用户程序执行错误指令(如除 0、访问非法内存、缺页)时,CPU 触发 "异常",强制切换到内核态处理。

详细流程(以缺页异常为例):
  1. 用户态触发异常:用户程序访问未映射到物理内存的虚拟地址,CPU 检测到后触发缺页异常(中断号 14);
  2. 切换到内核态 :CPU 保护用户态现场,改为 Ring0,跳转到内核的缺页异常处理函数 do_page_fault
  3. 内核处理异常
    • 若地址合法:内核分配物理页,建立虚拟地址→物理地址映射,恢复用户程序执行;
    • 若地址非法:内核向进程发送 SIGSEGV 信号,进程在用户态崩溃;
  4. 返回用户态:恢复现场,继续执行(或终止进程)。

2. 内核态 → 用户态(唯一核心场景)

内核完成工作后(系统调用执行完、中断 / 异常处理完),主动切回用户态,恢复用户程序的执行。

详细流程:
  1. 内核完成工作:系统调用 / 中断 / 异常的核心逻辑执行完毕;
  2. 恢复现场:从内核栈中取出之前保存的用户态现场(PC、SP、寄存器),写回 CPU 寄存器;
  3. 切换特权级:将 CPU 特权级从 Ring0 改回 Ring3;
  4. 执行返回指令 :执行 sysret(64 位)/iret(32 位)指令,CPU 跳回用户态程序的下一条指令,继续执行。

3. 切换的核心开销

态切换的开销主要来自:

  • 现场保护 / 恢复:读写 CPU 寄存器、内核栈;
  • 特权级校验:CPU 检查权限、更新寄存器;
  • 缓存刷新:用户态 / 内核态的地址空间切换可能导致 TLB(地址转换缓存)刷新。

优化思路:工作中减少不必要的系统调用(如批量读写文件,而非逐字节读写),可降低态切换开销,提升程序性能。

典型场景:不同操作的态分布

操作场景 状态切换流程
执行 printf("hello") 用户态(拼接字符串)→ 内核态(sys_write 写标准输出)→ 用户态(继续执行)
按 Ctrl+C 终止进程 硬件中断(键盘)→ 内核态(处理中断,向进程发 SIGINT)→ 用户态(进程响应信号,终止)
进程睡眠(sleep (1)) 用户态(调用 sleep)→ 内核态(设置定时器,将进程置为睡眠态,调度其他进程)→ 时钟中断触发后,内核态唤醒进程 → 用户态(继续执行)
访问非法内存 用户态(执行访问指令)→ 内核态(处理缺页异常,发 SIGSEGV)→ 用户态(进程崩溃)

实战关联:工作中如何感知 / 优化态切换?

1. 查看进程的态开销

  • top 命令%sys 列表示 CPU 用于内核态的时间占比,若该值过高,说明系统调用 / 中断过多;
  • strace 命令 :跟踪进程的系统调用(如 strace -c ls),查看调用次数 / 耗时,定位频繁的系统调用;
  • perf 工具perf trace -p <pid> 实时跟踪进程的态切换和系统调用,分析开销来源。

2. 常见问题与优化

(1)% sys 过高(内核态 CPU 占比高)
  • 原因:进程频繁调用系统调用(如逐字节 read/write)、硬件中断频繁(如高频网络包);
  • 优化:
    • 批量操作(如用缓冲区一次性读写大量数据,减少 read/write 调用次数);
    • 优化中断频率(如网络网卡的中断合并);
    • 用内存映射(mmap)替代 read/write,减少系统调用。
(2)用户态程序无法访问硬件
  • 本质:用户态无硬件操作权限,需通过内核驱动提供的系统调用 / 设备文件间接访问;
  • 解决:编写内核驱动,暴露设备文件(如 /dev/xxx),用户程序通过 open/read/write 访问。
(3)内核态崩溃(内核 panic)
  • 现象:系统卡死,控制台打印 Kernel panic - not syncing
  • 原因:内核代码错误(如空指针、越界访问)、硬件故障;
  • 排查:通过 dmesg、内核崩溃日志(/var/crash)定位错误代码行,修复内核模块 / 驱动。

关键补充:易混淆概念区分

1. 态切换 vs 进程切换

  • 态切换:CPU 特权级的变化(Ring3↔Ring0),仅涉及一个进程的上下文保存 / 恢复;
  • 进程切换:内核将 CPU 从一个进程切换到另一个进程,伴随态切换(通常是内核态下完成),需保存 / 恢复两个进程的上下文,开销更大。

2. 内核空间 vs 用户空间

  • 内核空间:所有进程共享,仅内核态可直接访问,存储内核代码 / 数据、硬件驱动;
  • 用户空间:每个进程独立,用户态仅能访问自身的用户空间,存储进程的代码 / 数据 / 栈。

3. 内核线程 vs 用户线程

  • 内核线程:全程运行在内核态,无用户空间,用于执行内核任务(如 kworker、kswapd);
  • 用户线程:大部分时间运行在用户态,仅需内核服务时切换到内核态。

核心总结

  1. 核心目的 :内核态 / 用户态的区分是为了权限隔离,保护系统核心资源不被用户程序破坏;
  2. 底层支撑:CPU 特权级(Ring0/Ring3)实现权限控制,虚拟地址空间划分实现空间隔离;
  3. 切换触发:用户态→内核态靠 "系统调用(主动)、中断 / 异常(被动)",内核态→用户态靠 "恢复现场 + 返回指令";
  4. 实战价值:理解态切换能排查 "CPU 占比高、程序性能差、系统崩溃" 等问题,优化程序的系统调用频率可显著提升性能;
  5. 核心原则:Linux 系统的运行本质是 "用户程序绝大部分时间在用户态执行,仅需内核资源时短暂切到内核态,用完即返回"。

简单来说:用户态是 "普通程序的安全区",内核态是 "系统核心的管控区",二者的切换是 "普通用户找管理员办事" 的过程,管理员(内核)会严格校验并代劳所有危险操作。

Linux 用户级页表 & 内核级页表 深度讲解

简单来说:用户级页表是 "进程的私人地址簿",每个进程一本,记录自己的虚拟地址对应哪块物理内存;内核级页表是 "系统的公共地址簿",所有进程共享,记录内核的虚拟地址对应哪块物理内存,二者结合实现了 "进程独立运行,内核统一管控" 的目标。

  1. 本质区别:用户级页表是进程私有,映射用户空间,保证进程隔离;内核级页表是全局共享,映射内核空间,保证内核统一管控资源;
  2. 协同方式:每个进程的页表包含用户和内核两部分,进程切换时仅切换用户级页表,内核级页表共享,兼顾隔离性和效率;
  3. 权限控制:通过页表的 U/S 位,实现用户态只能访问用户空间,内核态可访问所有空间,保证系统安全;
  4. 实战价值:理解页表机制能排查段错误、内核崩溃、内存泄漏等问题,优化程序的内存访问效率,提升系统性能。

先铺垫:页表的核心作用(为什么需要页表?)

Linux 采用虚拟内存机制,每个进程看到的是独立的「虚拟地址空间」(32 位 4GB/64 位 256TB),而实际数据存储在物理内存中。页表的核心作用是:

建立虚拟地址(VA)物理地址(PA) 的映射关系,让 CPU 能通过虚拟地址找到对应的物理内存位置。

页表的实现依赖硬件(内存管理单元 MMU)和软件(内核页表管理)协同:CPU 执行指令时,MMU 自动查询页表,将虚拟地址转换为物理地址;内核负责维护页表的创建、修改和销毁。

用户级页表与内核级页表的核心定义

在 Linux 中,每个进程拥有一套独立的页表,但这套页表分为两个逻辑部分:

页表类型 核心定义 所属范围
用户级页表 映射进程用户空间虚拟地址到物理地址的页表部分,每个进程独立存在,存储进程的代码、数据、栈等私有资源 进程私有(每个进程一套)
内核级页表 映射内核空间虚拟地址到物理地址的页表部分,所有进程共享,存储内核代码、数据、硬件驱动等全局资源 系统全局(所有进程共享)

关键澄清:不是 "每个进程有两个页表(用户 + 内核)",而是每个进程的页表包含 "用户空间映射" 和 "内核空间映射" 两部分

  • 用户空间映射(用户级页表):每个进程不同,保证进程隔离;
  • 内核空间映射(内核级页表):所有进程相同,保证内核空间全局共享。

用户级页表(进程私有)

1. 核心作用

  • 映射用户空间:将进程的用户空间虚拟地址(32 位 0~3GB,64 位 0~128TB)映射到物理内存的私有区域;
  • 保证进程隔离:每个进程的用户级页表独立,进程 A 的虚拟地址 0x1000 和进程 B 的 0x1000 会映射到不同的物理地址,互不干扰;
  • 实现内存保护:通过页表权限位,限制用户态程序只能访问自身的用户空间,禁止访问内核空间和其他进程的用户空间。

2. 映射范围与内容

用户级页表仅映射进程的用户空间,包含以下核心内容:

用户空间区域 虚拟地址范围(64 位) 映射内容
代码段 低地址区域 进程的可执行代码(如 C++ 编译后的二进制指令)
数据段 / 堆 代码段上方 全局变量、动态分配的内存(malloc/new 分配)
高地址区域 函数栈帧、局部变量、函数参数
共享库 堆与栈之间 动态链接库(如 libc.so)的代码和数据

3. 权限控制(关键安全机制)

用户级页表的每个页表项(PTE)包含权限位,核心控制用户态 / 内核态的访问权限:

  • U/S 位(User/Supervisor) :设为 1 时,表示该页可在用户态访问 ;设为 0 时,仅能在内核态访问。用户级页表的所有页表项 U/S 位 = 1,保证用户态程序可访问自身用户空间;
  • R/W 位(Read/Write):设为 1 时,该页可读写;设为 0 时,仅可读(用于代码段,防止程序误修改自身指令);
  • P 位(Present):设为 1 时,表示该页已映射到物理内存;设为 0 时,表示该页未映射(触发缺页异常)。

4. 生命周期管理

用户级页表与进程的生命周期绑定:

  • 创建 :进程创建时(fork),内核为新进程复制父进程的用户级页表(写时复制 COW),后续进程修改内存时,内核会分配新的物理页并更新页表;
  • 修改 :进程动态分配内存(malloc)、加载共享库时,内核会修改用户级页表,添加新的虚拟地址→物理地址映射;
  • 销毁 :进程退出时(exit),内核销毁该进程的用户级页表,释放对应的物理内存。

5. 缺页异常处理

当进程访问未映射的虚拟地址(P 位 = 0)时,触发用户缺页异常,内核处理流程:

  1. 内核检查虚拟地址是否合法(是否在用户空间范围内);
  2. 若地址非法:向进程发送 SIGSEGV 信号,进程崩溃(段错误);
  3. 若地址合法:
    • 分配物理页框;
    • 更新用户级页表,建立虚拟地址→物理地址映射;
    • 恢复进程执行,进程感知不到异常,继续运行。

内核级页表(全局共享)

1. 核心作用

  • 映射内核空间:将内核空间虚拟地址(32 位 3GB~4GB,64 位 128TB~256TB)映射到物理内存的内核区域;
  • 保证内核共享:所有进程的内核级页表完全相同,切换进程时无需修改内核空间映射,内核可快速访问全局资源;
  • 支撑内核功能:映射内核代码、数据、硬件驱动、进程 PCB、页表等核心结构,保证内核正常运行。

2. 映射范围与内容

内核级页表映射内核空间,Linux 内核空间分为多个功能区域(以 64 位为例):

内核空间区域 虚拟地址范围 映射内容
直接映射区 128TB~128TB + 物理内存大小 物理内存的直接映射(物理地址 x → 虚拟地址 = 128TB+x),用于访问物理内存的低端区域
vmalloc 区 直接映射区上方 动态分配的内核内存(连续虚拟地址,物理地址可离散)
永久映射区 vmalloc 区上方 临时映射高端物理内存(如高端内存页)
固定映射区 接近 128TB+2^48 内核固定用途的映射(如进程 PCB、页表)

关键特性:直接映射区是内核最常用的区域,物理内存与虚拟地址一一对应,内核可直接通过虚拟地址访问物理内存,无需复杂计算。

3. 权限控制(内核专属)

内核级页表的页表项权限位与用户级相反,核心限制用户态访问:

  • U/S 位 = 0 :表示该页仅能在内核态访问,用户态程序无法直接访问内核空间的虚拟地址(若访问会触发页错误,导致段错误);
  • R/W 位 = 1:内核空间通常可读写(代码段除外,设为只读);
  • P 位 = 1:内核空间的核心代码和数据始终驻留物理内存(不会被换出到磁盘),保证内核随时可访问。

4. 生命周期管理

内核级页表是系统全局资源,生命周期与内核绑定:

  • 创建 :内核启动时(start_kernel),初始化内核级页表,建立内核空间的映射;
  • 修改 :内核加载驱动、动态分配内核内存(kmalloc/vmalloc)时,内核会修改内核级页表,添加新的映射;
  • 销毁:仅当系统关机 / 重启时,内核级页表才会被销毁。

5. 缺页异常处理

内核级页表的缺页异常(内核缺页)比用户缺页更严重:

  • 若内核访问未映射的内核空间地址,触发内核缺页异常
  • 内核会检查地址合法性:
    • 若地址合法(如 vmalloc 分配的内存未建立映射):建立映射,恢复执行;
    • 若地址非法:触发内核 panic(内核崩溃),系统宕机(内核是系统核心,无法像用户进程一样优雅退出)。

用户级页表与内核级页表的协同机制

1. 页表的物理结构(以 x86_64 为例)

Linux 采用四级页表架构(页全局目录 PGD → 页上级目录 PUD → 页中间目录 PMD → 页表项 PTE),用户级和内核级页表共享同一套页表结构,只是映射的虚拟地址范围不同:

  • 每个进程的 PGD(页全局目录)包含两个部分:
    • 低地址条目:映射用户空间(0~128TB),即用户级页表;
    • 高地址条目:映射内核空间(128TB~256TB),即内核级页表,所有进程的高地址条目完全相同,指向同一个内核页表结构。

2. 进程切换时的页表处理

进程切换是 Linux 多任务的核心,页表切换的逻辑如下:

  1. 内核将当前进程的上下文(包括 CR3 寄存器的值)保存到 PCB;
  2. 加载新进程的 PCB,将新进程的 PGD 基址写入 CR3 寄存器(x86_64 中 CR3 存储当前页表的基址);
  3. MMU 刷新 TLB(地址转换缓存),清除旧进程的地址转换记录;
  4. 新进程开始执行。

关键优化:由于所有进程的内核级页表完全相同,切换进程时,仅需切换用户级页表的映射(CR3 指向新进程的 PGD),内核空间的映射无需改变 ------ 内核仍可通过新进程的页表访问内核空间,保证了切换效率。

3. 态切换时的页表访问

  • 用户态:CPU 只能访问用户级页表映射的用户空间(U/S=1),访问内核空间会触发页错误;
  • 内核态:CPU 可同时访问用户级页表(当前进程的用户空间)和内核级页表(内核空间)------ 内核需要访问用户进程的数据时(如系统调用传递参数),可通过当前进程的用户级页表访问用户空间。

核心区别对比(用户级 vs 内核级页表)

对比维度 用户级页表 内核级页表
所属范围 进程私有(每个进程一套) 系统全局(所有进程共享)
映射空间 用户空间(0~128TB,64 位) 内核空间(128TB~256TB,64 位)
权限控制 U/S=1(用户态可访问) U/S=0(仅内核态可访问)
生命周期 与进程绑定(创建→销毁) 与内核绑定(启动→关机)
缺页影响 用户缺页,进程可能崩溃(SIGSEGV) 内核缺页,可能导致系统宕机(panic)
内存回收 可被换出到磁盘(swap) 核心代码 / 数据不会被换出
管理主体 进程 + 内核协同管理 内核独立管理

实战关联:工作中如何感知页表?

1. 查看进程的页表信息

  • /proc/<pid>/maps :查看进程的用户空间映射(用户级页表的内容),包括代码段、数据段、栈、共享库的虚拟地址范围和权限;

    bash

    运行

    复制代码
    cat /proc/1/maps  # 查看init进程的用户空间映射
  • /proc/<pid>/pagemap:查看进程每个虚拟页的物理地址映射(需 root 权限),可分析内存使用情况;

  • perf record -e page-faults:跟踪进程的缺页异常,定位频繁缺页的代码路径(优化内存访问效率)。

2. 常见问题与页表的关联

(1)进程段错误(SIGSEGV)
  • 原因之一:进程访问了未映射的用户空间地址(用户级页表 P 位 = 0),或访问了内核空间地址(用户态访问 U/S=0 的页);
  • 排查:通过 gdb 定位错误指令,结合 /proc/<pid>/maps 查看该地址是否属于用户空间的合法范围。
(2)内核 panic(内核崩溃)
  • 原因之一:内核访问了未映射的内核空间地址(内核级页表 P 位 = 0),或非法修改了页表权限;
  • 排查:查看内核崩溃日志(/var/crashdmesg),定位错误代码行,修复内核驱动或模块。
(3)内存泄漏
  • 用户态内存泄漏:进程的用户级页表映射的物理页不断增加,通过 top 查看 RES 字段持续增长;
  • 内核态内存泄漏:内核级页表映射的物理页不断增加,通过 cat /proc/meminfo 查看 Slab 字段持续增长。

3. 性能优化与页表

  • 减少缺页异常 :批量分配内存(如用 mmap 分配大块内存)、减少随机内存访问,降低页表的修改和缺页处理开销;
  • 优化 TLB 命中率 :TLB 是页表的缓存,频繁切换进程会导致 TLB 刷新,降低命中率。通过绑定进程到 CPU(taskset),减少 TLB 刷新,提升性能。
相关推荐
QT 小鲜肉11 小时前
【Linux命令大全】002.文件传输之ftpwho命令(实操篇)
linux·运维·服务器·网络·chrome·笔记
应用市场11 小时前
Linux进程调度与多核CPU深度解析——从内核调度器到实战优化
linux·运维·服务器
帝落若烟11 小时前
ubuntu安装禅道
linux·运维·ubuntu
天上飞的粉红小猪11 小时前
线程同步与互斥
linux·开发语言·c++
大聪明-PLUS12 小时前
Linux 网络和流量加密完整指南(第一部分)
linux·嵌入式·arm·smarc
松涛和鸣12 小时前
DAY43 HTML Basics
linux·前端·网络·网络协议·tcp/ip·html
谁在夜里看海.13 小时前
【Linux-网络】HTTP的清风与HTTPS的密语
linux·网络·http·https
HIT_Weston13 小时前
82、【Ubuntu】【Hugo】搭建私人博客:文章目录(一)
linux·运维·ubuntu
CAU界编程小白13 小时前
Linux系统编程系列之文件fd
linux·文件