為什麼安裝好一個Linux操作系統後,想要寫個新的系統調用,還需要下載Linux內核,Linux內核不在安裝好的操作系統中嗎?操作系統沒有內核的話,是怎樣服務其他的應用程序的?


編譯好的Linux內核在文件系統中,比如說我的Ubuntu上就存在/boot/vmlinuz-5.3.0-23-generic,這個文件在開機時就由GRUB給載入到內存中去執行(其實是個自解壓文件,可以提升載入速度)。

不知道你說的「新的系統調用」是什麼意思,是想改內核新加一個系統調用,還是使用一個系統調用。改內核的話肯定要下載了:編譯好的內核是二進位文件,代碼得額外去下載。使用的話則不一樣。

回顧一下系統調用的執行過程:對x86_64,程序在用戶態使用syscall指令, rax裡面放系統調用號。這個過程一般被庫給包裝過,用戶程序使用庫函數即可。Linux上最常用的庫是glibc,也稱libc。這樣,對用戶而言,系統調用根調用別的函數一般沒有區別。

這樣,使用系統調用的話,需要有系統的C庫和有關頭文件。比如這個使用write系統調用的程序write.c

#include &
char* buf = "Hello world!
";
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!
"
.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!

參考資料:

Say hello to x86_64 Assembly [part 1] · Just a memo?

0xax.github.io圖標X86 Assembly: Interfacing with Linux?

en.wikibooks.org


瀉藥。下載的不是linux內核而是linux內核「頭文件」。頭文件只是方便引入幾個符號提供給你作為調用入口的。你真想拋棄這些頭文件的話自己用彙編把系統調用號放在EAX中調用syscall指令也是可以的。


你問得很混亂。按你的問法,我猜你想問的是為什麼使用系統(而不是增加系統調用)調用需要下載內核的開發包?

首先你裝完linux啟動起來以後,內核就肯定已經有了。簡要信息可以uname -a查看。一般會放在 /boot 目錄下。但是這只是安裝了運行時。你想要使用系統調用的話,有哪些系統調用,參數是啥意思,地址在哪。通通沒有一個簡明扼要的方式知道。那麼下載開發包差不多就這意思,用一種人類比較好懂得告訴你。

當然你閑的蛋疼也可以去查文檔查表,寫彙編去調用。其他答案裏寫了我就不寫具體方法了。


誰跟你說安裝好的linux操作系統沒內核的?沒內核系統能跑起來?建議好好看看操作系統基礎。

你寫新的系統調用是需要的新的內核版本吧?那就改裝符合內核版本要求的發行版或者升級內核到需要的新內核版本。


大多數發行版都會在安裝時提供編譯好的內核和內核源碼,gentoo系的發行版需要手動配置和編譯內核。但無論是哪一種,在安裝過程中,你實際上在用安裝環境上的內核。

編譯好的內核會被安裝到/boot目錄下。

按慣例當前的內核源碼在/usr/src中,這應該是你想找的東西。這個目錄下可能會有多個版本的內核,一般會有個符號鏈接叫做linux,他指向默認使用的內核源碼。要自己加系統調用就得改這個然後重新編譯安裝。


操作系統必須有內核才能運行,內核是os的核心。沒有kernel系統就不能run。


我猜你是說,編譯在Ubuntu上運行的模塊為什麼需要下載發行版內核源碼吧。目前編譯內核模塊是需要引用當時編譯內核的編譯目錄的,這是因為需要知道配置和符號信息。


寫個新的系統調用?

你這是要改內核, 當然要改源代碼重新編譯, 難不成你直接改二進位? 你都開始 hack kernel 了問什麼基礎問題呢?


事實上現在發行版安裝以後就已經自帶發行版的內核,當然你也可以自己下載開源內核按照你的需求修改後用修改的內核啟動。


推薦閱讀:
相關文章