Linux内核源码结构全景解析

文章目录

引言

Linux内核作为操作系统的核心,其源码结构之庞大、设计之精妙,让无数开发者为之着迷。当你第一次下载并解压内核源码时,面对几十个子目录、上万个源文件,可能会感到不知所措。但如果能够理解内核的目录组织方式、构建系统的工作原理,以及各个子模块的职责划分,你会发现这些看似复杂的结构背后,其实是经过精心设计的、层次分明的架构。

本文将以Linux 2.6.20版本为例,带领读者全面解析内核的源码结构。我们将从根目录的顶层设计开始,深入分析Makefile构建系统的精妙实现,剖析Kconfig配置系统的工作机制,并通过实际的源码分析和实践演示,帮助读者建立起内核源码的完整认知地图。这不仅是理解内核工作原理的基础,更是进行内核开发、调试和优化的必备知识。

内核目录结构的顶层设计

Linux内核源码的顶层目录结构并非随意堆砌,而是按照功能和职责进行了清晰的划分。理解这些目录的组织方式,就如同拿到了一张导航地图,能让你在内核的代码海洋中快速定位到需要关注的部分。

让我们先通过一个架构图来直观地了解内核目录的整体布局:
linux-2.6.20 根目录
核心代码目录
架构相关目录
文档与配置
驱动程序目录
构建系统目录
kernel/ - 内核核心
mm/ - 内存管理
fs/ - 文件系统
ipc/ - 进程间通信
net/ - 网络协议
crypto/ - 加密支持
lib/ - 库函数
block/ - 块设备层
init/ - 初始化
security/ - 安全框架
arch/ - 架构相关代码
drivers/ - 设备驱动
scripts/ - 构建脚本
include/ - 头文件
Documentation/ - 文档
Kconfig* - 配置文件
Makefile - 构建文件

核心子系统目录

内核的核心功能都集中在几个关键目录中,这些目录包含了内核最重要的子系统实现:

  • kernel/: 内核的核心代码,包括进程调度、信号处理、系统调用等核心功能。这里实现了内核最基本的调度机制、模块加载、定时器管理等。

  • mm/: 内存管理子系统,负责虚拟内存管理、物理内存分配、页面回收等功能。这是内核最复杂的部分之一。

  • fs/: 文件系统子系统,实现了VFS虚拟文件系统以及各种具体文件系统(如ext2、ext3、proc、sysfs等)。

  • net/: 网络协议栈,实现了TCP/IP协议栈、套接字接口、各种网络协议等。

  • ipc/: 进程间通信机制,包括信号量、消息队列、共享内存等System V IPC。

  • drivers/: 设备驱动程序,包含了几乎所有硬件设备的驱动代码,按照设备类型进行了细分。

架构相关代码

arch/ 目录是一个特殊的目录,它包含了与特定CPU架构相关的代码。Linux内核支持多种硬件架构,每种架构都有其特定的汇编代码、启动代码、硬件抽象等。例如:

  • arch/i386/ - x86架构
  • arch/arm/ - ARM架构
  • arch/powerpc/ - PowerPC架构

这种设计使得内核可以方便地移植到新的硬件平台上,而核心代码保持平台无关性。

头文件目录

include/ 目录包含了内核源码中使用的所有头文件。这个目录同样按照功能进行了划分:

  • include/linux/ - 通用的内核头文件,定义了内核中通用的数据结构、常量、函数声明等
  • include/asm/ - 架构相关的头文件,通过符号链接指向 include/asm-$(ARCH)/
  • include/asm-generic/ - 架构无关的通用汇编头文件

构建系统与文档

  • scripts/: 包含内核构建过程中使用的各种脚本工具,如配置工具、文档生成工具等。

  • Documentation/: 详细的内核文档,涵盖了内核开发的各个方面,是学习内核的重要资料。

Makefile构建系统深度解析

内核的构建系统是理解内核源码的关键入口。Linux内核使用了一套名为kbuild的构建系统,它基于GNU make,但进行了大量的扩展和定制。让我们深入分析顶层Makefile的实现机制。

内核版本信息的定义

