之所以會想寫這篇網誌是因為原本在Linux系統中新增系統呼叫是自己課程上的一份作業,但是當時自己其實在新增系統呼叫時用了很久,看了很多文件,所以希望說寫了這個以後能幫助比較多人比較快地了解到新增system call的流程
其實我在新增system call的過程中有看了網路上很多東西,但是我覺得幫助最大的是以下兩份文件,而我接下來網誌的內容與其說是改寫這兩份文件,倒不如說是整理這兩份文件而成的,如果這兩份文件的原作者認為我的內容有所不妥,我會馬上將自己的網誌屏蔽
第一份文件就是標準的在Linux系統中增加system call,但是沒有包含編譯kernel的部分,不過寫得已經很詳盡了,我雖然不知道這個作者是誰,但是真的很感謝他,因為我是大部分以此份文件為參考才順利地新增system call
在linux上新增一個system call ---kernel 2.6.28.5
連結網址:oss.csie.fju.edu.tw/note/C/HowToAddSystemCall.doc
而接下來在編譯核心的部分基本上完全都是參考鳥哥的私房菜其中在編譯核心的部分,在這裡也非常感謝鳥哥,我覺得鳥哥把linux系統做了非常完整的簡介,造福了無數的莘莘學子,讓我們在碰Linux系統時真的可以省去很多自學的麻煩
接下來就可以算是正題了,以下是我所用的虛擬機器、作業系統和核心版本
虛擬機器:VMware player
下載網址:
https://my.vmware.com/web/vmware/free#desktop_end_user_computing/vmware_player/5_0
作業系統:Ubuntu-9.04
Ubuntu舊版本下載區:http://old-releases.ubuntu.com/releases/
核心版本:linux-2.6.28.5
國家高速網路中心:ftp://ftp.twaren.net/pub/Unix/Kernel/linux/kernel/
而之所以會用這麼舊的作業系統和核心版本的原因是我在網路上找的介紹文件幾乎都是使用linux2.6.XX.X,所以為了不必要的麻煩所以當時我就直接使用跟第一份文件相同的核心版本
(一)前置處理
一開始可以先使用sudo su指令並輸入密碼取得超級權限,取得root的超級權限後對於很多設定方面會很方便
另一個技巧是chmod,也就是所謂改變權限的意思,因為某些文件可能權限不夠無法進行修改,所以可以在terminal下指令 chmod 777 檔案或文件 ,這樣來給文件極高的權限來用於讀寫修改,像若想改變system call table的權限其實我可以寫成:chmod 777 syscall_table_32.S
那這三個數字分別代表什麼意思,分別是user、group、other的權限,而要理解數字的意思得要先了解r、w、x所代表的意義,r代表可以讀取,數值是4,w代表可以寫入,數值是2,而x是代表可執行的意思,數值是1,所以說若權限是可以讀取、改寫並執行的話就要給r+w+x=4+2+1=7,若只要讀取和改寫就是給4+2=6的權限,當然其實想給多少權限可以好好思考,直接用777的權限其實算是比較不經思考的方法
另外還須記得把新下載的kernel放入source code中,原本存在作業系統中的kernel是沒有system call table,所以我們得要新加入別的kernel來修改system call table,那至於為什原本的kernel不給使用者增加system call,這點其實我也不是很清楚,但是我有聽到一個說法是Linux作業系統不是每個人都需要比較進階的功能,所以會拿掉一些不常用的地方
路徑位置:/usr/src/
把自己下載的kernel放進去
(二)Kernel設定
1.設定system call table
路徑位置:/usr/src/linux-2.6.28.5/arch/x86/kernel/syscall_table_32.S
核心中有個紀錄system call table的表,我們需要先至這個地方新增我們所要的系統呼叫,就如下圖所示增加了一個system call名為mycall,在這之中.long是一定要加的,因為這是屬於Linux組合語言的一個語法,後面的數字是代表system call number
2. 增加system call的定義
路徑位置:/usr/src/linux-2.6.28.5/arch/x86/include/asm/unistd_32.h
在unistd_32.h這個檔案中,增加system call number,也就是增加#define __NR_mycall,並定義為第333個system call number,增加完敘述後再順便增加#define NR_syscalls 334,這一行敘述,讓system call number提供上下界
3.定義system call的函式原型
路徑位置:/usr/src/linux-2.6.28.5/arch/x86/include/asm/syscalls.h
新增asmlinkage int sys_mycall(void);的函式原型
4.新增system call的主程式碼
路徑位置:/usr/src/linux-2.6.28.5/kernel/
這邊的目的就是撰寫新增的system call的程式碼,注意新增的程式碼檔名得要跟system call的名稱一樣,像在這邊就得要新增一個名為mycall.c的檔案,否則則系統無法找到正確的 system call 對應
5.Makefile的設定
路徑位置:/usr/src/linux-2.6.28.5/kernel/Makefile
在obj-y後面新增自己新增要編譯的檔,變數 obj-y 表示需要編繹到內核中的目標檔案名集合,如下範例新增mycall.o
到這邊Makefile設定完之後,在kernel的設定就差不多了,但是更改完後的核心還得要經過編譯才能使用
(三)核心編譯
1.刪除中間檔案
第一次編譯時才使用,會刪除之前核心功能的選擇檔案
後來的編譯就make clean來刪除掉編譯過程中的中間檔案
2.挑選核心功能並製作出config-XXX檔案
這個動作的最主要目的就是自己設定出自己的核心要有那些功能,並在設定完之後製作出config-XXX檔案,那這個config-XXX檔案其實就是核心功能列表檔
在製作出config-XXX檔案之前,得要先去下載ncurses的檔案(Ubuntu的作業系統要,其他的Linux衍生的作業系統不知道需不需要),一般來講可以直接使用apt-get install libncurses-dev指令獲取正確的ncurses
但是由於我使用的ubuntu作業系統比較舊,然後聽我這堂課助教的說法是,較舊的作業系統連到伺服器會有些問題,所以要更改什麼伺服器的位置然後才可以再使用apt-get install libncurses-dev,但這部分我就真的設定感覺很麻煩,所以就直接用手動下載的就好了
下載網址:http://ftp.gnu.org/pub/gnu/ncurses/
這邊我是使用5.7版的,但是沒測試過比較新版的ncurses可不可以使用
下以下的指令
./configure --without-cxx-binding(如果直接下./config指令會產生錯誤)
make
make install
安裝完後就可以來製作config檔案,鳥哥的網頁是有寫四種製作的方式,但是鳥哥是直接使用menuconfig的方式,我當然也就依樣畫葫蘆,此外其實這部分的挑選核心功能的選項是可以設定非常多的,但是我都沒選直接exit後儲存設定,畢竟這邊只是要新增一個system call而已,不用用到其他太多kernel的設定功能,不過若真的要設定其他的功能的話,建議還是去鳥哥的網頁來瀏覽完整的設定方式
下menuconfig的指令
跳出的設定畫面
3.編譯核心與模組
編譯核心(這部分可能會花一些時間)
編譯成功出現的訊息
編譯模組(這部份得要花費最久的時間)
編譯完後進行模組安裝
4.移動編譯玩的核心檔案
編譯完成的核心檔案,放在/usr/src/linux-2.6.28.5/arch/x86/boot/bzImage,但其實原始核心檔案都是放在/boot底下,所以其實可以把這個檔案放至boot底下後製作成多核心的檔案,其實我是不知道若是核心檔案不放在/boot底下會不會發生什麼事,因為最後在編輯開機選單時我們是用直接指定位置的方式來開啟核心的相關檔案,感覺乍看之下若核心相關檔案不放在/boot底下應該不會有什麼事,但是若都放在/boot底下其實有一個好處是方便管理,代表我要有到/boot資料夾就可以看到不同的核心檔案
移動核心到/boot資料下(切記不要取名跟原本的核心檔案同名,不然會覆蓋掉,現在的動作是要產生新的核心檔案)
將原先的bzImage檔複製到/boot底下並取名為vmlinuz-2.6.28.5
將原先的.config檔複製到/boot底下並取名為config-2.6.28.5
建立相對應的Initial Ram Disk(如果是其他作業系統似乎是使用mkinitrd -v,但是Ubuntu是使用mkinitramfs -o指令)
三個新增的檔案
5.編輯開機選單
路徑位置:/boot/grub/menu.list
開機程式:grub
這裡的目的就是去修改menu.list的開機選單
新增的開機選單內容
title:設定名稱
root:磁碟分割槽第一分割區
uuid:唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定
kernel:欲載入的核心檔案
initrd:欲載入的initrd檔案
quiet:只顯示重要訊息
savedefault:儲存預設
其實可以順便在開機選單家這兩行,第一行default=0是說預設是第0個選項,也就是第一個設置的那個核心,而第二行timeout=10是說一開始會給十秒做猶豫選擇的時間,如果十秒沒按ESC進入開機選單的話,就會自行進入預設為第0個的核心選項
十秒的選擇時間,按ESC進入開機選單
新的開機選單
進入以後可以用uname -a的指令來看是否載入正確
(四)測試程式
可在任一地方新增一個test檔,新增一個syscalltest.c
編譯並執行
最後輸入dmesg|tail –n5觀看system call所執行的結果
輸出 hello world,表呼叫system call成功
留言列表