系统调用
操作系统服务的编程接口
通常由高级语言编写(C或C++)
程序访问通常通过高层次 的API接口(C标准库的库函数)而不是直接进行系统调用
每个系统调用对应一个系统调用编号
系统调用与函数调用的区别
系统调用
1.使用INT和IRET指令,内核和应用程序使用的是不同的堆栈,因此存在堆栈的切换,从用户态切换到内核态,从而可以使用特权指令操控设备
2.依赖于内核,不保证移植性
3.在用户空间和内核上下文环境间切换,开销较大
4. 是操作系统的一个入口点
函数调用
1.使用CALL和RET指令,调用时没有堆栈切换
2.平台移植性好
3.属于过程调用,调用开销较小
4.一个普通功能函数的调用
以上转自:https://blog.csdn.net/qq_31759205/article/details/80602357
1. 系统调用(内核态)
系统调用,通俗的讲,说的是操作系统提供给用户程序调用的一组“特殊”接口。用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等。
- 控制硬件—系统调用往往作为硬件资源和用户空间的抽象接口,比如读写文件时用到的write/read调用。
- 设置系统状态或读取内核数据——因为系统调用是用户空间和内核的唯一通讯手段,所以用户设置系统状态,比如开/关某项内核服务(设置某个内核变量),或读取内核数据都必须通过系统调用。
- 进程管理—系统调用接口是用来保证系统中进程能以多任务在虚拟内存环境下得以运行。比如 fork、clone、execve、exit等
Linux中实现系统调用利用了0x86体系结构中的软件中断。首先,用户程序为系统调用设置参数。其中一个参数是系统调用编号。参数设置完成后,程序执行“系统调用”指令。x86系统上的软中断由int产生。这个指令会导致一个异常:产生一个事件,这个事件会致使处理器切换到内核态并跳转到一个新的地址,并开始执行那里的异常处理程序。此时的异常处理程序实际上就是系统调用处理程序。它与硬件体系结构紧密相关。
新地址的指令会保存程序的状态,计算出应该调用哪个系统调用,调用内核中实现那个系统调用的函数,恢复用户程序状态,然后将控制权返还给用户程序。系统调用是设备驱动程序中定义的函数最终被调用的一种方式。
(为系统调用设置参数,系统调用号压入寄存器,产生80中断, 由用户态切换到内核态 ,保护现场将程序运行相关信息压栈,执行系统调用处理程序 system_call,根据系统调用表找和系统调用号执行完函数,返回值压入寄存器,从内核态回到用户态,恢复现场,程序获得返回值 。)
2. 函数调用(或库函数调用,用户态, 与平台无关但是最终或多或少依赖于系统调用)
函数调用就相对熟悉多了。我们大一、大二编程所用的函数调用大多都是这里的函数调用,它运行在用户空间。
它主要通过压栈操作来进行函数调用。
例如,函数调用会执行下列操作:
⒈ 将帧指针压入栈中:pushebp
⒉ 使得帧指针等于栈指针:movebp,esp
⒊ 使栈指针自减,自减得到的内存地址应当能够(足够)用来存储被调用函数的本地状态:sub esp,0CCh
函数库调用 | 系统调用 |
在所有的ANSI C编译器版本中,C库函数是相同的 | 各个操作系统的系统调用是不同的 |
它调用函数库中的一段程序(或函数) | 它调用系统内核的服务 |
与用户程序相联系 | 是操作系统的一个入口点 |
在用户地址空间执行 | 在内核地址空间执行 |
它的运行时间属于“用户时间” | 它的运行时间属于“系统时间” |
属于过程调用,调用开销较小 | 需要在用户空间和内核上下文环境间切换,开销较大 |
在C函数库libc中有大约300个函数 | 在UNIX中大约有90个系统调用 |
典型的C函数库调用:system fprintf malloc | 典型的系统调用:chdir fork write brk; |
以上转自:https://blog.csdn.net/qq_37924084/article/details/78293047