| 目录                | 说明                                                |
| ------------------- | --------------------------------------------------- |
| /usr/include/linux/ | 从 Linux 内核源码生成，描述内核接口（系统调用等）   |
| /usr/include/asm/   | 和架构相关的定义（如 syscall 编号、CPU 寄存器布局） |
| /usr/include/sys/   | glibc 的封装头，用于标准 C 接口，对上层屏蔽差异     |

**/usr/include/linux/** 和 **/usr/include/asm/** 是你编译 Linux 内核后，通过 **make headers_install** 安装出来的
/usr/include/sys/ 是编译 glibc 时自动放进去的，不依赖内核。

由于glibc是源代码级，跨架构，跨平台的。又封装了系统调用，所以 **/usr/include/sys/** 下的文件是 **glibc构建过程中的脚本和模板** 时根据架构，平台生成的。
编译脚本判断完目标系统系统以后，比如 X86+LINUX，它会寻找OS对外暴露的系统调用头文件，比如'/usr/include/linux'，里面是C库如何调用本OS的系统调用的格式和指令，
然后编译脚本通过 **代码模板** 将这些系统调用封装好，基本上就是用宏将汇编指令封装成最低层的C函数，然后稍微上层一点的C函数，
比如read/write函数早就适配好要调用哪些封装C函数。 这些都是编译脚本自动生成，然后就可以编译了。
如果将glibc移植到一个新的平台，只要按照规则将一些脚本和模板编写好，后面都是由编译脚本自动完成。
这种约定已经很成熟了，基本上不需要我们操心。


Linux的内核系统调用接口除了几个独有的之外，大部分都兼容POSIX标准，而glibc将系统调用封装成用户空间函数接口，命名是一样的，glibc还实现了ISO C的标准库。

而Windows的系统调用通过ntdll.dll封装成Native API，然后再被kernel32.dll, user32.dll, gdi32.dll, ws2_32.dll之类的封装成常见的Win32API，
内核接口和用户空间接口命名不一样，而ISO C的标准库则是通过msvcrt.dll, msvcr*.dll, ucrtbase.dll之类的实现，
所以glibc和Windows的 API本质都是用户空间API而不是系统调用，是逻辑层次上基本等价的东西，只是要注意C标准库实现的所在位置。
参考：
https://en.wikipedia.org/wiki/Microsoft_Windows_library_files


系统调用是：用户态程序 → 内核

系统调用本身在内核中是“汇编 + C”实现的

glibc是c标准库的一个实现。
