没有合适的资源?快使用搜索试试~ 我知道了~
linux系统调用linux系统调用
4星 · 超过85%的资源 需积分: 12 7 下载量 11 浏览量
2011-08-02
00:20:48
上传
评论
收藏 101KB DOC 举报
温馨提示
试读
12页
linux系统调用linux系统调用linux系统调用linux系统调用linux系统调用linux系统调用linux系统调用linux系统调用linux系统调用linux系统调用linux系统调用
资源推荐
资源详情
资源评论
Linux 系统调用
什么是系统调用
顾名思意,系统调用说的是操作系统提供给用户程序调用的一组“特殊”接口。
用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务,比如用户
可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以
通过时钟相关的系统调用获得系统时间或设置系统时间等。
从逻辑上来说,系统调用可被看成是一个内核与用户空间程序交互的接口
——它好比一个中间人,把用户进程的请求传达给内核,待内核把请求处理完
毕后再将处理结果送回给用户空间。
系统服务之所以需要通过系统调用提供给用户空间的根本原因是为了对系
统“保护”,因为我们知道 Linux 的运行空间分为内核空间与用户空间,它们各自
运行在不同的级别中,逻辑上相互隔离。所以用户进程在通常情况下不允许访
问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用
户用空间函数。比如我们熟悉的“hello world”程序(执行时)就是标准的户空间
进程,它使用的打印函数 printf 就属于用户空间函数,打印的字符“hello word”
字符串也属于用户空间数据。
但是很多情况下,用户进程需要获得系统服务(调用系统程序),这时就
必须利用系统提供给用户的“特殊”接口——系统调用了,它的特殊性主要在于
规定了用户进程进入内核的具体位置;换句话说用户访问内核的路径是事先规
定好的,只能从规定位置进入内核,而不准许肆意跳入内核。有了这样的陷入
内核的统一访问路径限制才能保证内核安全无虞。我们可以形象地描述这种机
制:作为一个游客,你可以买票要求进入野生动物园,但你必须老老实实的坐
在观光车上,按照规定的路线观光游览。当然,不准下车,因为那样太危险,
不是让你丢掉小命,就是让你吓坏了野生动物。
Linux 的系统调用
对于现代操作系统,系统调用是一种内核与用户空间通讯的普遍手段 ,
Linux 系统也不例外。但是 Linux 系统的系统调用相比很多 Unix 和 windows 等
系统具有一些独特之处,无处不体现出 Linux 的设计精髓——简洁和高效。
Linux 系统调用很多地方继承了 Unix 的系统调用(但不是全部),但 Linux
相比传统 Unix 的系统调用做了很多扬弃,它省去了许多 Unix 系统冗余的系统
调用,仅仅保留了最基本和最有用的系统调用,所以 Linux 全部系统调用只有
250 个左右(而有些操作系统系统调用多达 1000 个以上)。
这些系统调用按照功能逻辑大致可分为“进程控制”、“文件系统控制”、“系
统控制”、“存管管理”、“网络管理”、“socket 控制”、“用户管理”、“进程间通信”几
类,详细情况可参阅文章系统调用列表
如果你想详细看看系统调用的说明,可以使用 man 2 syscalls 命令查看,
或干脆到 <内核源码目录>/include/asm-i386/unistd.h 源文件种找到它们的原本。
熟练了解和掌握上面这些系统调用是对系统程序员的必备要求,但对于一
个开发内核者或内核开发者来
1[1]
说死记硬背下这些调用还远远不够。如果你仅
仅知道存在的调用而不知道为什么它们会存在,或只知道如何使用调用而不知
道这些调用在系统中的主要用途,那么你离驾驭系统还有不小距离。
要弥补这个鸿沟,第一,你必须明白系统调用在内核里的主要用途。虽然
上面给出了数种分类,不过总的概括来讲系统调用主要在系统中的用途无非以
下几类:
控制硬件——系统调用往往作为硬件资源和用户空间的抽象接口,比
如读写文件时用到的 write/read 调用。
设置系统状态或读取内核数据——因为系统调用是用户空间和内核的
唯一通讯手段
2[2]
,所以用户设置系统状态,比如开/关某项内核服务
(设置某个内核变量),或读取内核数据都必须通过系统调用。比如
getpgid、getpriority、setpriority、sethostname
进程管理——一系列调用接口是用来保证系统中进程能以多任务,在
虚拟内存环境下得以运行。比如 fork、clone、execve、exit 等
第二,什么服务应该存在于内核;或者说什么功能应该实现在内核而不是
在用户空间。这个问题并不没有明确的答案,有些服务你可以选择在内核完成,
也可以在用户空间完成。选择在内核完成通常基于以下考虑:
服务必须获得内核数据,比如一些服务必须获得中断或系统时间等内
核数据。
从安全角度考虑,在内核中提供的服务相比用户空间提供的毫无疑问
更安全,很难被非法访问到。
从效率考虑,在内核实现服务避免了和用户空间来回传递数据以及保
护现场等步骤,因此效率往往要比实现在用户空间高许多。比如,httpd
等服务。
如果内核和用户空间都需要使用该服务,那么最好实现在内核空间,
比如随机数产生。
理解上述道理对掌握系统调用本质意义很大,希望网友们能从使用中多总结,
多思考。
系统调用、用户编程接口(API)、系统命令、和内核函数
的关系
系统调用并非直接和程序员或系统管理员打交道,它仅仅是一个通过软中
断机制(我们后面讲述)向内核提交请求,获取内核服务的接口。而在实际使
用中程序员调用的多是用户编程接口——API,而管理员使用的则多是系统命
令。
用户编程接口其实是一个函数定义,说明了如何获得一个给定的服务,比
如 read()、malloc()、free()、abs()等。它有可能和系统调用形式上一致,比如
1[1]
我们说的开发内核者指开发系统内核,比如开发驱动模块机制、开发系统调用机制;而内核开发者则是
指在内核基础之上进行的开发,比如驱动开发、系统调用开发、文件系统开发、网络通讯协议开发等。我
们杂志所关注的问题主要在内核开发层次,即利用内核提供的机制进行开发。
2[2]
对 Linux 而言,系统调用是用户程序访问内核的唯一手段,无论是/proc 方式或设备文件方式归根到底都
是利用系统调用完成的。
read()接口就和 read 系统调用对应,但这种对应并非一一对应,往往会出现几种
不同的 API 内部用到统一个系统调用,比如 malloc()、free()内部利用 brk( )系
统调用来扩大或缩小进程的堆;或一个 API 利用了好几个系统调用组合完成服
务。更有些 API 甚至不需要任何系统调用——因为它不必需要内核服务,如计
算整数绝对值的 abs()接口。
另外要补充的是 Linux 的用户编程接口遵循了在 Unix 世界中最流行的应用
编程界面标准—— POSIX 标准,这套标准定义了一系列 API。在 Linux 中
(Unix 也如此)这些 API 主要是通过 C 库(libc)实现的,它除了定义的一些
标准的 C 函数外, 一 个 很 重 要 的任务就是提供了一套封装例程(wrapper
routine)将系统调用在用户空间包装后供用户编程使用。
不过封装并非必须的,如果你愿意直接调用, Linux 内核也提供了一个
syscall()函数来实现调用,我们看个例子来对比一下通过 C 库调用和直接调用的
区别。
#include <syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
int main(void) {
long ID1, ID2;
/*-----------------------------*/
/* 直接系统调用*/
/* SYS_getpid (func no. is 20) */
/*-----------------------------*/
ID1 = syscall(SYS_getpid);
printf ("syscall(SYS_getpid)=%ld\n", ID1);
/*-----------------------------*/
/* 使用"libc"封装的系统调用 */
/* SYS_getpid (Func No. is 20) */
/*-----------------------------*/
ID2 = getpid();
printf ("getpid()=%ld\n", ID2);
return(0);
}
系统命令相对编程接口更高了一层,它是内部引用 API 的可执行程序,比
如我们常用的系统命令 ls、hostname 等。Linux 的系统命令格式遵循系统 V 的传
统,多数放在/bin 和/sbin 下(相关内容可看看 shell 等章节)。
有兴趣的话可以通过 strace ls 或 strace hostname 命令查看一下它们用到的系
统调用,你会发现诸如 open、brk、fstat、ioctl 等系统调用被用在系统命令中。
下一个需要解释一下的问题是内核函数和系统调用的关系,内核函数大家
不要想像的过于复杂,其实它们和普通函数很像,只不过在内核实现,因此要
满足一些内核编程的要求
3[3]
。系统调用是一层用户进入内核的接口,它本身并
非内核函数,进入内核后,不同的系统调用会找到对应到各自的内核函数——
换个专业说法就叫:系统调用服务服务例程。实际对请求服务的是内核函数而
3[3]
内核编程相比用户程序编程有一些特点,简单的讲内核程序一般不能引用 C 库函数(除非你自己实现了,
比如内核实现了不少 C 库种的 String 操作函数);缺少内存保护措施;堆栈有限(因此调用嵌套不能过
多);而且由于调度关系,必须考虑内核执行路径的连续性,不能有长睡眠等行为。
剩余11页未读,继续阅读
资源评论
- MrZhang19942019-08-28还可以的,不错
小新8111
- 粉丝: 9
- 资源: 13
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功