Linux 系统调用的内部结构
Posted
技术标签:
【中文标题】Linux 系统调用的内部结构【英文标题】:Internals of a Linux system call 【发布时间】:2011-01-18 23:09:54 【问题描述】:当线程通过引发中断 80 进行系统调用时(详细)会发生什么? Linux 对线程的堆栈和其他状态做了什么工作?对处理器进行了哪些更改以使其进入内核模式?运行中断处理程序后,如何将控制权恢复到调用进程?
如果系统调用不能快速完成怎么办:例如从磁盘读取。中断处理程序如何放弃控制权,以便处理器在加载数据时执行其他操作,然后如何再次获得控制权?
【问题讨论】:
我想一个很好的练习是检查源代码。也许从内核 0.0.1 开始并向上移动。 现在还有其他几种方法可以进行系统调用。您可以对特殊映射的内存页进行常规函数调用。您可以使用 SYSENTER 或 SYSCALL 指令。 【参考方案1】:这应该可以帮助那些寻求答案的人在执行syscall
指令时会发生什么,该指令将控制权转移到内核(用户模式到内核模式)。这是基于 x86_64 架构的。
https://0xax.gitbooks.io/linux-insides/content/SysCall/syscall-2.html
【讨论】:
【参考方案2】:回答问题的最后一部分——如果系统调用需要休眠,内核会做什么——
在系统调用之后,内核仍然在逻辑上运行在进行系统调用的同一任务的上下文中 - 它只是处于内核模式而不是用户模式 - 它不是一个单独的线程并且大多数系统调用不会调用来自另一个任务/线程的逻辑。发生的情况是系统调用调用 wait_event 或 wait_event_timeout 或其他一些等待函数,它将任务添加到等待某事的任务列表中,然后使任务进入睡眠状态,从而改变其状态,并调用 schedule() 放弃当前的 CPU。
在此之后任务无法再次运行,直到它被唤醒,通常由另一个任务(内核任务等)或中断处理程序调用唤醒*函数,该函数将唤醒正在等待该特定事件的任务,这意味着调度器将很快再次调度它们。
值得注意的是,用户空间任务(即线程)只是一种类型的任务,内核内部还有一些其他任务也可以工作 - 这些是内核线程和下半部分处理程序/tasklet/任务队列等. 不属于任何特定用户空间进程的工作(例如网络处理,例如响应 ping)在这些中完成。与中断不同(不应调用调度程序),这些任务可以进入睡眠状态
【讨论】:
【参考方案3】:一个堆栈溢出答案中的内核模式速成课程
好问题! (面试题?)
当一个 线程通过引发系统调用 中断 80?
int $80 操作有点像函数调用。 CPU“采取陷阱”并在内核模式下的已知地址处重新启动,通常也使用不同的 MMU 模式。内核将保存许多寄存器,尽管它不必保存程序不希望普通函数调用保存的寄存器。
Linux 对 线程的堆栈和其他状态?通常,操作系统会保存 ABI 承诺在过程调用期间不会更改的寄存器。堆栈将保持不变;内核将在每线程内核堆栈而不是每线程用户堆栈上运行。自然有些状态会发生变化,否则就没有理由进行系统调用。
对 处理器将其置于内核模式?这通常是完全自动的。 CPU 通常有一个软件中断指令,有点像函数调用操作。它将导致在受控条件下切换到内核模式。通常,CPU 会更改某种 PSW 保护位,保存旧的 PSW 和 PC,从众所周知的陷阱向量地址开始,也可能切换到不同的内存管理保护和映射安排。
运行中断处理程序后, 控制权如何恢复到 调用进程?通常会有某种“从中断返回”或“从陷阱返回”指令,其行为有点像复杂的函数返回指令。一些 RISC 处理器自动执行的操作很少,并且需要特定的代码来执行返回,而像 x86 这样的一些 CISC 处理器具有(从未真正使用过的)指令,这些指令将执行架构手册伪代码页面中记录的数十个操作,以进行能力调整。
如果系统调用不能 快速完成:例如读自 磁盘。中断处理程序如何 放弃控制权,使 处理器可以做其他事情,而 正在加载数据,它是如何加载的 然后再次获得控制权?内核本身是线程化的,就像线程化的用户程序一样。它只是切换堆栈(线程)并在其他人的进程上工作一段时间。
【讨论】:
好答案。不是面试问题——我只是感兴趣!最后一点,系统调用是自愿放弃执行还是被某些硬件定时器中断打断?谢谢。 内核通常会在系统调用上稳定工作,但如果它需要 I/O 操作,那么这些可能是中断驱动的。因此,内核将启动 I/O 操作,然后切换到另一个进程(非常类似于线程切换,如前所述),直到中断到来。内核会注意到系统调用 PID 再次可运行。它将把它放在运行队列中,然后当调度程序决定是时候让新人运行时,它就会退出队列。通常,无论如何它是唯一可运行的进程。 +1 - 这些是使 SO ......好吧...... SO :) 的答案类型【参考方案4】:http://tldp.org/LDP/khg/HyperNews/get/syscall/syscall86.html
【讨论】:
这是特定于 x86 的答案,因此太有限而不能被认为是一般性的。以上是关于Linux 系统调用的内部结构的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核Linux 内核体系架构 ( 硬件层面 | 内核空间 | 用户空间 | 内核态与用户态切换 | 系统调用 | 体系结构抽象层 )