Skip to content

Commit

Permalink
[docs]: update
Browse files Browse the repository at this point in the history
  • Loading branch information
TomSjtu committed Nov 4, 2024
1 parent dd147b5 commit 09b5a19
Show file tree
Hide file tree
Showing 19 changed files with 808 additions and 64 deletions.
Binary file added docs/images/kernel/elf.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/pl/go/channel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/pl/go/gpm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/pl/go/import.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
97 changes: 91 additions & 6 deletions docs/linux/drivers/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

使用`modinfo`命令可以获得模块的信息。

## 内核模块程序结构
## 模块程序结构

一个Linux内核模块主要由以下几个部分组成:

Expand Down Expand Up @@ -102,9 +102,94 @@ endif

## 模块管理工具

- lsmod:列出已经安装的模块
- insmod:手动安装模块
- rmmod:卸载模块
- modinfo:查看某个模块的详细信息
- modprobe:自动安装模块,并处理依赖关系
### 列出模块

可以使用`lsmod`命令列出列出所有内核模块,包括已加载和未加载的模块:

```SHELL
$ lsmod
Module Size Used by
arptable_filter 12702 1
xt_nat 12681 1
macvlan 19239 0
veth 13458 0
xt_CT 12956 2
nf_log_ipv4 12767 0
nf_log_common 13317 1 nf_log_ipv4
xt_LOG 12690 0
xt_limit 12711 0
iptable_raw 12678 1
ip_set_hash_net 36021 2
vxlan 53857 0
ip6_udp_tunnel 12755 1 vxlan
udp_tunnel 14423 1 vxlan
...
```

或使用`find`命令查看所有可用模块:

```SHELL
$ find /lib/modules/$(uname -r)/ -name '*.ko'
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/si470x/radio-si470x-usb.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/si470x/radio-si470x-i2c.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/tea575x.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/tef6862.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/radio-raremono.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/radio-si476x.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/radio-tea5764.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/radio-wl1273.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/radio-mr800.ko
/lib/modules/5.15.0-117-generic/kernel/drivers/media/radio/shark2.ko
...
```

### 显示模块信息

`modinfo`命令提供有关内核模块的信息,包括作者、描述、许可证、参数等:

```SHELL
$ modinfo usbhid
filename: /lib/modules/5.15.0-117-generic/kernel/drivers/hid/usbhid/usbhid.ko
license: GPL
description: USB HID core driver
author: Jiri Kosina
author: Vojtech Pavlik
author: Andreas Gal
srcversion: 541F12A52D5FDDAF4E19777
alias: usb:v*p*d*dc*dsc*dp*ic03isc*ip*in*
depends: hid
retpoline: Y
intree: Y
name: usbhid
vermagic: 5.15.0-117-generic SMP mod_unload modversions
sig_id: PKCS#7
signer: Build time autogenerated kernel key
sig_key: 45:00:3B:43:A0:87:2F:E9:C1:F9:9B:0C:A2:C6:3D:78:F7:15:94:98
sig_hashalgo: sha512
...
```

### 检查依赖关系

modules.dep 文件记录了模块之间的依赖关系,可以直接用`grep`命令搜索指定模块的依赖。也可以使用`modprobe`命令:

```SHELL
$ modprobe --show-depends usbhid
insmod /lib/modules/5.15.0-117-generic/kernel/drivers/hid/hid.ko
insmod /lib/modules/5.15.0-117-generic/kernel/drivers/hid/usbhid/usbhid.ko
```

### 加载模块

`modprobe`命令是最常用的加载模块的工具,它会自动处理模块依赖关系,而`insmod`命令则不会。

如果需要在 Linux 启动时自动加载模块,可以将模块的名称添加到`/etc/modules`文件中。


### 删除模块

可以使用`modprobe -r`命令删除模块,它会自动处理模块依赖关系。也可以使用`rmmod`命令。

### 生成依赖关系

`depmod`命令用于生成 modules.dep 文件,这些文件对于`modprobe`命令的自动处理依赖关系很有用。
2 changes: 0 additions & 2 deletions docs/linux/kernel/cma.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

![内存分配](../../images/kernel/mem_alloc.png)

https://www.laumy.tech/917.html

在嵌入式环境中,许多设备都需要连续内存块的操作,比如相机、视频解码器、音频设备等,早期内核驱动只能通过预留专属内存的方式,在映射后作为设备私有内存使用。这样的后果就是当设备不工作时,预留的内存页无法被当作通用内存使用,造成了内存的浪费。

连续内存分配(CMA)就是为了解决上述困境而被引入的。当一个驱动模块想要申请大块连续内存时,内存管理系统将CMA区域的内存进行迁移,空出连续内存给驱动使用。而当驱动模块释放时,它又被归还给操作系统管理,可以分配给其他使用者。
Expand Down
18 changes: 13 additions & 5 deletions docs/linux/kernel/debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,19 @@ $ cat /proc/sys/kernel/printk
### 调试函数

- dump_stack():打印当前调用栈
- BUG():触发panic,输出log
- BUG_ON(condition):触发panic,输出log
- WARN(condition, fmt...):当condition为真时,打印信息,不触发panic
- WARN_ON(condition):调用`dump_stack()`
- panic(fmt...):系统crash,输出log
- BUG():触发panic,输出 log
- BUG_ON(condition):如果条件为真,则触发 panic,输出 log
- WARN(condition, fmt...):如果条件为真,打印信息,不触发 panic
- WARN_ON(condition):调用`dump_stack()`
- panic(fmt...):系统 crash,输出 log

