內核下載地址
https://www.kernel.org/
官網鏈接:
HTTP https://www.kernel.org/pub/
GIT https://git.kernel.org/
官網下載經常速度太慢,無法下載,提供另一個鏈接:
http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/
以下來自:
https://www.cnblogs.com/tsruixi/p/10777242.html
實驗一:Linux內核編譯及添加系統調用(HDU)
花了一上午的時間來寫這個,良心制作,發現自己剛學的時候沒有找到很詳細的,就是泛泛的說了下細節地方也沒有,於是自己寫了這個,有點長,如果你認真的看完了,也應該是懂了。
一、前期准備工作
- 需要准備虛擬機上安裝Ubuntu,筆者安裝的是Ubuntu18.04,安裝的教程自行百度解決,教程很多。有幾點需要提一下,就是內存分配至少60G,核分配4個最好,為了在編譯的時候別崩潰。
建議去熟悉一下Linux下面的文件目錄結構,根目錄下每個目錄一般會存放什么樣的文件
- ,然后常見命令操作也要熟悉一下。
- 下載Linux內核地址,自行選擇版本,建議選擇4.xx版本,因為版本高出錯的概率也大。
下載好了之后,會放在自己的Ubuntu中的Downloads目錄下,同時是一個壓縮文件,到時候需要解壓到放內核目錄文件下。首先進入到該Downloads文件目錄下,查看是否下載好了。
- 下載Linux內核地址,自行選擇版本,建議選擇4.xx版本,因為版本高出錯的概率也大。
下載好了之后,會放在自己的Ubuntu中的Downloads目錄下,同時是一個壓縮文件,到時候需要解壓到放內核目錄文件下。首先進入到該Downloads文件目錄下,查看是否下載好了。
$cd ~/Downloads $ls linux-4.19.25.tar.xz
之后開始解壓上面的那個壓縮文件到存放內核的地方,就是Linux系統的/usr/src目錄下,此目錄用來存放內核源碼的。從上圖也可以了解到。
cd ~/Downloads
tar xvJf linux-4.19.25.tar.xz -C /usr/src
進入/usr/src目錄查看是否有,如果有就可以開始后續工作了。
二、實驗要求和內容
1. 內容要求:
(1)添加一個系統調用,實現對指定進程的nice值的修改或讀取功能,並返回進程最新的nice值及優先級。建議調用原型是int mysetniec(pid_t pid, int flag, int nicevalue, void_user* prio, void_user* nice);
參數含義:
pid:進程ID
flag:若為0,則表示讀取nice的值;若為1,則表示修改nice的值。
nicevalue:為指定的進程設置新的nice。
prio,nice:指向進程的優先級和nice值。
返回值:系統調用成功時返回0;失敗時返回錯誤碼EFAULT。
(2)寫一個簡單的應用程序測試(1)中添加的系統調用。
(3)若系統調用了Linux的內核函數,要求深入閱讀相關的源碼。
2. Linux系統調用的基本概念
實質是指調用內核函數,於內核態中運行,Linux中的用戶通過執行一條訪管指令“int $0x80”來調用系統調用,該指令會產生一個訪管中斷,從而讓系統暫停當前的進程執行,而轉去執行系統調用處理程序。通過用戶態傳入的系統調用號從系統調用表中找到相應的服務例程的入口並執行,完成后返回。
(1)系統調用號與系統調用表:Linux內核中設置了一張系統調用表,用於關聯系統調用號及其相對應的服務例程入口地址,定義在./arch/x86/entry/syscalls/syscall_64.tbl文件中,每個系統調用占一個表項,一旦分配好就不可以有任何變更。
(2)系統調用服務例程:每個系統調用都對應一個內核服務例程來實現系統調用的功能,其命名的格式都是以"sys_開頭。其代碼通常放在./kernel/sys.c中,服務例程的原型聲明則是放在./include/linux/syscall.h中。如sys_open,通常格式是asmlinkage long sys_open(int flag......)。其中的amslinkage是一個必需的限定詞,用於通知編譯器從堆棧中提取函數的參數,而不是從寄存器中。
在sys.c中編程時,格式是SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
N=5代表參數的個數。
(3)系統調用參數傳遞:在X86中,Linux通過6個寄存器來傳入參數,其中一個eax是傳遞系統調用號,后面的5個傳遞參數。
(4)系統調用參數驗證
三、開始實驗
1. 切換到root權限下,防止權限不夠,導致出錯。
$ sudo passwd root [sudo] password for leslie: Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully $ su root Password:
(1)首先,你安裝Linux系統時,它會讓你設置一個你的用戶名和用戶密碼,在這里我設置的用戶名是leslie,即綠色字體leslie@tp50的前半部分,后半部分tp50是我的主機名。
sudo放在命令首,意思是當前指令以管理員權限運行。
(2)passwd是一條命令,用來修改用戶密碼,參數root是超級用戶名,擁有系統最高的權限。passwd root的意思是修改超級用戶的密碼,在創建Ubuntu時,默認超級用戶是沒有密碼的(也可能是一個隨機數之類的我不記得了),用這條命令重新設定一個密碼。
(3)su是一條命令,用來切換當前用戶,在第一章你會認識到,Linux是一個多用戶多任務的操作系統。參數root是用戶名,指示切換到的用戶,在這里su root意為切換到root用戶,當參數缺省時,默認切換到超級用戶。
(4)你會發現,它在提示輸入密碼時,雖然鍵盤已經輸入了密碼,但是終端沒有任何響應,不要擔心,這正是Unix和Linux的特點,為了確保安全,在輸入密碼時不顯示輸入的內容,在輸入密碼后,直接按下回車就好了。
2. 分配系統調用號,修改系統調用表
(1)查看系統調用表,並修改
gedit /usr/src/linux-4.19.25/arch/x86/entry/syscalls/syscall_64.tbl
你只需要將linux-4.19.25換成你自己下載好的版本即可。
你會看見這個格式
應用二進制接口分為三種:64、x32和common,即三種不同的調用約定,這里不需考慮太多,三種任意選擇一種即可,按照上述格式編寫新的系統調用表表項如下:
335 64 first_compile __x64_sys_first_compile
編譯的時候發現錯誤,無法找到,
修改成 sys_first_compile 再測試
實際為:
(2)聲明系統調用服務例程
查看系統調用頭文件
$cd /usr/src/linux-4.19.34(換成自己的版本即可)/kernel
vim sys.c
函數說明:
這一步與上一步的關系,就是C語言中頭文件與實現文件的關系,上一步我們對函數進行了聲明,這里給函數一個具體的實現。
首先要明確,我們要實現一個什么樣的功能,根據內容要求可知,這個系統調用需要具備對指定進程的nice值的修改及讀取的功能,同時返回進程最新的nice值及優先級prio。
把功能分拆成一個一個小塊,我們需要做到的有以下幾點:
根據進程號pid找到相應的進程控制塊PCB(因為進程控制塊中記錄了用於描述進程情況及控制進程運行所需要的全部信息,nice值和優先級正是其中的一部分);
根據PCB讀取它的nice值和優先級prio;
根據PCB對相應進程的nice值進行修改;
將得到的nice值和優先級prio進行返回。
SYSCALL_DEFINE5(first_compile, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
{
int cur_prio, cur_nice;
struct pid *ppid;
struct task_struct *pcb;
ppid = find_get_pid(pid);
pcb = pid_task(ppid, PIDTYPE_PID);
if (flag == 1)
{
set_user_nice(pcb, nicevalue);
}
else if (flag != 0)
{
return EFAULT;
}
cur_prio = task_prio(pcb);
cur_nice = task_nice(pcb);
copy_to_user(prio, &cur_prio, sizeof(cur_prio));
copy_to_user(nice, &cur_nice, sizeof(cur_nice));
return 0;
}
(4)開始編譯內核
首先,用下面這條命令查漏補缺,很有用處,用來它,我編譯是一次通過的,沒有遇見什么其他麻煩。
sudo apt-get install libncurses5-dev make openssl libssl-dev bison flex
make menuconfig
sudo make -j4 2> error.log
-j4表示使用四線程進行編譯,這個過程大概持續一個小時,后面的重定向將錯誤信息輸出到了error.log這個文件里面,方便我們之后進行錯誤排查,不至於一兩個小時坐在電腦面前盯着信息輸出生怕出現一個錯誤而自己錯過了,之后修改只能靠兩眼排查,相信我,那不是一種好的體驗。
開始等待吧,結束后就可以安裝內核了
(5)安裝內核
此時還是在你原來的目錄路徑下
安裝模塊:
sudo make modules_install
使用這一行命令進行模塊的安裝,模塊的安裝持續時間大概在十幾分鍾左右,視你分配的資源多寡這個時間會適當地增加或減少。
結束后
安裝內核:
sudo make install
test.c
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#define _SYSCALL_MYSETNICE_ 335
#define EFALUT 14
int main()
{
int pid, flag, nicevalue;
int prev_prio, prev_nice, cur_prio, cur_nice;
int result;
printf("Please input variable(pid, flag, nicevalue): ");
scanf("%d%d%d", &pid, &flag, &nicevalue);
result = syscall(_SYSCALL_MYSETNICE_, pid, 0, nicevalue, &prev_prio,
&prev_nice);
if (result == EFALUT)
{
printf("ERROR!");
return 1;
}
if (flag == 1)
{
syscall(_SYSCALL_MYSETNICE_, pid, 1, nicevalue, &cur_prio, &cur_nice);
printf("Original priority is: [%d], original nice is [%d]\n", prev_prio,
prev_nice);
printf("Current priority is : [%d], current nice is [%d]\n", cur_prio,
cur_nice);
}
else if (flag == 0)
{
printf("Current priority is : [%d], current nice is [%d]\n", prev_prio,
prev_nice);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
下載歷史版本:
https://juejin.cn/post/6844903940023140360
打開官方下載鏈接 The Linux Kernel Archives 如下圖所示:
點擊打開 HTTP 的鏈接,比如這里我要下載 4.4.192 的版本,那么依次點擊 linux->kernel->v4.x 如下圖所示:
要下載的包就在這個界面,但是這個界面有點長,剛開始我以為沒有。得繼續往下一直拉就可以找到了,如下圖:
ubuntu 內核版本下載:
不是標准的linux kernel
$ sudo apt-get install git $ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-$(lsb_release --codename | cut -f2).git
4.4.0-116-generic
來自:
https://www.ktanx.com/blog/p/1126
在Debian上安裝完整的內核源碼
在下載內核源碼之前,先安裝dpkg-dev,其中包含你在Debian上生成源代碼時需要的開發工具套件。不僅如此,dpkg-dev中還包含在用來解壓Debian源碼包並自動打補丁的工具dpgk-source。
$ sudo apt-get install dpkg-dev
然后,運行以下命令下載完整的內核源碼。
$ apt-get source linux-image-$(uname -r)
伴隨着完整內核源碼(linux_X.X.XX.orig.tar.xz)的還有一些可用的內核補丁(linux_X.X.X+XXX.debian.tar.xz)和源碼控制文件(linux_XXXX.dsc),這些都將被下載並存儲到當前目錄。在.dsc文件中會指出如何給內核源碼打補丁。
當下載完成,以上的命令將會自動調用工具dpkg-source將下載的內核源碼解壓到當前的目錄中,與此同時根據.dsc文件來下補丁。
最終完整的內核源碼樹將會以”linux-X.X.XX”的形式呈現在當前目錄中。
在Ubuntu上安裝完整內核源碼
如果你想安裝完整內核源碼的話,以上在Debian上的那一套做法在Ubuntu上仍然奏效。
在Ubuntu上還有另一套方法安裝完整內核源碼。事實上,你可以查一下由Canonical為Ubuntu不同發行版維護的內核源碼樹。
$ sudo apt-get install git $ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-$(lsb_release --codename | cut -f2).git
舉個例子,如果你使用的是Ubuntu 14.04,以上的命令將會查看Git的”ubuntu-trusty”倉庫中的代碼。
一旦在你對Git倉庫的查詢結束后,使用以下的命令來安裝用來訪問生成內核源碼樹所需依賴的重要開發包。
$ sudo apt-get build-dep linux-image-$(uname -r)
參考:
https://www.cnblogs.com/tsruixi/p/10777242.html
https://richardweiyang-2.gitbook.io/kernel-exploring/00_index/01_build_your_first_kernel