學習linux系統呼叫時先明確乙個概念:一般情況下,應用程式通過應用程式設計介面api而不是直接通過系統呼叫來程式設計
應用程式設計介面api與系統呼叫的關係如下:(應用程式程式設計介面實際上並不需要和核心提供的系統呼叫對應)
(1)乙個api可以實現成乙個系統呼叫
(2)乙個api可以通過呼叫多個系統呼叫來實現
(3)乙個api可以完全不使用任何系統呼叫
來說說系統呼叫的一些共性吧:
1.系統呼叫(在linux中常稱作syscalls)通常通過函式進行呼叫
2.它們通常都需要定義乙個或幾個引數
3.系統呼叫通常會通過乙個long型別的返回值來表示成功或者錯誤
注意:用乙個負的返回值來表明錯誤;用乙個0值通常(不絕對)表明成功
系統呼叫號很重要:
每個系統呼叫被賦予乙個系統呼叫號,系統呼叫號關聯系統呼叫,當使用者空間的程序執行乙個系統呼叫的時候,這個系統呼叫號就被用來指明到底是要執行哪個系統呼叫,程序不會提及系統呼叫的名稱。注意:系統呼叫號相當關鍵,一旦分配就不能再有任何變更,否則編譯好的應用程式就會崩潰。此外,如果乙個系統呼叫被刪除,它所占用的系統呼叫號也不允許被**利用,否則,以前編譯過的**會呼叫這個系統呼叫,造成混亂。(linux有乙個「未實現」系統呼叫sys_ni_syscall(),它除了返回-enosys外不做任何其他工作,如果乙個系統呼叫被刪除,或者變得不可用,這個函式就要負責「填補空位」)
系統呼叫表(sys_call_table):
表中存放每個的系統呼叫的入口位址(函式指標);
每乙個體繫結構都有對應的乙個系統呼叫表;
如x86平台的系統呼叫表arch/x86/kernel/syscall_table_32.s
如arm平台的系統呼叫表arch/arm/kernel/entry-common.s
entry(sys_call_table)
#include"calls.s"//arch/arm/kernel/calls.s檔案內容如下:
/*0 */
call(sys_restart_syscall)
call(sys_exit)
call(sys_read)
call(sys_write)
/*5 */
call(sys_open)
call(sys_close)
..........
系統呼叫處理過程:
對於arm來說,系統軟中斷的入口處理程式是vector_swi(arch/arm/kernel/entry-common.s)
entry(vector_swi)
@獲取系統呼叫號到scno(r7)中;
@載入sys_call_table表到tbl變數中
@呼叫系統呼叫
基於tiny4412開發板的系統呼叫流程及示例:
linux核心的唯一訪問介面是系統呼叫,不同平台下的系統呼叫數目不一樣,在arm中,通用的系統呼叫有390個。通過修改核心的原始碼,增加第391個系統呼叫到核心中。
第一步:往核心新增乙個自定義系統呼叫
在核心原始碼的arch/arm/kernel/sys_arm.c 檔案中新增乙個系統呼叫的實現:
gedit arch/arm/kernel/sys_arm.c
在檔案最後新增如下**,這個就是系統呼叫的實現**:
asmlinkage long sys_foo(void)
第二步:將系統呼叫新增到系統呼叫表中
gedit arch/arm/kernel/calls.s
在系統呼叫號為390後面新增,如下藍色部分
/* 385 */ call(sys_memfd_create)
call(sys_bpf)
call(sys_execveat)
call(sys_use***ultfd)
call(sys_membarrier)
call(sys_mlock2)
call(sys_foo)
第三步:新增系統呼叫號
gedit arch/arm/include/uapi/asm/unistd.h
在系統呼叫號為390後面新增,如下藍色部分
#define __nr_bpf (__nr_syscall_base+386)
#define __nr_execveat (__nr_syscall_base+387)
#define __nr_use***ultfd (__nr_syscall_base+388)
#define __nr_membarrier (__nr_syscall_base+389)
#define __nr_mlock2 (__nr_syscall_base+390)
#define __nr_foo (__nr_syscall_base+391)
第四步:修改系統呼叫數目
gedit arch/arm/include/asm/unistd.h
#include
*this may need to be greater than __nr_last_syscall+1 in order to
*account for the padding in the syscall table
#define __nr_syscalls(392)//
該值要大於等於
」最大的系統呼叫號+1」
並且為4
的整數倍,對齊
第五步: 新增系統呼叫函式的宣告到頭檔案中
gedit include/linux/syscalls.h
在檔案的最後新增如下藍色部分;
asmlinkage long sys_open_by_handle_at(int mountdirfd,
struct file_handle __user *handle,
int flags);
asmlinkage long sys_setns(int fd, int nstype);
asmlinkage long sys_foo(void);
#endif
第六步:新增完畢後,重新編譯核心,並且使用重新編譯的核心來啟動開發板
make uimage loadaddr=0x40008000 -j2
以上就是新增乙個系統呼叫的過程,可通過一下應用程式做測試:
#include
#include
#include
int main(void)
long stack_size;
stack_size= syscall(391);//系統一般會通過c庫來呼叫系統呼叫,但是自己定義的系統呼叫缺少c庫的支援,只能使用巨集來呼叫系統呼叫
printf("thekernel stack size is %ld\n",stack_size);
return0;
交叉編譯上面的測試程式,在開發板上執行檢視效果
四 系統呼叫示例
獲取輸出檔名 開啟輸入檔案 如果檔案不存在,出錯退出 建立輸出檔案 如果檔案存在,出錯退出 迴圈直到讀取結束 關閉輸出檔案 在螢幕顯示完成完成資訊 正常退出 這裡涉及到的系統呼叫是 define sys write 5 define sys read 6 define sys close 7 def...
Linux 系統呼叫及核心除錯
編號後三位 411,參考孟寧老師 wget tar xzvf linux 5.0.3.tar.gz sudo apt install flex bison libssl devmake i386 defconfig make make j8 include intmain gcc o init in...
Linux系統呼叫及效能提公升
如何高效執行linux系統呼叫 linux的執行環境 核心空間 使用者空間 可以形象的把我們的整個linux執行環境想象成現實中的銀行,銀行的工作人員是核心空間,而使用者空間就是我們小老百姓,中間的視窗是為了實現我們和銀行工作人員進行交流進行業務辦理,那麼為什麼我們要有個隔板呢?那也是為了讓銀行的內...