## 获取函数地址

在内核调试中,经常需要知道某个函数的地址,或者根据地址找到相应的函数。下面介绍几种方法,可以获取函数的地址信息。

1. system.map:在内核编译时,会生成一个 system.map 文件,也叫内核符号表,里面每一行都代表一个函数符号,包括地址、类型和名称。
2. vmlinux:编译内核时生成的原始内核镜像文件,可以通过`nm``objdump``readelf`等工具来查看符号表信息。
3. /proc/kallsyms:内核符号表信息,可以通过`cat /proc/kallsyms`命令查看。

## 动态打印

Expand Down
11 changes: 3 additions & 8 deletions docs/linux/kernel/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@

## 网络系统

- [网络系统](./network.md)
- [IO多路复用](./iomultiplexing.md)
- [异步IO](./io_uring.md)

## 时间系统

Expand All @@ -54,10 +55,4 @@

## shell脚本

- [shell脚本](./shell.md)






- [shell脚本](./shell.md)
17 changes: 17 additions & 0 deletions docs/linux/kernel/io_uring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# 异步IO

异步 IO 一直是 Linux 系统的痛。Linux 很早就有 POSIX AIO 这套异步 IO 实现,但它是在用户空间自己开用户线程模拟的,效率极其低下。后来在 Linux 2.6 引入了真正的内核级别支持的异步 IO 实现(Linux aio),但是它只支持 Direct IO,只支持磁盘文件读写,而且对文件大小还有限制,总之各种麻烦。

随着 Linux 5.1 的发布,Linux 终于有了自己好用的异步 IO 实现,并且支持大多数文件类型(磁盘文件、socket,管道等),这个就是本文的主角:io_uring。

相比于Linux传统的异步I/O机制,io_uring的优势主要体现在以下几个方面:

1. 高效:一方面,io_uring 采用了共享内存的方式来传递参数,减少了数据拷贝;另一方面,采用 ringbuffer 的方式来实现批量的 IO 请求,减少了系统调用的次数。
2. 可扩展性强,具体表现在:
- 支持的 IO 设备类型多样化,不仅支持块设备的 IO,还支持任何基于文件的 IO,例如管道、socket。
- 支持的 IO 操作多样化,不仅支持常见的 read/write 操作,还支持 send/recv/close/sync 等。
3. 易用:io_uring 提供了配套的 liburing 库,对底层的系统调用进行了大量的封装。
4. 可伸缩:io_uring 提供了 poll 模式,对于 IO 性能要求较高的场景,允许用户牺牲一定的 CPU 来获得更高的 IO 性能。


总结 io_uring :一套全新的 syscall,一套全新的 async API,更高的性能,更好的兼容性,来迎接高 IOPS,高吞吐量的未来。
File renamed without changes.
43 changes: 43 additions & 0 deletions docs/linux/kernel/load.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,46 @@
## execve系统调用

## 加载ELF文件

### ELF解析

![Linux ELF](../../images/kernel/elf.jpg)

ELF 文件是 Linux 系统上通用的可执行文件、共享库、核心转储文件格式。可以通过`file`命令查看 ELF 文件的信息:

```SHELL
$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=36b86f957a1be53733633d184c3a3354f3fc7b12, for GNU/Linux 3.2.0, stripped
```

`readelf`命令查看 ELF 文件的结构:

```SHELL
$ readelf -h /usr/bin/ls
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x6aa0
Start of program headers: 64 (bytes into file)
Start of section headers: 136232 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
```
- 魔数:前4个字节固定为`7f 45 4c 46`,表示这是一个 ELF 文件(45=E,4c=L,46=F)。
- 类别:在 ELF 文件之后,定义了一个类别字段,这个值决定了该文件是 32(=01) 位架构还是 64(=02) 位架构。
- 大小端:后面跟着的数据决定了文件是大端还是小端,01 表示小端,02 表示大端。
- 版本:接下来的 01 表示版本号。
2 changes: 1 addition & 1 deletion docs/linux/kernel/vma.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ struct vm_area_struct {

### ptmalloc概念

在 ptmalloc 中,是通过分配去、空闲链表、内存块等几个数据结构来管理内存的。
在 ptmalloc 中,是通过分配区、空闲链表、内存块等几个数据结构来管理内存的。

#### 分配区

Expand Down
22 changes: 22 additions & 0 deletions docs/pl/cpp/gdb.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,24 @@
# GDB

GDB 是强大的代码调试工具,编译时需要设置`-g`选项,使得编译器生成调试信息。可以直接使用 gdb a.out 来调试一个可执行文件,也可以通过 gdb attach pid 来将 GDB 附加到正在运行的程序上。

## 常用命令

GDB 的命令有很多,这里列出一些常用的,足以应付一般的调试任务:

- run:运行程序,直到遇到断点
- list:显示源代码
- break:设置断点
- next:单步执行(跳过函数)
- step:单步执行(进入函数)
- backtrace:显示函数调用栈
- set:设置变量的值
- frame:切换函数调用栈
- info:显示局部变量的值
- finish:结束当前函数
- until:退出循环体
- delete:删除断点
- continue:继续执行到下一个断点处或程序结束
- print:打印变量的值
- watch:监视某个变量
- quit:退出 GDB
Loading

0 comments on commit 09b5a19

Please sign in to comment.