当前信号量的实现是如何工作的?它使用自旋锁或信号吗?
如果使用信号,调度程序如何知道调用哪一个?
它在用户空间中是如何工作的?内核锁定建议使用自旋锁,但用户空间不建议使用。那么信号量在用户空间和内核空间的实现是否不同?
当前信号量的实现是如何工作的?它使用自旋锁或信号吗?
如果使用信号,调度程序如何知道调用哪一个?
它在用户空间中是如何工作的?内核锁定建议使用自旋锁,但用户空间不建议使用。那么信号量在用户空间和内核空间的实现是否不同?
使用开源的力量 - 只需查看源代码。
内核空间信号量定义为
struct semaphore {
raw_spinlock_t lock;
unsigned int count;
struct list_head wait_list;
};
lock
用于保护count
和wait_list
。
在信号量上等待的所有任务都驻留在wait_list
. 当信号量上升时,一个任务被唤醒。
用户空间信号量应该依赖于与信号量相关的系统调用,内核提供。用户空间信号量的定义是:
/* One semaphore structure for each semaphore in the system. */
struct sem {
int semval; /* current value */
int sempid; /* pid of last operation */
spinlock_t lock; /* spinlock for fine-grained semtimedop */
struct list_head sem_pending; /* pending single-sop operations */
};
内核使用与内核空间信号量类似的用户空间信号量的定义。sem_pending
是等待过程的列表以及一些附加信息。
我应该再次强调,内核空间信号量和用户空间信号量都没有使用自旋锁来等待锁定。自旋锁包含在这两个结构中只是为了保护结构成员免受并发访问。结构修改后,自旋锁被释放,任务停留在列表中,直到被唤醒。
此外,自旋锁不适合等待来自另一个线程的某些事件。在获取自旋锁之前,内核禁用抢占。因此,在这种情况下,在单处理器机器上,自旋锁永远不会被释放。
我还应该注意到,用户空间信号量虽然代表用户空间服务,但在内核空间中执行。
PS 内核空间信号量的源代码位于include/linux/semaphore.h和kernel/semaphore.c中,用户空间位于ipc/sem.c