Linux系统调用流程序列

Vin*_*Pai 4 linux operating-system system-calls linux-kernel

我有一个关于Linux深入工作的问题.

假设在CPU中正在执行多线程进程.在这种情况下,我们将有一个在CPU上执行的线程.在更广泛的图片中,我们将属于Process的相应页面加载到RAM中以供执行.

让我们说线程进行系统调用.我对此之后的运作有点不清楚.中断将生成一个呼叫.我的一个问题是谁将接听这个电话?

让我们说系统有m:n用户级线程到内核级线程映射,我假设相应的内核级线程将回答此调用.

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

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

当内核线程正在执行时,我还假设RAM上的"OS区域"将用于容纳正在执行系统调用的页面.

再次从不同的角度看待它(希望你还在我身边)最后我假设相应的内核线程正在由CPU调度程序处理,在这里,从用户级线程到相应的内核级线程的上下文切换当fopen系统调用被回答时.

我已经做了很多假设,如果有人能够清除疑虑或者至少引导我朝着正确的方向前进,那绝对是太棒了.

tan*_*grs 7

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

让我们说线程进行系统调用.我对此之后的运作有点不清楚.中断将生成一个呼叫.我的一个问题是谁将接听这个电话?

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

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

我很确定它会切换到内核堆栈.如果使用用户空间堆栈,那么信息泄漏会有一些非常严重的安全问题.

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

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

所以,这个过程(大致)是:

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

当内核线程正在执行时,我还假设RAM上的"OS区域"将用于容纳正在执行系统调用的页面.

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

再次从不同的角度看待它(希望你还在我身边)最后我假设相应的内核线程正在由CPU调度程序处理,在这里,从用户级线程到相应的内核级线程的上下文切换当fopen系统调用被回答时.

使用抢占式内核,有效地不会区分线程.根据我的理解,不是为了服务系统调用而创建一个新线程 - 它只是在请求系统调用的同一个线程中运行,除了内核模式.

这意味着处于为系统调用提供服务的内核模式的线程可以与任何其他线程一样进行调度.因此,在开发内核时,您可以在这里听到"用户空间上下文".这意味着它在用户模式线程上以内核模式执行.

这有点难以解释,所以我希望我做对了.