系统调用是否完全在软件中断处理程序中执行?

时间:2012-06-08 11:35:03

标签: kernel system-calls interrupt

系统调用是否完全在软件中断处理程序的上下文中执行?

我的意思是,一些像read()这样的系统调用可能需要很长时间才能返回,而ISR的执行时间应该非常短。系统调用是否已卸载到其他线程?这有什么作用?

[对任何内核的引用都很好]

3 个答案:

答案 0 :(得分:3)

请阅读此系统调用通常如何工作的引用文本:

  

系统调用处理程序在用户程序启动时获得控制权   系统调用。系统调用处理程序更改保护域   从呼叫者保护域,用户到系统呼叫保护   域,内核和切换到受保护的堆栈。

     

系统调用处理程序然后调用支持系统的函数   呼叫。加载程序维护当前定义的系统的表   呼吁这个目的。

     

系统调用在调用进程中运行,但有更多   特权比调用过程。这是因为保护   域已从用户更改为内核。

     

系统调用函数返回系统调用处理程序   已经完成了它的运作。系统调用处理程序然后恢复   进程状态并返回用户程序。

现在,在系统调用期间,有两种类型的内核涉及上下文切换。 抢占式和非抢占式内核(粗略地说;因为这有时也适用于执行关键代码段的线程/进程)。

前者在RTOS(实时操作系统)中很常见,而后者在我们所知的最常见的操作系统中很常见。
在抢占式内核中,允许调度程序选择退出执行系统调用的线程,以获得具有更高优先级的线程的优先权。 后者不允许这种先发制人,如;如果一个线程当前正在执行系统调用,那么所有其他线程应该等到它完成内核模式工作。

总结一下,通常在非RT系统中,如果线程执行系统调用,它应该在调度之前完成其工作。

现在注意一些事情,某些系统调用可能会阻止
这是什么意思?这意味着他们将停止直到中断发生,然后他们将重新执行,直到他们完成他们的工作。
一个例子是read(),它将阻塞直到用户请求的数据准备好;同时其他线程可以被调度运行但是一旦中断到达read()它就会再次开始运行而没有人可以发送它(再次,只在非抢先的环境中),直到它返回到用户着陆结果。 / p>

答案 1 :(得分:3)

系统调用 ISR 内的大多数内核上运行。快速浏览一下以前的Linux版本,您会注意到int $Ox80调用内核。从内核开发的角度来看,这个解决方案可能是最简单的,它有一个很大的缺点:只要运行ISR;中断被禁用。禁用中断太长时间很糟糕,因为很明显你的系统不会被动(它会延迟外部事件,不会按时重新安排,......)。

Preemption ,正如Adel在他的answer中所解释的那样,这是一个聪明的解决方案。但是每当内核因为不可用的资源而选择抢占一个线程时,它通常已经花了很多时间禁用了中断。

  

是否将系统调用卸载到其他线程?

你是对的。 Interrupt-threads 和/或线程内核是一种更智能的解决方案。像Solaris和Mac OS X这样的内核更喜欢使用非常简单的ISR来唤醒高优先级的中断线程。因此,ISR被减少到最小处理,并且系统在禁用中断的情况下运行的时间大大减少。由于这些中断线程具有高优先级,因此它们很可能在ISR返回时运行。什么是好的是中断将再次启用,因此更高优先级的工作不会被延迟。使用线程内核,例如Linux在其最新版本中,可以在内核中完成多项任务,尽管有一个块,但其他进程仍然可以进入内核。

希望这有帮助!

答案 2 :(得分:1)

首先,Linux中使用的一些术语。在Linux中,内核可以在多个上下文中运行:

  • 进程上下文(用户上下文):内核代表用户 - 空间进程运行,该进程已调用系统调用,正在读取{{1文件,...
  • 中断上下文:内核正在响应某些中断而运行。
  • 原子上下文:由于某种原因,内核无法休眠(阻塞):可能是在中断上下文中运行,或者某些自旋锁被锁定,...
  • 非原子背景:很明显,我希望。

系统调用在启用中断的情况下开始执行(因为它们被显式重新启用(例如:使用x86的/proc时),或者因为它们从未被禁用(例如:使用x86的陷阱门时,Linux 'sysenter确实))。因此,内核可以在执行系统调用时被中断中断。

某些系统调用可能会睡眠(阻塞),等待某些事情。在这种情况下,内核可以切换到另一个任务(进程/线程),稍后将唤醒睡眠任务。

在非抢占式内核中,任务不能抢占进程上下文中正在运行的另一个任务(即实际工作,而不是休眠)。在抢占式内核中,优先级较高的任务可以抢占在非原子进程上下文中运行的低优先级任务。这可以防止高上下文切换延迟,例如:音频程序可能需要非常频繁地调度,抢占式内核可以防止其他任务的繁重系统调用处理搞乱(否则会导致音频伪像,点击......)