Makefile的前几行定义了内核的版本信息:

makefile 复制代码
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 20
EXTRAVERSION =
NAME = Homicidal Dwarf Hamster

这些宏定义构成了内核版本号 2.6.20,NAME 是该版本的代号。通过这种方式,构建系统可以自动生成正确的版本信息,用于内核的编译和打包。

递归构建策略

内核采用的是递归构建策略。顶层Makefile会调用各个子目录的Makefile,逐步完成整个内核的编译。关键代码如下:

makefile 复制代码
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
             $(core-y) $(core-m) \
             $(drivers-y) $(drivers-m) \
             $(net-y) $(net-m) \
             $(libs-y) $(libs-m)))

这里定义了需要进入构建的所有子目录。各个子目录通过变量进行组织,例如:

makefile 复制代码
init-y     := init/
drivers-y  := drivers/ sound/
net-y      := net/
libs-y     := lib/
core-y     := usr/

最终这些目录会被转换为对应的 built-in.o 目标文件:

makefile 复制代码
init-y     := $(patsubst %/, %/built-in.o, $(init-y))
core-y     := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y  := $(patsubst %/, %/built-in.o, $(drivers-y))

内核镜像的链接过程

vmlinux是最终的内核镜像文件,其链接过程是构建系统的核心:

makefile 复制代码
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds

链接命令的定义如下:

makefile 复制代码
quiet_cmd_vmlinux__ ?= LD      $@
      cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
      -T $(vmlinux-lds) $(vmlinux-init) \
      --start-group $(vmlinux-main) --end-group \
      $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)

这个命令展示了链接器的使用方式:

  • 使用 -T 选项指定链接脚本 vmlinux.lds
  • vmlinux-init 部分必须首先链接
  • 使用 --start-group 和 --end-group 处理符号依赖

递归进入子目录的规则

如何让Makefile递归进入每个子目录进行构建?关键规则如下:

makefile 复制代码
PHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts
    $(Q)$(MAKE) $(build)=$@

这里使用了kbuild定义的 ( b u i l d ) 变量,它会展开为相应的 m a k e 参数和规则。 (build) 变量,它会展开为相应的make参数和规则。 (build)变量,它会展开为相应的make参数和规则。(Q) 变量用于控制输出的详细程度,当 KBUILD_VERBOSE=0 时,这个变量为 @,表示不显示命令本身。

构建系统的输出美化

内核构建系统提供了一套输出美化机制,可以根据用户的需要控制输出的详细程度:

makefile 复制代码
ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

当用户执行 make V=1 时,会看到完整的编译命令;默认情况下则只看到简短的提示信息。例如:

makefile 复制代码
quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
      cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<

通过这种机制,既可以在调试时看到详细信息,又可以在正常编译时保持输出简洁。

Kconfig配置系统的工作原理

Linux内核的灵活性很大程度上归功于其配置系统。Kconfig允许用户通过图形界面、文本界面等方式定制内核功能,只编译需要的模块,从而减小内核体积、优化性能。

配置系统的基本结构

内核的配置系统由以下几个部分组成:

  • Kconfig文件: 分布在各个目录中,描述了该目录下的配置选项
  • 配置工具: 位于 scripts/kconfig/ 目录,包括 conf、mconf、qconf 等
  • 配置文件: .config 文件存储了当前的配置结果

Kconfig语法示例

让我们看一个简单的Kconfig文件示例,了解其语法结构:

kconfig 复制代码
config NET
    bool "Networking support"
    depends on !UML
    default y
    help
      This option enables networking support in the kernel.

      If you say Y here, your Linux system will be able to act as a
      network server or client, and you will be able to use networking
      features such as NFS.

config INET
    bool "TCP/IP networking"
    depends on NET
    default y
    help
      These are the protocols used on the Internet.

配置选项的类型

Kconfig支持多种配置选项类型:

  • bool: 布尔选项,值为 y 或 n
  • tristate: 三态选项,值为 y、m 或 n(支持编译为模块)
  • string: 字符串选项
  • int: 整数选项
  • hex: 十六进制选项

配置选项的依赖关系

depends on 关键字用于指定配置选项的依赖关系:

kconfig 复制代码
config EXT3_FS
    tristate "Ext3 journalling file system support"
    depends on BLOCK
    select JBD
    help
      This is the journaling version of the Second Extended file system.

这里表示EXT3文件系统依赖于 BLOCK 配置,并且会自动选中 JBD 配置。

配置流程

当用户运行 make menuconfig 时,配置系统的工作流程如下:
Config File Kconfig Parser Menuconfig User Config File Kconfig Parser Menuconfig User make menuconfig 解析所有Kconfig文件 构建配置树 显示配置界面 修改配置选项 保存到.config 读取旧配置(如果存在) 显示默认值 退出并保存 写入最终的.config

自动配置文件生成

配置完成后,系统会自动生成 include/linux/autoconf.h 文件,将配置选项转换为C语言的宏定义:

c 复制代码
#define CONFIG_NET 1
#define CONFIG_INET 1
#define CONFIG_EXT3_FS_MODULE 1

这样内核代码就可以通过 #ifdef CONFIG_NET 这样的预编译指令来根据配置情况选择不同的实现。

源码目录结构的详细解析

现在让我们深入探讨各个关键子目录的具体内容和作用。

init/ 目录 - 内核初始化

init/ 目录是内核初始化的核心所在,其中最重要的文件是 main.c,它包含了内核启动的入口函数 start_kernel():

c 复制代码
asmlinkage void __init start_kernel(void)
{
    char * command_line;
    extern struct kernel_param __start___param[], __stop___param[];
    
    lock_kernel();
    page_address_init();
    printk(KERN_NOTICE);
    printk(linux_banner);
    setup_arch(&command_line);
    setup_per_cpu_areas();
    smp_prepare_boot_cpu();
    sched_init();
    preempt_init();
    disable_early_printk();
    
    /* ... 更多初始化代码 ... */
}

这个函数是内核启动的总指挥,它依次初始化各个子系统,从最基础的内存管理开始,到进程调度、中断系统,最后才进入用户空间。

kernel/ 目录 - 核心功能实现

kernel/ 目录包含了内核的核心功能实现:

  • sched.c: 进程调度器的实现,包括CFS完全公平调度器
  • fork.c: 进程创建相关函数,如 do_fork()
  • exit.c: 进程退出相关函数,如 do_exit()
  • signal.c: 信号处理机制
  • module.c: 内核模块的加载和卸载

mm/ 目录 - 内存管理

内存管理是内核最复杂的部分之一,mm/ 目录包含了:

  • page_alloc.c: 物理页面分配器,实现了伙伴算法
  • slab.c: Slab分配器,用于高效分配小对象
  • vmalloc.c: 虚拟连续内存分配
  • swap.c: 交换空间管理

fs/ 目录 - 文件系统

文件系统子系统的核心:

  • super.c: 超级块管理
  • inode.c: inode节点管理
  • file_table.c: 文件表管理
  • namei.c: 路径名解析
  • 各具体文件系统的实现目录

drivers/ 目录 - 设备驱动

设备驱动目录按照设备类型进行了详细划分:

  • drivers/char/: 字符设备驱动
  • drivers/block/: 块设备驱动
  • drivers/net/: 网络设备驱动
  • drivers/usb/: USB设备驱动
  • drivers/scsi/: SCSI设备驱动

内核编译流程详解

理解内核的编译流程对于内核开发至关重要。让我们通过一个实际的例子来演示完整的编译过程。

编译流程图

内核的完整编译流程可以通过下图来展示:
配置目标
构建目标




开始编译
目标类型
运行配置工具
读取.config
menuconfig/xconfig
解析Kconfig文件
用户选择配置
生成.config
生成autoconf.h
准备阶段prepare
递归进入子目录
编译子目录源码
生成built-in.o
所有子目录完成?
链接生成vmlinux
编译模块?
编译模块.ko
生成System.map
编译完成

实际编译示例

让我们通过一个实际的编译示例来理解这个过程。假设我们要编译一个最小化的内核:

