【发布时间】:2012-06-12 11:12:19
【问题描述】:
系统调用是否完全在软件中断处理程序的上下文中执行?
我的意思是,像 read() 这样的一些系统调用可能需要很长时间才能返回,这违反了 ISR 的执行时间应该非常短的策略。系统调用是否已卸载到其他线程?它是如何工作的?
[对任何内核的引用都可以]
【问题讨论】:
标签: kernel system-calls interrupt
系统调用是否完全在软件中断处理程序的上下文中执行?
我的意思是,像 read() 这样的一些系统调用可能需要很长时间才能返回,这违反了 ISR 的执行时间应该非常短的策略。系统调用是否已卸载到其他线程?它是如何工作的?
[对任何内核的引用都可以]
【问题讨论】:
标签: kernel system-calls interrupt
请阅读系统调用正常工作方式的引用文本:
当用户程序启动一个 系统调用。系统调用处理程序更改保护域 从调用者保护域、用户到系统调用保护 域、内核和切换到受保护的堆栈。
系统调用处理程序然后调用支持系统的函数 称呼。 loader 维护一个当前定义系统的表 为此目的而呼吁。
系统调用在调用进程中运行,但有更多 权限高于调用进程。这是因为保护 域已从用户更改为内核。
系统调用函数在执行时返回到系统调用处理程序 已执行其操作。系统调用处理程序然后恢复 进程的状态并返回给用户程序。
现在,关于系统调用期间的上下文切换,有两种类型的内核。 抢占式和非抢占式内核(粗略地说;因为这有时也适用于执行关键代码部分的线程/进程)。
前者在 RTOS(实时操作系统)中很常见,而后者在我们所知道的最常见的操作系统中很常见。
在抢占式内核中,调度程序可以选择退出执行系统调用的线程,以支持具有更高优先级的线程。
后者不允许这种抢占,如;如果一个线程当前正在执行系统调用,所有其他线程都应该等到它完成其内核模式工作。
总结一下,通常在非RT系统中,如果一个线程执行系统调用,它应该在被调度之前完成它的工作。
现在请注意,某些系统调用可能会阻塞!
这是什么意思?这意味着它们将停止直到发生中断,然后它们将重新执行直到完成工作。
一个例子是 read(),它会阻塞直到用户请求的数据准备好;同时可以安排其他线程运行,但是一旦中断到达该 read() 它将再次开始运行,并且没有人可以调度它(再次,仅在非抢占式环境中),直到它返回给用户登陆结果。
【讨论】:
系统调用在ISR内的大多数内核上运行。快速浏览一下以前的 Linux 版本,您会注意到 int $Ox80 调用内核。从内核开发的角度来看,这个可能是最简单的解决方案有一个很大的缺点:只要运行 ISR;中断被禁用。禁用中断太长时间很糟糕,因为很明显您的系统不会反应(它会延迟外部事件,它不会按时重新安排......)。
抢占,正如 Adel 在他的 answer 中解释的那样,这是一个聪明的解决方案。但是每当内核因为资源不可用而选择抢占线程时,它通常已经花费了很多时间来禁用中断。
系统调用是否被卸载到其他线程?
你是对的。 Interrupt-threads 和/或 线程内核 是一个更智能的解决方案。像 Solaris 和 Mac OS X 这样的内核更喜欢有非常简单的 ISR,它只是唤醒高优先级的中断线程。因此,ISR 被减少到最少的处理,并且系统在中断禁用的情况下运行的时间大大减少。因为这些中断线程具有高优先级,它们很可能在 ISR 返回时运行。好的是中断将再次启用,因此不会延迟更高优先级的工作。使用线程化内核,例如最近发布的 Linux,可以在内核内完成多项操作,并且尽管有一个阻塞,其他进程仍然可以进入内核。
希望对您有所帮助!
【讨论】:
首先,Linux 中使用的一些术语。在 Linux 中,内核可以在多种环境中运行:
/proc文件,...系统调用在启用中断的情况下开始执行(或者因为它们被明确地重新启用(例如:当使用 x86 的 sysenter 时),或者因为它们根本没有被禁用(例如:当使用 x86 的陷阱门时,Linux'@ 987654323@ 确实))。因此,内核在执行系统调用时可能会被中断中断。
一些系统调用可能会休眠(阻塞),等待某些东西。在这种情况下,内核可以切换到另一个任务(进程/线程),休眠的任务稍后会被唤醒。
在非抢占式内核中,一个任务不能抢占另一个在进程上下文中正在运行(即实际工作,而不是休眠)的任务。在抢占式内核中,较高优先级的任务可以抢占在非原子进程上下文中运行的较低优先级的任务。这可以防止高上下文切换延迟,例如:音频程序可能需要非常频繁地调度,抢占式内核可以防止其他任务的繁重系统调用处理与此混淆(否则可能导致音频伪影、点击……)
【讨论】: