结论速览

  • 典型调用链是应用程序、libc/POSIX API、syscall、Linux Kernel,write() 由 libc 提供用户态包装后进入内核。
  • 文件、网络、进程、内存、设备控制都有对应的常见接口:open/read/write、socket/connect、fork/execve、mmap、ioctl。
  • strlen、strcmp、memcpy 完全在用户空间完成,不进内核;C 标准库函数和 Linux 系统调用不是一回事。
  • 头文件只提供函数声明、结构体、宏、常量和类型,真正功能由 libc 和 Kernel 共同完成。
  • Linux 的接口不只是 syscall:/dev、/proc、/sys 里的文件同样是访问内核的接口。

1. 用户程序如何使用 Kernel

典型调用链:

1
2
3
4
5
6
7
应用程序
↓
libc / POSIX API
↓
syscall
↓
Linux Kernel

例如:

1
write(fd, buf, len);

通常由 libc 提供用户态包装,然后进入内核。

2. 常见接口

文件:

1
2
3
4
open()
read()
write()
close()

网络:

1
2
3
4
socket()
connect()
send()
recv()

进程:

1
2
3
fork()
execve()
wait()

内存:

1
mmap()

设备控制:

1
ioctl()

3. 不是所有 libc 函数都会进入 Kernel

例如:

1
2
3
strlen()
strcmp()
memcpy()

通常完全在用户空间完成。

而:

1
2
3
read()
write()
socket()

需要 Kernel 提供对应系统调用。

因此:

1
C 标准库函数

和:

1
Linux 系统调用

不是一回事。

4. 头文件告诉你 API 怎么使用

例如 socket 程序:

1
2
3
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

头文件提供:

1
2
3
4
5
函数声明
结构体
宏
常量
类型

但真正的功能由 libc 和 Kernel 共同完成。

5. 怎么查接口文档

Linux 上常用:

1
2
3
4
man 2 socket
man 2 open
man 2 read
man 3 getaddrinfo

其中:

1
2
3
4
5
man 2
= 系统调用

man 3
= 库函数

6. /dev、/proc、/sys 也是接口

Linux 并不只有 syscall。

用户空间还经常通过:

1
2
3
/dev/*
/proc/*
/sys/*

访问内核。

例如:

1
/dev/ttyS0

代表串口设备接口。

1
/proc/cpuinfo

暴露 CPU 信息。

1
/sys/class/net/

暴露网络设备对象。

所以 Linux 应用看到的「接口」可能是:

1
2
3
4
5
6
函数
文件描述符
设备节点
虚拟文件
socket
ioctl