Dla klasy OS, obecnie muszę utworzyć kolejkę bezpieczną dla wątków w jądrze Linuksa, z którą współdziała się przy użyciu syscalls.Czy istnieją jakiekolwiek korzyści z używania semafora binarnego zamiast muteksu do wzajemnego wykluczania w krytycznej sekcji kolejki?
Teraz dla krytycznych sekcji mam wrażenie, że chciałbym użyć funkcji mutex_lock
i mutex_unlock
w nagłówku . Jednak powiedziano mi, że zamiast tego mogę użyć binarnego semafora z down_interruptible
i up
w nagłówku semaphore.h
i że będzie lepiej.
Czytałem przez Difference between binary semaphore and mutex: Z nim, rozumiem, że główną zaletą jest to, jak silnie mutex to egzekwuje prawo własności, i że korzyść z semafora jest to, że ponieważ nie wymusza własność można go użyć jako mechanizm synchronizacji między dwoma (wieloma?) różnymi wątkami.
Moje pytanie brzmi: jakie są zalety semafora binarnego, jeśli używasz go w dokładnie taki sam sposób jak muteks. Bardziej wyraźnie gdybym napisał:
down()
/* critical */
up()
w taki sam sposób, że zrobię
mutex_lock()
/* critical */
mutex_unlock()
Czy jest jakaś zaleta wydajność, ponieważ jest mniej bezpieczne niż mutex? Czy czegoś brakuje?
Oto niewielki fragment kodu, który chcę zrobić wątku bezpieczny, jeśli chcesz więcej kontekstu (to mój pierwszy C proj kiedykolwiek):
#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;
}
Czy Twoja kolejka będzie kiedykolwiek wymagać rekursywnego blokowania lub będzie musiała uporać się z priorytetową inwersją? –
Nie dla odwrócenia priorytetu, i jestem całkiem pewny, że nie będę potrzebował również rekursywnego blokowania. – m0meni
W tym momencie myślę, że sprowadza się to do wydajności. A jeśli chodzi o wydajność, najlepiej jest zrobić profil i zobaczyć, co się stanie. Mam przeczucie, że jeśli wykonają mniej więcej to samo, trzymam się muteksu, ale inni mogą mieć lepsze odpowiedzi na pewno. –