bash 复制代码
# 第一步: 配置内核
make defconfig
# 这会使用架构的默认配置生成.config文件

# 第二步: 查看配置
make menuconfig
# 可以在这里进行必要的配置修改

# 第三步: 开始编译
make -j4
# -j4 表示使用4个并行任务加速编译

# 第四步: 查看生成的文件
ls -l vmlinux System.map arch/x86/boot/bzImage

构建系统的依赖关系处理

构建系统需要精确处理源码文件之间的依赖关系。它通过生成 .cmd 文件来记录依赖信息:

makefile 复制代码
cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $f).$(notdir $f).cmd))

ifneq ($(cmd_files),)
  $(cmd_files): ;
  include $(cmd_files)
endif

这些 .cmd 文件包含了目标文件依赖的源文件和头文件列表,当任何一个依赖文件发生变化时,构建系统会自动重新编译相应的目标文件。

模块的编译与加载

如果配置中启用了模块支持(CONFIG_MODULES=y),内核会编译可加载的模块:

bash 复制代码
# 编译模块
make modules

# 安装模块
make modules_install

# 模块会被安装到 /lib/modules/$(KERNELRELEASE)/ 目录下

模块的编译过程与内核类似,但最终生成的是 .ko(kernel object)文件,这些文件可以在系统运行时动态加载。

源码分析实践

现在让我们通过实际的源码分析,来加深对内核构建系统的理解。

分析Makefile中的关键变量

打开顶层Makefile,我们可以看到许多关键变量的定义:

makefile 复制代码
# 版本信息
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 20

# 编译器工具链
AS      = $(CROSS_COMPILE)as
LD      = $(CROSS_COMPILE)ld
CC      = $(CROSS_COMPILE)gcc

# 编译标志
CFLAGS  := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
           -fno-strict-aliasing -fno-common

# 头文件路径
LINUXINCLUDE := -Iinclude \
                $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
                -include include/linux/autoconf.h

追踪vmlinux的生成过程

让我们追踪 vmlinux 是如何生成的。首先找到其依赖规则:

makefile 复制代码
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
    $(call if_changed_rule,vmlinux__)

这个规则表示 vmlinux 依赖于:

  • 链接脚本 vmlinux-lds
  • 初始化部分 vmlinux-init
  • 主要部分 vmlinux-main
  • 符号表 kallsyms.o

查看子目录的Makefile

每个子目录都有自己的Makefile,它们遵循统一的格式。例如 kernel/Makefile:

makefile 复制代码
# Makefile for the linux kernel.
#
obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
            profile.o exit.o itimer.o time.o softirq.o resource.o \
            sysctl.o capability.o ptrace.o timer.o user.o \
            signal.o sys.o kmod.o workqueue.o pid.o \
            rcupdate.o intermodule.o extable.o params.o posix-timers.o \
            kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o \
            reboot.o

obj-$(CONFIG_DEBUG_KERNEL) += debug/
obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o

这里的 obj-y 定义了要编译到内核中的对象,obj-$(CONFIG_xxx) 表示根据配置条件决定是否编译。

使用构建系统分析工具

内核提供了一些有用的工具来分析构建系统:

bash 复制代码
# 查看所有配置选项
make help

# 查看内核版本信息
make kernelversion

# 查看内核发布版本(包含本地版本信息)
make kernelrelease

# 生成依赖关系图
make tags

# 生成cscope索引
make cscope

常见问题与调试技巧

在学习和使用内核构建系统的过程中,经常会遇到一些问题。这里总结一些常见问题和解决方法。

编译错误排查

问题: 修改源码后重新编译,但修改没有生效

原因: 可能是依赖关系没有正确更新

解决方法:

bash 复制代码
# 清理中间文件
make clean

# 或者彻底清理所有生成文件
make mrproper

# 然后重新编译
make

配置问题

问题: 运行 make menuconfig 后看不到新添加的配置选项

原因: Kconfig文件中的依赖关系可能导致选项被隐藏

解决方法:

  • 检查Kconfig文件中的 depends on 语句
  • 使用 / 键在menuconfig中搜索选项
  • 查看生成的 .config 文件确认选项是否被设置为 # CONFIG_XXX is not set

