操作系统 系统调用
系统调用是用户程序与操作系统进行交互的一种方式。程序请求多项服务,操作系统通过调用一系列系统调用来满足请求。系统调用可以用汇编语言或高级语言如 C 或 Pascal 编写。如果使用高级语言,操作系统可以直接调用预定义函数进行系统调用。
在本文中,您将了解操作系统中的系统调用,讨论它们的类型和其他许多内容。
什么是系统调用
系统调用是计算机程序向正在运行的内核请求服务的一种方法。系统调用是通过程序与操作系统进行交互的方法。系统调用是计算机软件向操作系统内核发出的请求。
应用程序接口(API)将操作系统的函数连接到用户程序。它充当操作系统与进程之间的链接,允许用户级程序请求操作系统服务。只能使用系统调用来访问内核系统。任何使用资源的程序都需要系统调用。
如何进行系统调用
当计算机软件需要访问操作系统的内核时,它会进行系统调用。系统调用使用API将操作系统的服务暴露给用户程序。这是访问内核系统的唯一方法。所有需要执行资源的程序或进程都必须使用系统调用,因为它们充当操作系统和用户程序之间的接口。
下面是系统调用与用户函数之间的一些示例差异:
- 系统调用函数可以创建和使用内核进程来执行异步处理。
- 系统调用具有比标准子例程更高的权限。拥有内核模式特权的系统调用在内核保护域中执行。
- 系统调用不允许使用共享库或任何不在内核保护域中的符号。
- 系统调用的代码和数据存储在全局内核内存中。
为什么在操作系统中需要系统调用
在操作系统中,有各种情况下都需要系统调用。以下是一些情况:
- 当文件系统想要创建或删除文件时。
- 网络连接需要系统调用来发送和接收数据包。
- 如果要读取或写入文件,需要系统调用。
- 如果要访问硬件设备,包括打印机、扫描仪,需要系统调用。
- 系统调用用于创建和管理新进程。
系统调用的工作原理
应用程序运行在被称为用户空间的内存区域中。系统调用连接到操作系统的内核,内核在内核空间中执行。当应用程序创建一个系统调用时,它首先必须获得内核的许可。它使用中断请求来实现这一点,中断请求会暂停当前进程并将控制权转移到内核。
如果请求被允许,内核将执行请求的操作,比如创建或删除文件。作为输入,应用程序接收到内核的输出。应用程序在接收到输入后恢复过程。操作完成后,内核将结果返回给应用程序,然后将数据从内核空间移动到用户空间的内存中。
一个简单的系统调用可能只需要几纳秒来提供结果,比如获取系统的日期和时间。一个更复杂的系统调用,比如连接到网络设备,可能需要几秒钟。大多数操作系统为每个系统调用启动一个单独的内核线程,以避免瓶颈。现代操作系统是多线程的,这意味着它们可以同时处理各种系统调用。
系统调用的类型
通常有五种类型的系统调用。它们如下:
- 进程控制
- 文件管理
- 设备管理
- 信息维护
- 通信
现在,你将逐一了解所有不同类型的系统调用。
进程控制
进程控制是用于控制进程的系统调用。一些进程控制的例子包括创建、加载、中止、结束、执行、处理、终止进程等。
文件管理
文件管理是用于处理文件的系统调用。一些文件管理的例子包括创建文件、删除文件、打开、关闭、读取、写入等。
设备管理
设备管理是用于处理设备的系统调用。一些设备管理的例子包括读取设备、写入设备、获取设备属性、释放设备等。
信息维护
信息维护是用于维护信息的系统调用。一些信息维护的例子包括获取系统数据、设置时间或日期、获取时间或日期、设置系统数据等。
通信
通信是用于通信的系统调用。一些通信的例子包括创建、删除通信连接、发送、接收消息等。
Windows和Unix系统调用的例子
Windows和Unix系统调用有各种各样的例子。下表列出了一些例子:
进程 | Windows | Unix |
---|---|---|
进程控制 | CreateProcess() ExitProcess() WaitForSingleObject() | Fork() Exit() Wait() |
文件操作 | CreateFile() ReadFile() WriteFile() CloseHandle() | Open() Read() Write() Close() |
设备管理 | SetConsoleMode() ReadConsole() WriteConsole() | Ioctl() Read() Write() |
信息维护 | GetCurrentProcessID() SetTimer() Sleep() | Getpid() Alarm() Sleep() |
通信 | CreatePipe() CreateFileMapping() MapViewOfFile() | Pipe() Shmget() Mmap() |
保护 | SetFileSecurity() InitializeSecurityDescriptor() SetSecurityDescriptorgroup() | Chmod() Umask() Chown() |
这里,您将简要了解一些方法:
open()
open()系统调用允许您访问文件系统中的文件。它为该文件分配资源并提供一个进程可以引用的句柄。可以有多个进程同时打开一个文件,也可以只有一个进程打开一个文件。这完全取决于文件系统和结构。
read()
它用于从文件系统中获取数据。一般接受三个参数:
- 文件描述符。
- 用于存储读取数据的缓冲区。
- 从文件中读取的字节数。
要读取的文件的文件描述符可以在读取之前使用open()标识并打开它。
wait()
在某些系统中,一个进程可能需要等待另一个进程完成执行后才能继续。当父进程创建子进程时,父进程的执行被挂起,直到子进程完成。wait()系统调用用于挂起父进程。一旦子进程完成执行,控制将返回给父进程。
write()
它用于将用户缓冲区中的数据写入设备(如文件)。这个系统调用是程序生成数据的一种方式。一般情况下,它接受三个参数:
- 文件描述符。
- 指向保存数据的缓冲区的指针。
- 从缓冲区中要写入的字节数。
fork()
进程使用fork()系统调用生成自己的克隆。这是操作系统中创建进程的最常见方式之一。当父进程生成一个子进程时,父进程的执行被中断,直到子进程完成。一旦子进程完成执行,控制将返回给父进程。
close()
它用于结束文件系统访问。当调用此系统调用时,表示程序不再需要该文件,缓冲区将被清除,文件信息将被修改,并且文件资源将被释放。
exec()
当可执行文件替换已经执行的进程中的旧可执行文件时,将调用此系统函数。由于不会构建新的进程,因此旧的进程标识保持不变,但新的进程替换了数据、堆栈、数据头等。
exit()
exit()是一个用于结束程序执行的系统调用。此调用表示线程执行完成,在多线程环境中特别有用。操作系统在使用exit()系统函数之后回收进程使用的资源。