对于操作系统类,我目前必须在 linux 内核中创建一个线程安全的队列,使用系统调用与之交互。
现在对于关键部分,我的直觉是我想在 mutex.h
header 中使用 mutex_lock
和 mutex_unlock
函数.但是,我被告知我可以在 semaphore.h
header 中使用带有 down_interruptible
和 up
的二进制信号量,并且它会变得更好。
我已通读 Difference between binary semaphore and mutex :从中,我了解到互斥锁的主要优点是它强制所有权的强度,而信号量的优点是由于它不强制所有权,您可以将它用作两个(多个?)不同的线程。
我的问题是,如果您以与互斥锁完全相同的方式使用二进制信号量,它有哪些优势。如果我写得更明确:
down()
/* critical */
up()
和我一样
mutex_lock()
/* critical */
mutex_unlock()
是否有一些性能优势,因为它不如互斥体安全?我错过了什么吗?
如果您需要更多上下文(这是我的第一个 C 项目),这里有一小段代码,我想使其成为线程安全的代码:
#define MESSAGE_MAX_SIZE 512
typedef struct list_head list_node;
/* Create message struct */
typedef struct {
size_t size;
list_node node;
char data[MESSAGE_MAX_SIZE];
} Message;
/* Create the linked list queue with dummy head */
struct {
size_t size;
list_node head;
} my_q = { 0, LIST_HEAD_INIT(my_q.head) };
/*
Adds a new item to the tail of the queue.
@data: pointer to data to add to list
@len: size of the data
*/
asmlinkage long sys_enqueue(const void __user *data, long len) {
long res = 0;
Message *msg = 0;
if (len < 0) return EINVAL;
if (len > MESSAGE_MAX_SIZE) return E2BIG;
msg = kmalloc(sizeof(Message), GFP_KERNEL);
if (msg == 0) return ENOMEM;
res = copy_from_user(msg->data, data, len);
if (res != 0) return EFAULT;
/* Start Critical Section */
my_q.size++;
list_add_tail(&msg->node, &my_q.head);
/* End Critical Section */
return 0;
}
最佳答案
在缺乏经验证据的情况下,我会引用Linux Kernel Development这本书
It (i.e. mutex) behaves similar to a semaphore with a count of one, but it has a simpler interface, more efficient performance, and additional constraints on its use.
此外,还有许多适用于互斥量但不适用于信号量的约束。持有互斥锁时,诸如进程之类的东西无法退出。此外,如果启用了 CONFIG_DEBUG_MUTEXES
内核选项,则所有适用于互斥锁的约束都将通过调试检查来确保。
因此,除非有充分的理由不使用互斥锁,否则应该首选互斥锁。
关于c - 在队列的关键部分使用二进制信号量而不是互斥锁进行互斥有什么好处吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40291858/