问:系统调用的原理,一个C函数怎么就把系统功能提供给了用户程序呢?

YoziDream 2005-01-07 04:37:26
最近学习操作系统,了解到操作系统很大一部分可以说是由其提供的系统调用组成。

以前学微机原理时只知道Dos下系统调用int 21h等中断进入到系统的代码,这样系统通过中断向用户程序开放了功能调用。

而到了现代这个时代,不管是Linux还是Windows,系统调用好像都是通过一系列的C库函数提供的。依据我对C语言的理解,编写好的程序总要链接成一个可执行文件。最近我又了解到Linux内核编译后,所有提供系统调用功能的函数应该都是链接到一个内核映像文件里,然后由引导器加载然后执行的。然后由引导器加载然后执行的。

那么,通过 C 函数来调用的系统功能,是如何进入到系统的?我的程序显然不是和内核链接在一起的。好像这也不像通常那样的动态链接呀?动态链接又是怎么实现的?

谢谢各位老大!
...全文
272 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
YoziDream 2005-01-13
  • 打赏
  • 举报
回复
OK,谢谢各位的帮助,以后有问题了再请教。
CoolQ 2005-01-12
  • 打赏
  • 举报
回复
you can use man to get info about all the system call functions, also.
CoolQ 2005-01-12
  • 打赏
  • 举报
回复
Real mode and protected mode is quite different.

Linux also exported the syscalls.
Have a look at unistd.h, all syscall numbers(__NR_xxx) are listed in it.
you can use the defined Macros(syscall0,...) to call syscall directly, without the need of glibc.

You can think Glibc is equivalent to MFC ;)
YoziDream 2005-01-12
  • 打赏
  • 举报
回复
还有一点点疑问,解决了就结贴。再谢。

系统调用在Windows里好像是通过Windows里的User32.dll等来导出的。 也就是说操作系统完整的提供了系统调用的接口。

而在Linux里的系统调用接口,却是由glibc来实现的,glibc却不属于Linux kernel,怎样看来Linux和Glibc绑定在了一起。好像同时还存在一个“循环”?linux kernel用gcc来编译的,kernel提供的系统调用又是用gcc来调用。kernel在实现的时候,自己提供一个系统调用的导出库不好吗?
zdhzidy 2005-01-12
  • 打赏
  • 举报
回复
英语狂人说的对。up。
you can use man to get info about all the system call functions, also

这句说的非常好。你学习Linux应该先学会使用man。
zdhzidy 2005-01-11
  • 打赏
  • 举报
回复
你对Linux系统调用理解正确:)
但是和dos的区别你只看到了表面现象,其实两个系统调用原理最大的不同在于:dos运行的CPU实模式下而Linux运行在保护,这才是它们的本质区别-0-,由于这个原因Linux的中断入口表存储的不直接是入口地址,而是入口地址的选择子(保护模式都是通过选择子来寻址的)。
中断表存放的位置是根据CPU中的一个中断地址寄存器来访问的,DOS也同样使用这个寄存器,只不过它默认的指向内存的开始位置罢了。
CPU运行级别的变化是是不需要程序自己处理的,CPU在接到中断并相应中断的时候就已经自己转换了。
zdhzidy 2005-01-11
  • 打赏
  • 举报
回复
我还是把我另一个帖子的回答copy过来把
先说系统调用的问题。其实任何操作系统的系统调用原理都是一样的(x86体系下)都是通过一个调用门从用户态转入核心态的,不同的系统对这个门的处理可能在细节上不同,但是反映到编程上都是int xx,比如DOS系列的就是21h中断,Linux是80h中断。由于CPU运行在保护模式下,用户空间和系统空间是分离的,系统调用要作的就是给用户空间和系统空间提供一个桥梁可以让用户访问系统空间的内容,要达到这个目的主要是改变当前CPU的运行级别。这样就可以访问系统空间,当从内核返回的时候又把CPU的运行级别改位用户级别。

内核模块是和内核代码连接到一起运行的,并且和内核代码有一样的CPU运行级别所以可以不通过系统调用就直接访问内核空间的内容。如果用户空间要访问这部分代码同样要通过系统调用这个门来进行。

用C/C++等语言编程的时候你虽然没有直接用到int 80h来进行系统调用但是你调用的一些函数编译以后也是编程int 80h,只是你直接看不到而已。

动态连接是一个用户空间的概念,不同的系统有自己不同的可执行文件格式,Linux使用的是elf格式的可执行文件,动态连接只是把多个符合格式的文件在需要的时候加载到用户空间内存,然后把那段地址空间映射到需要调用它的进程空间中。这样用到动态库的进程就可以顺利的访问了。


PS:DOS操作系统提供的21h中断其实不是现在意义上的系统调用,而只是一个函数的入口表而已,因为DOS并没有用户空间的概念,它是一个运行的实模式下的系统。
YoziDream 2005-01-09
  • 打赏
  • 举报
回复
通过大家的耐心解答,这是我的一点理解,看对吗?

操作系统在编写的时候,写了一系列的C函数,分别完成各种系统调用的功能。然后系统加载的时候,在系统的地址空间里保存了一张表,内容是:
“ 调用号,入口地址 ”
然后用户程序中一个系统调用,比如
fork();
编译器看到这个函数,就在glibc里找到这个函数对应的代码,里面有这样一些指令:
mov eax,调用号
int 80h
系统在执行到int 80h时,产生一个陷入?中断,完成从用户态到系统态的转换,并根据调用号查找系统调用表相应的入口地址,完成具体的功能。

他和Dos 不同的地方在于,(1)这个表不仅保存入口地址,还包括一些其他额外信息?(2)不是固定在内存的最开头,而是根据操作系统实现不同,可以放在不同地方,(3)有执行权限的转化。

是这样吗?
沙沙的吹 2005-01-09
  • 打赏
  • 举报
回复
实际过程其实跟DOS是一样的,应用程序首先会把函数调用信息(函数名、参数)保存到一个地方,然后产生一个软中断以进入内核,内核在把这些数据取出来,然后查找一个表,找到该系统调用对应的函数入口,用参数调用之
gettext 2005-01-08
  • 打赏
  • 举报
回复
一两句话还真说不明白。
beepbug 2005-01-08
  • 打赏
  • 举报
回复
补充一点。和DOS的机理一模一样。DOS是学CP/M(运行于8080、Z80等8位CPU),CP/M是学UNIX。
区别是:在源码里,DOS的系统调用是汇编语言级,而UNIX是C语言级。因而在UNIX里,系统调用和库函数调用的格式是一样的。
beepbug 2005-01-08
  • 打赏
  • 举报
回复
说到底就是一个远程指针。用它就可以访问系统调用模块。系统有个总接口,也就是有一张入口表。你要调用的系统调用模块此时不一定在内存中。没关系,系统的内存调度会把它装进来。
lijiangshui 2005-01-07
  • 打赏
  • 举报
回复
呵呵,UP
zhengda1936 2005-01-07
  • 打赏
  • 举报
回复
哈哈。分没地方用给我好了
YoziDream 2005-01-07
  • 打赏
  • 举报
回复
我怎么没有看到啊?打开帖子说请输入帖子号。我还说系统吃了我一百分呢?

zdhzidy 2005-01-07
  • 打赏
  • 举报
回复
不是已经回答过一次了嘛!怎么又问一次,你很多分没地方用?

4,441

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