交叉编译问题

问题: 需要为其他架构编译内核

解决方法:

bash 复制代码
# 指定目标架构和交叉编译工具链
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-

# 或者先设置环境变量
export ARCH=arm
export CROSS_COMPILE=arm-linux-
make menuconfig
make

模块加载失败

问题: 编译的模块无法加载

检查步骤:

  1. 确认模块版本与内核版本匹配
  2. 使用 dmesg 查看内核日志
  3. 检查模块的依赖关系: modinfo module.ko
  4. 尝试使用 insmod -f 强制加载(仅用于调试)

调试技巧

使用详细的编译输出:

bash 复制代码
# 显示完整的编译命令
make V=1

# 显示更详细的输出(包括为什么需要重新编译)
make V=2

单独编译某个文件:

bash 复制代码
# 编译特定的目标文件
make kernel/sched.o

# 编译特定的子目录
make kernel/

跟踪编译过程:

bash 复制代码
# 显示所有编译依赖
make -n vmlinux

# 只打印命令而不执行(用于调试Makefile)
make -n

内核源码阅读建议

掌握了内核的目录结构和构建系统后,如何高效地阅读内核源码呢?以下是一些建议。

从感兴趣的功能开始

不要试图一次性理解整个内核,应该从你感兴趣的功能模块开始:

  • 对进程调度感兴趣: 从 kernel/sched.c 开始
  • 对内存管理感兴趣: 从 mm/page_alloc.c 开始
  • 对文件系统感兴趣: 从 fs/namei.c 开始

使用工具辅助阅读

使用grep搜索:

bash 复制代码
# 搜索函数定义
grep -r "do_fork" --include="*.c"

# 搜索宏定义
grep -r "CONFIG_PREEMPT" --include="*.h"

# 在当前目录搜索
grep "schedule\(" *.c

使用cscope或tags:

bash 复制代码
# 生成cscope数据库
make cscope
# 使用cscope: cscope -d

# 生成tags文件
make tags
# 使用vim跳转: ctrl-]

理解数据结构是关键

内核中的核心数据结构定义在头文件中,理解这些数据结构是理解内核实现的关键:

  • task_struct: 进程描述符(定义在 include/linux/sched.h)
  • mm_struct: 内存描述符(定义在 include/linux/mm_types.h)
  • inode: 索引节点(定义在 include/linux/fs.h)
  • file: 文件结构(定义在 include/linux/fs.h)

关注函数调用链

理解内核功能的实现,需要追踪函数调用链。例如,要理解进程创建的过程,可以按照这个顺序阅读:

  1. 系统调用入口: sys_fork 或 sys_clone
  2. 通用实现: do_fork
  3. 复制进程: copy_process
  4. 设置进程状态: 各种设置函数

实践与实验

最好的学习方式是实践:

  1. 添加调试输出: 使用 printk 函数
  2. 修改代码并观察效果
  3. 编写内核模块进行实验
  4. 使用调试工具如 gdb、strace 等

构建系统的进阶技巧

对于想要深入研究内核构建系统的开发者,这里介绍一些进阶技巧。

输出目录分离

内核支持将编译输出文件与源码分离,这对于保持源码目录的整洁非常有用:

bash 复制代码
# 创建输出目录
mkdir build

# 在输出目录中编译
make O=build menuconfig
make O=build

# 编译后的文件都在build目录中
ls build/

并行编译加速

使用 -j 选项可以并行编译,大幅提高编译速度:

bash 复制代码
# 根据CPU核心数自动选择并行数
make -j$(nproc)

# 或者手动指定
make -j8

仅编译变更的文件

构建系统会自动检测文件的变更,只重新编译必要的文件。但有时候需要强制重新编译:

bash 复制代码
# 删除所有.o文件但保留.config
make clean

# 删除所有编译产物
make mrproper

# 重新开始编译
make

定制编译选项

可以通过环境变量或命令行定制编译选项:

bash 复制代码
# 启用额外的警告
make KCFLAGS="-Wextra"

