为什么Linux使用系统调用还需要下载内核?
知乎问题:Linux内核为什么不在安装好的操作系统中,而需要安装好系统后再下载?
编译好的Linux内核就存在文件系统中。比如说我的Ubuntu上就存在/boot/vmlinuz-5.3.0-23-generic
,这个文件在开机时就由GRUB给加载到内存中去执行(其实是个自解压文件,可以提升加载速度)。
不知道你说的“新的系统调用”是什么意思,是想改内核新加一个系统调用,还是使用一个系统调用。改内核的话肯定要下载了:编译好的内核是二进制文件,代码得额外去下载。使用的话则不一样。
回顾一下系统调用的执行过程:对x86_64
,程序在用户态使用syscall
指令,rax
里面放系统调用号。这个过程一般被库给包装过,用户程序使用库函数即可。Linux上最常用的库是glibc
,也称libc
。这样,对用户而言,系统调用跟调用别的函数一般没有区别。
这样,使用系统调用的话,需要有系统的C库和有关头文件。比如这个使用write
系统调用的程序write.c
:
#include <unistd.h>
char* buf = "Hello world!\n";
int main() {
write(1, buf, 13); // 去/usr/include/x86_64-linux-gnu/asm/unistd_64.h里面找
return 0;
}
编译后运行:
$ gcc write.c -o write
$ ./write
Hello world!
unistd.h
在/usr/include/unistd.h
,是许多系统调用和glibc
函数的头文件。编译时要和/lib/x86_64-linux-gnu/libc.so.6
链接,write
的实现就在里面。 libc.so
库是几乎百分之百的程序都要用的,几乎所有的非嵌入式系统都有。不过这个/usr/include/unistd.h
可不一定系统都有。看看是哪个包的:
$ dpkg -S /usr/include/unistd.h
libc6-dev:amd64: /usr/include/unistd.h
看看这个包的信息(删去了几行):
$ apt --info libc6-dev
Package: libc6-dev
Version: 2.30-0ubuntu2
Priority: optional
Build-Essential: yes
Provides: libc-dev
Depends: libc6 (= 2.30-0ubuntu2), libc-dev-bin (= 2.30-0ubuntu2), linux-libc-dev
APT-Manual-Installed: no
Description: GNU C Library: Development Libraries and Header Files
Contains the symlinks, headers, and object files needed to compile
and link programs which use the standard C library.
Priority: optional,不一定非要有哦。
总结一下,使用系统调用不光需要内核、glibc
,还需要头文件。头文件可能系统没自带,需要下载。不过我还没遇到过需要额外下载的情况,不知道是不是Ubuntu默认装了。
PS:如果你善于汇编,那手动调用syscall当然可以。刚才的例子重写:
.section .data
msg .ascii "Hello world!\n"
.section .text
.global _start
_start:
movq $1, %rax ; write 系统调用;
movq $1, %rdi ; 1是stdout。
movq $msg, %rsi ; 输出msg
movq $13, %rdx ; 13个字符
syscall
movq $60, %rax ; 使用 _exit syscall。
movq $0, %rdi ; 返回值 0
syscall ;
汇编:
$ as -mmnemonic=intel hello.s -o hello.o
$ ld hello.o -o hello
$./hello
Hello world!
参考资料: