跟蹤分析Linux內核5.0系統調用處理過程
阿新 • • 發佈:2019-03-20
bubuko 內存空間 轉換 ase 運行 ubuntu fig 1.0 bss
---
學號尾號:155
基於ubuntu kylin 18.10虛擬機
原創作品轉載請註明出處https://github.com/mengning/linuxkernel/
實驗準備
下載和編譯內核
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.tar.xz # 下載內核
# 解壓文件
xz -d linux-5.0.1.tar.xz
tar -xvf linux-5.0.tar.xz
cd linux-5.0
# 編譯內核
make i386_defconfig
此處出現報錯:
執行以下命令
apt-get install flex
再次執行
make i386_defconfig
出現報錯
執行以下命令
apt-get install bison
再次執行
make i386_defconfig
make
出現報錯
執行以下命令
apt-get install libssl-dev
再次執行
make
等待一段時間後,控制臺會輸出如下信息,表示編譯完成
制作根文件系統
cd ..
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
此處出現問題:
apt install gcc-multilib gcc -pthread -o init linktable.c menu.c test.c -m32 -static
再次出現問題
apt-get install gcc-4.8 gcc-4.8-multilib g++-4.8 g++-4.8-multilib
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
成功了
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
制作成功!
啟動MenuOS
cd ..
qemu -kernel linux-5.0/arch/x86/boot/bzImage -initrd rootfs.img
啟動成功!
---
跟蹤系統調用
我的學號尾號是155,在查閱系統調用表後,發現155號系統調用是
#define __NR_sched_getparam 155
函數的原型是
#include <sched.h>
//該函數用於根據進程號獲取進程的調度參數,pid用於指定要獲取調度參數的進程號,為0時表示獲取當前進程的調度參數
//param用於存儲獲得的進程調度參數
//返回0時表示成功獲得進程的調度參數,返回-1時表示出錯,並設置errno
//errno有兩種,EPERM:調用進程沒有足夠的權限來獲取調度參數。ESRCH:進程pid不存在。
int sched_getparam(pid_t pid,struct sched_param * param);
struct sched_param
{
int32_t sched_priority;//獲取調度參數時,此成員將反映分配給線程或進程的優先級
int32_t sched_curpriority;//獲取調度參數時,此成員將設置為線程或進程當前運行的優先級。這是內核在進行調度決策時使用的值。
union
{
int32_t reserved[8];
struct
{
int32_t __ss_low_priority;
int32_t __ss_max_repl;
struct timespec __ss_repl_period;
struct timespec __ss_init_budget;
} __ss;
} __ss_un;
}
#define sched_ss_low_priority __ss_un.__ss.__ss_low_priority
#define sched_ss_max_repl __ss_un.__ss.__ss_max_repl
#define sched_ss_repl_period __ss_un.__ss.__ss_repl_period
#define sched_ss_init_budget __ss_un.__ss.__ss_init_budget
對於該系統調用,我們可以寫出如下代碼對其進行測試
//在menu文件夾中的test.c文件中加入如下代碼
#include <sched.h>
int test_get_param()
{
struct sched_param param;
sched_getparam(0,¶m);
printf("The original priority of the process is %d\n",param.sched_priority);
}
int main()
{
PrintMenuOS();
SetPrompt("MenuOS>>");
MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
MenuConfig("quit","Quit from MenuOS",Quit);
MenuConfig("time","Show System Time",Time);
MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
MenuConfig("get_param","根據進程號獲取進程的優先級",test_get_param);
ExecuteMenu();
}
重新制作根文件系統
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
使用gdb跟蹤調試內核
cd ..
qemu -kernel linux-5.0/arch/x86/boot/bzImage -initrd rootfs.img -S -s -append nokaslr
此時啟動的qemu窗口是stopped的狀態
另開一個shell窗口
gdb
file vmlinux # target remote之前加載符號表
target remote:1234 # 建立gdb和gdbserver之間的連接,按c讓qemu上的Linux系統繼續運行
b sys_sched_getparam # 打上斷點
在gdb窗口中輸入
c
在qemu窗口中輸入
get_param
在gdb窗口中輸入
c
系統調用分析
可以看到,sched_getparam系統調用的流程如下:
- 用戶調用sched_getparam接口
- 將系統調用號155放入eax寄存器
- 執行int $0x80指令產生一個向量為128的編程異常,進入內核態
- 保護現場
- 根據系統調用號,查找系統調用表,找到中斷處理程序的地址並執行中斷處理程序
- 恢復現場,進入用戶態
由此可以看出,用戶態進程是無法訪問內核的內存空間的,只有內核態進程才能訪問內核。因此當執行系統調用時,必須要先將進程轉換成內核態才能執行系統調用,執行完畢後再恢復到用戶態。
跟蹤分析Linux內核5.0系統調用處理過程