信号量需要系统调用吗?

Do semaphores require syscalls?

我正在通过过去的考试准备有关操作系统的考试。它主要是关于 Unix 系统,C 编程语言,它提到了很多 POSIX,所以最好在这里问这个问题。

问题是:

Give three disadvantages of simple spinlocks and/or semaphores. Explain how the respective other mechanism improves on the problem.

给出的 3 个缺点之一 + 解释是这样的:

Semaphores require a system call even when the thread may proceed immediately. (0.5 P) Spinlocks on the other hand can be implemented completely in userspace and do not require syscalls. They are very efficient for short wait times. (0.5 P)

为什么信号量需要系统调用?它们必须在内核 space 中吗?他们需要执行特权指令吗?

单处理器系统和多处理器系统都需要考虑。

一些历史背景会让事情变得更清楚。在 POSIX IPC 出现之前,信号量最初是 System V 进程间通信包 (System V IPC) 的一部分。这些名称可能会为您提供有关事物发展方向的线索;最初的用例是合作进程共享的锁。 (我 99.99% 确定 IPC 比线程早了很长一段时间。)

POSIX 信号量与进程或线程一起工作,因此涉及 OS。上下文在这里很重要,因为答案显然是关于标准信号量实现,而不是信号量的抽象概念。

是的,信号量需要系统调用,除非在非常特殊的情况下。信号量必须能够等待其他竞争者释放资源。等待需要系统调用。

如果锁上的竞争者可以访问共享内存 space 并且他们相互信任以遵守信号量协议(当锁位于同一进程的线程之间时,这种情况最常见),那么锁并不总是需要系统调用:它可以使用非特权处理器指令来检查和更改锁状态。这允许在锁空闲时获取锁,并释放锁,但等待锁空闲是另一回事。

自旋锁一直忙(“自旋”)直到锁空闲。如果争用锁的线程在不同的 CPU 上为 运行 所知,这可能是一个有效的策略。如果线程可能 运行 在同一个 CPU 上,则等待锁的线程需要允许另一个线程 运行,因此它需要让步。使用用户态线程,无需系统调用即可完成此操作。

信号量应该休眠直到锁准备就绪。在现实世界中,旋转睡觉几乎是不可接受的。休眠几乎总是需要系统调用:内核将等待线程移出调度程序的就绪列表并移至信号量对象的等待列表。