Using Spinlocks and Mutexes
Spinlocks and mutexes are two fundamental synchronization primitives used in kernel development to protect shared data from concurrent access. A spinlock is a lightweight lock where a thread repeatedly checks if the lock is available, "spinning" in a tight loop until it can acquire the lock. This is efficient in short, non-blocking critical sections, especially in contexts where sleeping is not allowed, such as interrupt handlers. A mutex (short for "mutual exclusion") is a heavier-weight lock that can put the thread to sleep if the lock is not available, making it suitable for longer critical sections where sleeping is allowed, such as process context.
spinlock_interrupt_example.c
12345678910111213141516171819202122232425262728293031323334353637#include <linux/module.h> #include <linux/kernel.h> #include <linux/interrupt.h> #include <linux/spinlock.h> static spinlock_t my_lock; static int shared_data = 0; irqreturn_t my_interrupt_handler(int irq, void *dev_id) { unsigned long flags; // Acquire spinlock and save interrupt state spin_lock_irqsave(&my_lock, flags); shared_data++; spin_unlock_irqrestore(&my_lock, flags); return IRQ_HANDLED; } static int __init spinlock_example_init(void) { spin_lock_init(&my_lock); // Normally you would request an IRQ here and register my_interrupt_handler pr_info("Spinlock interrupt example loaded\n"); return 0; } static void __exit spinlock_example_exit(void) { pr_info("Spinlock interrupt example unloaded\n"); } module_init(spinlock_example_init); module_exit(spinlock_example_exit); MODULE_LICENSE("GPL");
You should use a spinlock, as shown in the code above, when you need to protect shared data in interrupt context or any context where sleeping is not allowed. Spinlocks are designed for short, quick operations and do not cause the current context to sleep, making them ideal for interrupt handlers. Mutexes, on the other hand, can sleep and are only safe to use in process context, where sleeping is permitted. If you try to use a mutex in an interrupt handler, you may cause a deadlock or crash, since mutexes may block the current context.
mutex_process_example.c
1234567891011121314151617181920212223242526272829303132333435363738// mutex_process_example.c #include <linux/module.h> #include <linux/kernel.h> #include <linux/mutex.h> #include <linux/fs.h> static DEFINE_MUTEX(my_mutex); static int shared_resource = 0; ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t ret = 0; if (mutex_lock_interruptible(&my_mutex)) return -ERESTARTSYS; shared_resource++; mutex_unlock(&my_mutex); ret = count; return ret; } static int __init mutex_example_init(void) { pr_info("Mutex process example loaded\n"); return 0; } static void __exit mutex_example_exit(void) { pr_info("Mutex process example unloaded\n"); } module_init(mutex_example_init); module_exit(mutex_example_exit); MODULE_LICENSE("GPL");
Bedankt voor je feedback!
Vraag AI
Vraag AI
Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.
Geweldig!
Completion tarief verbeterd naar 3.85
Using Spinlocks and Mutexes
Veeg om het menu te tonen
Spinlocks and mutexes are two fundamental synchronization primitives used in kernel development to protect shared data from concurrent access. A spinlock is a lightweight lock where a thread repeatedly checks if the lock is available, "spinning" in a tight loop until it can acquire the lock. This is efficient in short, non-blocking critical sections, especially in contexts where sleeping is not allowed, such as interrupt handlers. A mutex (short for "mutual exclusion") is a heavier-weight lock that can put the thread to sleep if the lock is not available, making it suitable for longer critical sections where sleeping is allowed, such as process context.
spinlock_interrupt_example.c
12345678910111213141516171819202122232425262728293031323334353637#include <linux/module.h> #include <linux/kernel.h> #include <linux/interrupt.h> #include <linux/spinlock.h> static spinlock_t my_lock; static int shared_data = 0; irqreturn_t my_interrupt_handler(int irq, void *dev_id) { unsigned long flags; // Acquire spinlock and save interrupt state spin_lock_irqsave(&my_lock, flags); shared_data++; spin_unlock_irqrestore(&my_lock, flags); return IRQ_HANDLED; } static int __init spinlock_example_init(void) { spin_lock_init(&my_lock); // Normally you would request an IRQ here and register my_interrupt_handler pr_info("Spinlock interrupt example loaded\n"); return 0; } static void __exit spinlock_example_exit(void) { pr_info("Spinlock interrupt example unloaded\n"); } module_init(spinlock_example_init); module_exit(spinlock_example_exit); MODULE_LICENSE("GPL");
You should use a spinlock, as shown in the code above, when you need to protect shared data in interrupt context or any context where sleeping is not allowed. Spinlocks are designed for short, quick operations and do not cause the current context to sleep, making them ideal for interrupt handlers. Mutexes, on the other hand, can sleep and are only safe to use in process context, where sleeping is permitted. If you try to use a mutex in an interrupt handler, you may cause a deadlock or crash, since mutexes may block the current context.
mutex_process_example.c
1234567891011121314151617181920212223242526272829303132333435363738// mutex_process_example.c #include <linux/module.h> #include <linux/kernel.h> #include <linux/mutex.h> #include <linux/fs.h> static DEFINE_MUTEX(my_mutex); static int shared_resource = 0; ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t ret = 0; if (mutex_lock_interruptible(&my_mutex)) return -ERESTARTSYS; shared_resource++; mutex_unlock(&my_mutex); ret = count; return ret; } static int __init mutex_example_init(void) { pr_info("Mutex process example loaded\n"); return 0; } static void __exit mutex_example_exit(void) { pr_info("Mutex process example unloaded\n"); } module_init(mutex_example_init); module_exit(mutex_example_exit); MODULE_LICENSE("GPL");
Bedankt voor je feedback!