# 启用代码静态检查
make C=1

# 使用特定的编译器
make CC=/usr/bin/gcc-4.9

分析编译时间

了解哪些文件的编译时间最长,可以帮助优化编译过程:

bash 复制代码
# 使用time命令
time make

# 或者使用更详细的timing工具
make V=1 2>&1 | time

总结

通过本文的深入学习,我们全面了解了Linux内核的源码结构和构建系统。让我们总结一下核心要点:

核心要点回顾

  1. 目录结构: 内核源码按功能清晰地划分为多个目录,每个目录负责特定的子系统,从kernel核心功能到mm内存管理,从fs文件系统到net网络协议,层次分明。

  2. 构建系统: kbuild构建系统基于GNU make,通过递归构建的方式组织整个内核的编译,从顶层Makefile开始,逐级调用子目录的Makefile,最终链接生成vmlinux内核镜像。

  3. 配置系统: Kconfig提供了灵活的内核配置机制,支持多种配置界面和复杂的依赖关系,允许用户根据自己的需求定制内核功能,生成.config配置文件和autoconf.h头文件。

  4. 编译流程: 从配置、准备、编译到链接,每个阶段都有明确的目标和规则,构建系统能够自动处理依赖关系,只编译变更的文件,大大提高了编译效率。

  5. 依赖管理: 构建系统通过 .cmd 文件精确管理源码文件之间的依赖关系,当依赖文件发生变化时,自动触发重新编译,确保编译结果的正确性。

延伸阅读建议

对于想要进一步深入学习的读者,建议:

  1. 阅读内核文档: Documentation/kbuild/ 目录包含了详细的构建系统文档,深入了解kbuild的工作原理和高级特性。

  2. 研究具体子系统的Makefile,理解它们的编写规范和变量使用,这对于进行内核模块开发非常有帮助。

  3. 尝试编写自己的内核模块,实践构建系统的使用,通过实际操作加深理解。

  4. 关注内核 mailing list,了解最新的开发动态和技术趋势,与其他内核开发者交流经验。

重要源码文件参考

以下是在本文中分析过的重要源码文件路径:

  • 顶层Makefile: Makefile
  • 构建脚本: scripts/Kbuild.include, scripts/Makefile.*
  • 配置系统: scripts/kconfig/conf.c, scripts/kconfig/mconf.c
  • 内核初始化: init/main.c
  • 进程调度: kernel/sched.c
  • 内存管理: mm/page_alloc.c
  • 文件系统: fs/namei.c

掌握这些知识,你就已经具备了深入研究内核内部实现的基础。接下来可以根据自己的兴趣,选择特定的子系统进行深入分析。内核源码的世界博大精深,但只要掌握了正确的入门方法和工具,就一定能够逐步揭开其神秘的面纱。


参考资料:

  • Linux内核官方文档: Documentation/ 目录
  • Kbuild文档: Documentation/kbuild/
  • 内核源码注释: 各源文件中的注释说明
  • Linux内核邮件列表: linux-kernel@vger.kernel.org
相关推荐
9分钟带帽2 小时前
debain系统更新软件源
linux·debain
yayatiantian_20222 小时前
Ubuntu 24.04 安装与配置 pyenv
linux·运维·python·ubuntu·pyenv
HIT_Weston2 小时前
109、【Ubuntu】【Hugo】搭建私人博客:搜索功能(五)
linux·javascript·ubuntu
Byte不洛2 小时前
《Linux线程原理详解:进程、轻量级进程(LWP)与pthread实战》
linux·多线程
坐怀不乱杯魂2 小时前
Linux - 进程信号
linux·c++
EverydayJoy^v^2 小时前
RH134学习进程——七.管理基本存储
运维·服务器·云计算
GAOJ_K2 小时前
交叉导轨如何避免无效安装
运维·人工智能·科技·自动化·制造
fanruitian3 小时前
k8s pv pvc 持久化存储
java·linux·kubernetes
Trouvaille ~3 小时前
【Linux】进程信号(一):信号的快速认识与五种产生方式
linux·运维·网络·c++·操作系统·信号处理·中断