《程序员的自我修养》学习心得——第十二章 系统调用与API

前言

老规矩,还是只看Linux相关的东西,想要了解Windows的朋友还请自行翻阅原著。关于系统调用,起始在前面ret2sys这道题中有过一些了解,程序本身没有system函数,通过使用int 0x80的方式进行系统调用。完全不知道我在说些什么也没有关系,这是一道pwn栈溢出的题,可以翻看前面的文章。下一个文章会列出系统调用号

如果这篇文章能够帮助到你,就点个赞吧,有什么问题也可以在评论区留言Thanks♪(・ω・)ノ

一、系统调用介绍

1、什么是系统调用

为了让应用程序有能力访问系统资源,也为了让程序借助操作系统 做一些必须有操作系统支持的行为,每个操作系统都会提供一套接口,以供应用程序使用。这些接口往往通过中断来实现,比如Linux使用0x80号中断作为系统调用的入口

系统调用涵盖功能很广,有程序运行所必须的支持,例如创建/退出进程和线程、进程内存管理,也有对系统资源的访问,例如文件、网络、进程间通信、硬件设备的访问,也可能有对图形界面的操作支持

系统调用既然作为一个借口,定义十分重要。因为所有应用程序都依赖于系统调用,那么,首先系统调用必须有明确的定义,即每个调用的含义、参数、行为都需要有严格的定义,这样应用程序(运行库)才可以正确使用它。其次必须保持稳定和向后兼容,如果某次系统更新导致系统调用接口发生改变,新的系统调用接口与之前版本完全不同,这是无法想象的,因为所有之前能正常运行的程序都将无法使用。所以操作系统的系统调用往往从一开始定义后就基本不做改变,而仅仅是增加新的调用接口,以保持向后兼容

2、Linux系统调用

下面看看Linux系统调用的定义,已有一个比较直观的概念。在x86下,系统调用由0x80中断完成,各个通用寄存器用于传递参数,EAX寄存器用于表示系统调用的接口号,比如EAX=1表示退出进程(exit);EAX=2表示创建进程(fork);EAX=3表示读取文件或IO(read);EAX=4表示写文件或IO(write)等,每个系统调用都对应于内核源代码中的一个函数,他们都是以“sys_”开头的,比如exit调用对应内核中的sys_exit函数。当系统调用返回时,EAX又作为调用结果的返回值

3、系统调用的弊端

系统调用完成了应用程序和内核交流的工作,因此理论上只需要系统调用,就可以完成一些程序,但是事实上,包括Linux,大部分操作系统的系统调用都有两个特点:

  • 使用不便:操作系统提供的系统调用接口往往过于原始,程序员要了解很多与操作系统相关的细节。如果没有进行很好的包装,使用起来不方便
  • 各个操作系统之间系统调用不兼容:首先Windows系统和Linux系统之间的系统调用就基本上完全不同,虽然它们的内容很多都一样,但是定义和实现不大一样,即使是同系列的操作系统的系统调用都不一样,比如Linux和UNIX就不相同

为了解决这个问题,就用到了第一章讲的增加层的方法,哪里不兼容加哪里,妈妈再也不担心操作系统听不懂人话了。那么添加的中间层就是运行库,它作为系统调用与程序之间的一个抽象层可以保持着这样的特点:

  • 使用简便。因为运行库本身就是语言级别的,他一般都设计相对比较友好
  • 形式统一。运行库有它的标准,叫做标准库,范式所有遵循这个标准的运行库理论上都是相互兼容的,不会随着操作系统或编译器的变化而变化

二、系统调用原理

1、特权级与中断

现代的VPU常常可以再多种不同的特权级别下执行指令,现代操作系统中有两种特权级别,分别为用户模式(User Mode)和内核模式(Kernel Mode)也被称为用户态内核态。由于有多种特选模式存在,操作系统就可以让不同的代码运行在不同的模式上,以限制他们的权利,提高稳定性和安全性。普通应用程序在用户态的模式下,诸多操作将受到限制,这些操作包括访问硬件设备、开关中断、改变特权模式等

一般来说,运行在高特权级的代码将自己降至低特权是允许的,但反过来低特权级的代码将自己提升至高特权级则不是轻易就能进行的,否则特权级的作用就有名无实了。在将低特权级的环境装维高特权级时,需要使用一种较为受控和安全的形式,以防止低特权模式的代码破坏搞特权模式代码的执行

系统调用时运行在内核态的,而应用程序基本都是运行在用户态的。操作系统一般通过中断(Interrupt)来从用户态切换到内核态。中断是一个硬件或软件发出的请求,要求CPU暂停当前的工作转手去处理更加重要的事情。

中断一般具有两个属性,一个称为中断号(从0开始),一个称为中断处理程序(Interrupt Service Routine,ISR)。不同的中断具有不同的中断号,同时一个中断处理程序一一对应一个中断号。在内核中,有一个数组称为中断向量表(Interrupt Vector Table),这个数组的第n项包含了指向第n号中断的中断处理程序的指针。当中断到来时,CPU会暂停当前执行的代码,根据中断的中断号,在中断向量表中找到对应的中断处理程序,并调用它。中断处理程序执行完成之后,CPU会继续执行之前的代码

在这里插入图片描述
通常中断有两种类型,一种为硬件中断,这种中断来自于硬件的异常或其他事件的发生,如电源掉电、键盘被按下等。另一种称为软件中断,软件中断通常是一条指令(i386下是int),常有一个参数记录中断号,使用这条指令用户可以手动触发某个中断并执行其中断处理程序。例如在i386下,int 0x80这条指令会调用第0x80号中断的处理程序

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41202237/article/details/107180764