Interacting with Linux Kernel Through System Calls

什么是 Linux 内核?

Linux 内核可以理解为:运行在硬件和应用程序之间的“资源管理与安全控制层”。
应用程序不能直接操作磁盘、网卡或内存,而是通过系统调用请求内核完成:

1
2
3
4
5
应用程序
↓ 系统调用
Linux 内核
↓ 驱动程序
硬件

内核主要负责:

  • 进程调度:决定哪个程序使用 CPU
  • 内存管理:虚拟内存、页表、缓存、回收
  • 文件系统:目录、文件、权限、挂载
  • 设备管理:磁盘、网卡、USB、GPU 等驱动
  • 网络协议栈
  • 安全隔离和权限控制
  • 多核并发、中断、锁和同步

存储请求如何经过 Linux 内核?

以应用执行 write(fd, buf, 4096) 为例,大致路径是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
应用程序
↓ write 系统调用
系统调用层

VFS

具体文件系统:ext4 / XFS

页缓存、写回机制

块层:bio / request

设备映射:LVM / dm-crypt / RAID

磁盘驱动:NVMe / SCSI / SATA

硬件设备

用户态如何进入内核?

用户态进入内核可以通过以下系统调用:

  • open()
  • read()
  • write()
  • fsync()
  • ioctl()
  • mmap()
  • stat()

常用工具:

1
2
3
4
strace -e trace=file,read,write cat file.txt
lsof /data/file.txt
stat file.txt
sync

Example:

1
2
strace -T -e openat,read,write,fsync \
dd if=/bin/bash of=/dev/null bs=1M count=10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
root@ubuntu:/home/fengzetao/data# strace -T -e openat,read,write,fsync   dd if=/bin/bash of=/dev/null bs=1M count=10
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000006>
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000004>
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\360u\2\0\0\0\0\0"..., 832) = 832 <0.000004>
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 <0.000008>
openat(AT_FDCWD, "/bin/bash", O_RDONLY) = 3 <0.000206>
openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 <0.000090>
read(0, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\0E\3\0\0\0\0\0"..., 1048576) = 1048576 <0.001258>
write(1, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\0E\3\0\0\0\0\0"..., 1048576) = 1048576 <0.000005>
read(0, "\26\0\200\322@\2\0004\23\0\200\322\364\0\0004\240zs\370s\6\0\221@\0\0\264\345\310\374\227"..., 1048576) = 350840 <0.000088>
write(1, "\26\0\200\322@\2\0004\23\0\200\322\364\0\0004\240zs\370s\6\0\221@\0\0\264\345\310\374\227"..., 350840) = 350840 <0.000007>
read(0, "", 1048576) = 0 <0.000003>
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 0 <0.000263>
read(0, "# Locale name alias data base.\n#"..., 4096) = 2996 <0.000037>
read(0, "", 4096) = 0 <0.000007>
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000031>
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000005>
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000004>
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000003>
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000041>
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000022>
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000003>
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000005>
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000008>
openat(AT_FDCWD, "/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000003>
openat(AT_FDCWD, "/usr/share/locale-langpack/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000002>
openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = 0 <0.000022>
write(2, "1+1 records in\n1+1 records out\n", 311+1 records in
1+1 records out
) = 31 <0.000003>
write(2, "1399416 bytes (1.4 MB, 1.3 MiB) "..., 621399416 bytes (1.4 MB, 1.3 MiB) copied, 0.00287576 s, 487 MB/s) = 62 <0.000003>
write(2, "\n", 1
) = 1 <0.000002>
+++ exited with 0 +++

本文作者:jujimeizuo
本文地址https://blog.jujimeizuo.cn/2026/09/18/Interacting-with-Linux-Kernel-Through-System-Calls/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!