linux系统调用功能上可以分为,Linux系统调用(syscall)原理

Linux体系结构

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

fae47c2532d79a70adb5bd3c52500399.png

linux 体系结构图

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

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

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

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

系统调用数:

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

/*This file contains the system call numbers*/

#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)

#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)系统控制

ioctl I/O总控制函数

reboot重新启动

—sysctl读写系统参数

...

使用系统调用函数举例:

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

#include

main()

{

time_t t_time;

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

printf("The time is %ld\n",t_time);

}

系统调用工作原理:

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

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

工作原理概述:

(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)特殊的指令

在Intel CPU中,这个指令由中断0x80实现

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

(3)固定的位置

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

(4)相应的函数

内核根据应用程序传递来的系统调用号,从系统调用表sys_call_table找到相应的内核函数

CALL(sys_restart_syscall)

CALL(sys_exit)

CALL(sys_fork_wrapper)

实例:

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

#define __syscall(name) "swi\t" __NR_##name "\n\t“

int open( const char * pathname, int flags)

{

。。。。。。

__syscall(open);

。。。。。。

}

转化为

int open( const char * pathname, int flags)

{

。。。。。。

swi\t __NR_open  //#define __NR_open(__NR_SYSCALL_BASE+  5)

。。。。。。

}

//内核入口

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

ENTRY(vector_swi)

…… …… …… ……

adr tbl, sys_call_table @ load syscall table pointer

…… …… …… ……

ldrcc pc, [tbl, scno, lsl #2] @ call sys_* 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)

http://blog.csdn.net/nanfenglei23/article/details/41928293

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值