Linux体系结构

内核空间与用户空间是程序执行的两种不同状态,通过调用和硬件中断才能完成从用户空间到内核空间的转移。如右图所示:

linux内核调试方法总结_linux调用系统内核函数_linux内核系统调用

linux体系结布光

从上图获知,Linux由用户空间和内核空间

通常情况下,用户进程是不能访问内核的。它既不能访问内核所在的显存空间,也不能调用内核中的函数。Linux内核中设置了一组用于实现各类系统功能的子程序,用户可以通过调用她们访问linux内核的数据和函数,这种系统调用插口(SCI)称为系统调用。

系统调用和普通函数的区别:

系统调用和普通的函数调用十分相像,区别仅仅在于,系统调用由操作系统内核实现,运行于内核态;而普通的函数调用由函数库或用户自己提供,运行于用户态。

系统调用数:

在2.6.32版内核中,共有系统调用365个,可在arch/arm/include/asm/unistd.h中找到它们。

/*Thisfilecontainsthesystemcallnumbers*/

#define__NR_restart_syscall(__NR_SYSCALL_BASE+0)

#define__NR_exit(__NR_SYSCALL_BASE+1)

#define__NR_fork(__NR_SYSCALL_BASE+2)

......

#define__NR_preadv(__NR_SYSCALL_BASE+361)

#define__NR_pwritev(__NR_SYSCALL_BASE+362)

linux内核系统调用_linux调用系统内核函数_linux内核调试方法总结

#define__NR_rt_tgsigqueueinfo(__NR_SYSCALL_BASE+363)

#define__NR_perf_event_open(__NR_SYSCALL_BASE+364)

系统调用的功能:

主要分为3大类:

(1)进程控制类

fork创建一个子进程

clone根据指定条件创建子进程

execve运行可执行文件

...

(2)文件控制操作

fcntl文件控制

open打开文件

read读文件

...

(3)系统控制

ioctlI/O总控制函数

reboot重新启动

—sysctl读写系统参数

...

使用系统调用函数举例:

下边通过time函数系统调用实现从格林尼治时间1970年1月1日0:00开始到现今的秒数。

#include

main()

time_tt_time;

t_time=time((time_t*)0);/*调用time系统调用*/

printf("Thetimeis%ldn",t_time);

系统调用工作原理:

通常情况下,用户进程是不能访问内核的。它既不能访问内核所在的显存空间,也不能调用内核中的函数。系

统调用是一个例外。其原理是(1)进程先用适当的值填充寄存器,(2)之后调用一个特殊的指令,(3)这个指令会让用户程序跳转到一个事先定义好的内核中的一个位置。(4)进程可以跳转到的固定的内核位置。这个过程检测系统调用号,这个号码告诉内核进程恳求哪种服务。之后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。接着,就调用函数,等返回后,做一些系统检测linux内核系统调用,最后返回到进程。

工作原理概述:

(1)适当的值

所有适当的值我们都可以在include/asm/unistd.h中找到,在这个文件中为每一个系统调用规定了惟一的编号,称作系统调用号。

#define__NR_utimensat(__NR_SYSCALL_BASE+348)

#define__NR_signalfd(__NR_SYSCALL_BASE+349)

#define__NR_timerfd_create(__NR_SYSCALL_BASE+350)

#define__NR_eventfd(__NR_SYSCALL_BASE+351)

#define__NR_fallocate(__NR_SYSCALL_BASE+352)

这儿面每一个宏就是一个系统调用号

(2)特殊的指令

在IntelCPU中linux内核系统调用linux makefile,这个指令由中断0x80实现

在ARM中,这个指令是SWI(softwhereinterrupt:软中断指令),现今重新命名为SVC

(3)固定的位置

每位CPU固定的位置是不一样的,在ARM体系中这个固定的内核位置是ENTRY(vector_swi)(在archshkernelentry-common.S),也就是PC表针会跳转到这个位置

(4)相应的函数

内核依照应用程序传递来的系统调用号linux安装,从系统调用表sys_call_table找到相应的内核函数

CALL(sys_restart_syscall)

CALL(sys_exit)

CALL(sys_fork_wrapper)

实例:

工作原理(应用):下边是一个从用户open调用到找到内核中具体的系统调用函数入口地址的大体流程

#define__syscall(name)"swit"__NR_##name"nt“

intopen(constchar*pathname,intflags)

。。。。。。

__syscall(open);

。。。。。。

转化为

intopen(constchar*pathname,intflags)

。。。。。。

swit__NR_open//#define__NR_open(__NR_SYSCALL_BASE+5)

。。。。。。

//内核入口

/*arch/arm/kernel/entry-common.S*/

ENTRY(vector_swi)

……………………

adrtbl,sys_call_table@loadsyscalltablepointer

……………………

ldrccpc,[tbl,scno,lsl#2]@callsys_*routine

……………………

ENTRY(sys_call_table)

#include"calls.S"

/*arch/arm/kernel/calls.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_dup3)

CALL(sys_pipe2)

/*360*/CALL(sys_inotify_init1)

本文原创地址://gulass.cn/ltxjgnhkjyyh.html编辑:刘遄,审核员:暂无