微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Arm Linux系统调用流程详细解析

Arm Linux系统调用流程详细解析

时间:11-09 来源:互联网 点击:

d as sys_ni_syscall.*/#define ABI(native, compat) native#ifdef CONFIG_AEABI#define OBSOLETE(syscall) sys_ni_syscall#else#define OBSOLETE(syscall) syscall#endif.type sys_call_table, #objectENTRY(sys_call_table)#include "calls.S"#undef ABI#undef OBSOLETE

上面的zero_fp是一个宏,在arch/arm/kernel/entry-header.S中定义:

.macro zero_fp#ifdef CONFIG_FRAME_POINTERmov   fp, #0#endif.endm//而fp位寄存器r11。

像每一个异常处理程序一样,要做的第一件事当然就是保护现场了。紧接着是获得系统调用的系统调用号。

然后以系统调用号作为索引来查找系统调用表,如果系统调用号正常的话,就会调用相应的处理例程来处理,就是上面的那个ldrccpc, [tbl, scno, lsl #2]语句,然后通过例程ret_fast_syscall来返回。

在这个地方我们接着来讨论ABI的问题。现在,我们首先来看两个宏,一个是CONFIG_OABI_COMPAT意思是说与old ABI兼容,另一个是CONFIG_AEABI意思是说指定现在的方式为EABI。这两个宏可以同时配置,也可以都不配,也可以配置任何一种。我们来看一下内核是怎么处理这一问题的。我们知道,sys_call_table在内核中是个跳转表,这个表中存储的是一系列的函数指针,这些指针就是系统调用函数的指针,如(sys_open)。系统调用是根据一个系统调用号(通常就是表的索引)找到实际该调用内核哪个函数,然后通过运行该函数完成的。
首先,对于old ABI,内核给出的处理是为它建立一个单独的system call table,叫sys_oabi_call_table,这样,兼容方式下就会有两个system call table,以old ABI方式的系统调用会执行old_syscall_table表中的系统调用函数,EABI方式的系统调用会用sys_call_table中的函数指针。
配置无外乎以下4中:
第一、两个宏都配置行为就是上面说的那样。
第二、只配置CONFIG_OABI_COMPAT,那么以old ABI方式调用的会用sys_oabi_call_table,以EABI方式调用的用sys_call_table,和1实质上是相同的。只是情况1更加明确。
第三、只配置CONFIG_AEABI系统中不存在sys_oabi_call_table,对old ABI方式调用不兼容。只能 以EABI方式调用,用sys_call_table。

第四、两个都没有配置,系统默认会只允许old ABI方式,但是不存在old_syscall_table,最终会通过sys_call_table完成函数调用

系统会根据ABI的不同而将相应的系统调用表的基地址加载进tbl寄存器,也就是r8寄存器。接下来来看系统调用表,如前面所说的那样,有两个,同样都在文件arch/arm/kernel/entry-common.S中:

/** This is the syscall table declaration for native ABI syscalls.* With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.*/#define ABI(native, compat) native#ifdef CONFIG_AEABI#define OBSOLETE(syscall) sys_ni_syscall#else#define OBSOLETE(syscall) syscall#endif.type    sys_call_table, #objectENTRY(sys_call_table)#include "calls.S"#undef ABI#undef OBSOLETE

另外一个为:

/** This is the syscall table declaration for native ABI syscalls.* With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.*/#define ABI(native, compat) native#ifdef CONFIG_AEABI#define OBSOLETE(syscall) sys_ni_syscall#else#define OBSOLETE(syscall) syscall#endif.type    sys_call_table, #objectENTRY(sys_call_table)#include "calls.S"#undef ABI#undef OBSOLETE

这样看来貌似两个系统调用表是完全一样的。这里预处理指令include的独特用法也挺有意思,在系统调用表的内容就是整个arch/arm/kernel/calls.S文件的内容这个文件的内容如下(由于太长,这里就不全部列出了):

/**  linux/arch/arm/kernel/calls.S**  Copyright (C) 1995-2005 Russell King** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation.**  This file is included thrice in entry-common.S*//* 0 */        CALL(sys_restart_syscall)CALL(sys_exit)CALL(sys_fork_wrapper)CALL(sys_read)CALL(sys_write)/* 5 */        CALL(sys_open)CALL(sys_close)CALL(sys_ni_syscall)        /* was sys_waitpid */CALL(sys_creat)CALL(sys_link)...

这个是同样在文件arch/arm/kernel/entry-common.S中的宏CALL()的定义:

.equ NR_syscalls,0#define CALL(x) .equ NR_syscalls,NR_syscalls+1#include "calls.S"#undef CALL#define CALL(x) .long x

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top