Linux 系统调用流程序列

标签 linux linux-kernel operating-system system-calls

我有一个关于 Linux 深度工作的问题。

假设一个多线程进程正在 CPU 中执行。在这种情况下,我们将有一个正在 CPU 上执行的线程。从更广泛的角度来看,我们将拥有属于正在加载到 RAM 中以供执行的进程的相应页面。

假设线程进行系统调用。我对这之后的工作有点不清楚。中断将产生一个调用。我的问题之一是谁会接听这个电话?

假设系统有 m:n 用户级线程到内核级线程映射,我假设相应的内核级线程将响应此调用。

因此内核将查找中断向量表并获取需要执行的例程。我的下一个问题是哪个堆栈将用于中断的执行?它是内核线程的栈还是用户级线程的栈? (我假设它将是内核线程的堆栈。)

回到程序流程,假设操作是使用 fopen 打开文件。接下来的问题是如何从 ISR 跳转到系统调用?或者我们的 ISR 是否映射到系统调用?

另外,在执行内核线程时,从更广泛的角度来看,我假设 RAM 上的“操作系统区域”将用于存放正在执行系统调用的页面。

再次从不同的角度来看它(希望你仍然支持我)最后我假设相应的内核线程正在由 CPU 调度程序处理,在上下文切换中会发生从用户级线程到相应的fopen 系统调用被应答时的内核级线程。

我做了很多假设,如果有人能消除疑虑或至少指导我朝着正确的方向前进,那将是非常棒的。

最佳答案

注意:我主要使用 ARM 机器,因此其中一些内容可能是特定于 ARM 的。另外,我将尝试尽可能地简化它。随时纠正任何可能错误或过于简单化的内容。

Lets say the thread makes a system call. I am a bit unclear on the workings after this. The Interrupt will generate a call. One of my questions is who will answer this call?

通常,处理器会在内核模式下的某个预定位置开始执行。内核将保存当前进程状态并查看用户空间寄存器以确定请求了哪个系统调用并将其分派(dispatch)给正确的系统调用处理程序。

So the Kernel will lookup the Interrupt Vector Table and get the routine which needs to be executed. My next question is which stack will be used in the execution of the Interrupt? Will it be the Kernel Thread's Stack or the User level Thread's Stack? (I am assuming that it will be the Kernel Thread's Stack.)

我很确定它会切换到内核堆栈。如果他们使用用户空间堆栈,将会存在一些非常严重的信息泄漏安全问题。

Coming back to the flow of the program lets say the operation is opening a file using fopen. The subsequent question I have is how will the jump from the ISR to System Call take place? Or is our ISR mapped to a System Call?

fopen() 实际上是一个 libc 函数而不是系统调用本身。它可能(并且在大多数情况下会)在其实现中调用 open() 系统调用。

因此,过程(大致)是:

  1. 用户空间调用 fopen()
  2. fopen 执行对 open()
  3. 的系统调用
  4. 这会触发某种异常或中断。作为响应,处理器切换到更高特权模式并开始在内核中的某个预设位置执行。
  5. 内核确定它是什么类型的中断和异常并适本地处理它。在我们的例子中,这将是一个系统调用。
  6. 内核通过读取用户空间寄存器并提取任何参数并将其传递给适当的处理程序来确定正在请求哪个系统调用。
  7. 处理程序运行。
  8. 内核将任何返回代码放入用户空间寄存器。
  9. 内核将执行转移回异常发生的地方。

Also at a more broader picture when the Kernel Thread is being executed I am assuming that the "OS region" on the RAM will be used to house the pages which are executing the System Call.

页面不执行任何操作 :) 通常,在 Linux 中,任何映射到 0xC0000000 以上的地址都属于内核。

Again looking at it from a different angle (Hope your still with me) finally I am assuming that the corresponding Kernel Thread is being handled by the CPU Scheduler where in a context switch would have happened from the User Level Thread to the corresponding Kernel Level Thread when the fopen System Call was being answered.

有了抢占式内核,线程实际上就不会受到歧视。据我了解,创建新线程并不是为了为系统调用提供服务 - 它只是在请求系统调用的同一线程中运行,内核模式除外。

这意味着可以像任何其他线程一样调度处于内核模式服务系统调用的线程。因此,这就是您在为内核开发时听到“用户空间上下文”的地方。这意味着它在用户模式线程上以内核模式执行。

解释这个有点困难,所以我希望我没弄错。

关于Linux 系统调用流程序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15917544/

相关文章:

linux - 在 shell 脚本中使用的持久非交互式 FTP session

c - 错误 : could not insert module. 模块中的未知符号

linux - usb_serial_register 函数的头文件?

ubuntu - 如何在 Ubuntu VPS 上安装 FreeBSD?

architecture - DMA 与中断驱动的 I/O

linux - 段错误 debian 8 golang

linux - 如何在 linux 终端中运行二进制可执行文件

linux - 使用 $ - x 时我们在汇编中减去多少位(或字节)

Linux用户空间线程、内核线程、轻量级进程

linux - 内核空间内存布局