所有Unix内核都是可重入的:内核中可能正在执行多个进程 模式同时。如何在代码中实现这种效果?我应该如何处理许多进程在内核模式下调用系统调用的情况?
答案 0 :(得分:1)
[编辑 - 术语“可重入”用于几种不同的意义。这个答案使用了基本的“多个上下文可以同时执行相同的代码”。这通常适用于单个例程,但可以扩展为应用于一组协作例程,通常是共享数据的例程。这种情况的一个极端情况是应用于完整的程序 - Web服务器或操作系统。如果Web服务器一次只能处理一个客户端,则可能被视为不可重入。 (呃!)如果一次只有一个进程/线程/处理器可以执行内核代码,则操作系统内核可能被称为非可重入。
在向多处理器系统过渡期间发生的操作系统。许多人经历了从单一处理器编写到单一锁定保护一切(即不可重入)的缓慢过渡,通过更精细和更细粒度锁定的各个阶段。 IIRC,linux终于摆脱了“大内核锁定”。版本2.6.37 - 但在此之前它已经很久了,只是保护尚未转换为多处理实现的残余。
本答案的其余部分是根据个人惯例而非完整程序编写的。]
如果您在用户空间,则无需执行任何操作。你可以调用你想要的任何系统调用,并且正确的事情发生。
所以我假设你在询问内核中的代码。
从概念上讲,这很简单。当多个线程调用相同的子例程时,它也与用户空间中的多线程程序中发生的情况非常相似。 (我们假设它是一个C程序 - 其他语言可能有不同的命名机制。)
当系统调用实现使用自动(堆栈)变量时,它有自己的副本 - 重新入门没问题。当需要使用全局数据时,它通常需要使用某种锁定 - 所需的特定锁定取决于它所使用的特定数据,以及它对该数据的作用。
这一切都非常通用,所以也许一个例子可能有所帮助。
假设系统调用想要修改进程的某些属性。该过程由struct task_struct
表示,tasklist_lock
是各种链接列表的成员。这些链接列表受tasklist_lock
保护。您的系统调用获取const
,找到正确的进程,可能获得每个进程锁定控制它关心的字段,修改字段,并丢弃两个锁。
还有一个细节,即执行不同系统调用的进程的情况,这些进程不会相互共享数据。通过合理的实施,根本没有冲突。一个进程可以进入内核来处理其系统调用,而不会影响其他进程。我不记得具体看linux的实现,但我认为这是“合理的”。类似陷阱的异常处理程序,它在表中查找子程序以处理所请求的特定系统调用。该表实际上是{{1}},因此不需要锁定。