Для класса ОС в настоящее время мне нужно создать потокобезопасную очередь в ядре linux, с которой один взаимодействует с использованием системных вызовов.Существуют ли какие-либо преимущества в использовании двоичного семафора вместо мьютекса для взаимного исключения в критическом разделе очереди?
Теперь для критических разделов мое чувство кишки состоит в том, что я хотел бы использовать функции и mutex_unlock
в заголовке mutex.h
. Однако мне сказали, что вместо этого я мог бы использовать двоичный семафор с down_interruptible
и up
в заголовке semaphore.h
, и было бы лучше.
Я прочитал 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;
}
Будет ли ваша очередь требовать рекурсивной блокировки или иметь дело с инверсией приоритета? –
Нет для инверсии приоритета, и я уверен, что мне также не понадобится рекурсивная блокировка. – m0meni
Тогда в этот момент я думаю, что это сводится к производительности. И когда это производительность, самое лучшее, что нужно сделать, это профилировать и то, и другое. Я чувствую, что если они будут работать примерно одинаково, я бы придерживался мьютекса, но другие, возможно, получили бы более точные ответы. –