1. 程式人生 > >在ARM Linux核心中增加一個新的系統呼叫

在ARM Linux核心中增加一個新的系統呼叫

實驗平臺核心版本為4.0-rc1,增加的系統呼叫僅僅是簡單列印一個Hello World,最後我們在使用者空間用swi指令驗證。涉及到的改動如下:

1. 在核心中增加檔案arch/arm/kernel/mysyscall.c,這個檔案實現新的列印Hello World的系統呼叫。

#include <linux/printk.h>
void sys_helloworld(void)
{
	printk("hello world\n");
}

修改arch/arm/kernel下的Makefile編入該檔案:
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -18,7 +18,7 @@ CFLAGS_REMOVE_return_address.o = -pg
 obj-y          := elf.o entry-common.o irq.o opcodes.o \
                   process.o ptrace.o return_address.o \
                   setup.o signal.o sigreturn_codes.o \
-                  stacktrace.o sys_arm.o time.o traps.o
+                  stacktrace.o sys_arm.o time.o traps.o mysyscall.o
 
 obj-$(CONFIG_ATAGS)            += atags_parse.o
 obj-$(CONFIG_ATAGS_PROC)       += atags_proc.o

2. 將sys_helloworld加入syscall的表,並修正syscall的數量:

數量修正,注意不是加1,而是加4,這個主要是因為padding對齊的原因。

--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -19,7 +19,7 @@
  * 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  (388)
+#define __NR_syscalls  (392)
 
 /*
  * *NOTE*: This is a ghost syscall private to the kernel.  Only the

把sys_helloworld函式指標填入arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -397,6 +397,7 @@
 /* 385 */      CALL(sys_memfd_create)
                CALL(sys_bpf)
                CALL(sys_execveat)
+               CALL(sys_helloworld)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted

編譯核心時候,使能OABI的相容:



重新編譯核心後,寫應用程式來驗證這個系統呼叫。

3. 應用程式驗證,OABI和EABI兩種方式:

程式如下:

#include <stdio.h>

#define	sys_oabi_hello() __asm__ __volatile__ ("swi 0x900000+388\n\t")
#define	sys_eabi_hello() __asm__ __volatile__ ("mov r7,#388\n\t" "swi 0\n\t" )

void main(void)
{
	printf("start hello\n");
	sys_oabi_hello();
	sys_eabi_hello();
	printf("end hello\n");
}

OABI方式下,系統呼叫方式是“swi 0x900000+388”,EABI則是把388填入r7,之後發“swi 0"。

關於OABI和EABI的區別,可以在PC上執行man syscall,得到答案如下:

       arch/ABI   instruction          syscall #   retval Notes
       ───────────────────────────────────────────────────────────────────────────────────
       arm/OABI   swi NR               -           a1     NR is syscall #


       arm/EABI   swi 0x0              r7          r0