偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.
全部博文(1750)
分类: LINUX
2009-02-06 17:25:46
struct semaphore sem; |
void sema_init (struct semaphore *sem, int val); |
void init_MUTEX (struct semaphore *sem); |
void init_MUTEX_LOCKED (struct semaphore *sem); |
void down(struct semaphore * sem); |
int down_interruptible(struct semaphore * sem); |
int down_trylock(struct semaphore * sem); |
void up(struct semaphore * sem); |
spinlock_t spin; |
spin_lock_init(lock) |
spin_lock(lock) |
spin_trylock(lock) |
spin_unlock(lock) |
该宏释放自旋锁lock,它与spin_trylock或spin_lock配对使用;
除此之外,还有一组自旋锁使用于中断情况下的API。
下面进入对并发控制的实战。首先,在globalvar的驱动程序中,我们可以通过信号量来控制对int global_var的并发访问,下面给出源代码:
#include #include #include #include #include MODULE_LICENSE("GPL"); #define MAJOR_NUM 254 static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*); static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*); struct file_operations globalvar_fops = { read: globalvar_read, write: globalvar_write, }; static int global_var = 0; static struct semaphore sem; static int __init globalvar_init(void) { int ret; ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops); if (ret) { printk("globalvar register failure"); } else { printk("globalvar register success"); init_MUTEX(&sem); } return ret; } static void __exit globalvar_exit(void) { int ret; ret = unregister_chrdev(MAJOR_NUM, "globalvar"); if (ret) { printk("globalvar unregister failure"); } else { printk("globalvar unregister success"); } } static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off) { //获得信号量 if (down_interruptible(&sem)) { return - ERESTARTSYS; } //将global_var从内核空间复制到用户空间 if (copy_to_user(buf, &global_var, sizeof(int))) { up(&sem); return - EFAULT; } //释放信号量 up(&sem); return sizeof(int); } ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off) { //获得信号量 if (down_interruptible(&sem)) { return - ERESTARTSYS; } //将用户空间的数据复制到内核空间的global_var if (copy_from_user(&global_var, buf, sizeof(int))) { up(&sem); return - EFAULT; } //释放信号量 up(&sem); return sizeof(int); } module_init(globalvar_init); module_exit(globalvar_exit); |
#include #include #include #include #include MODULE_LICENSE("GPL"); #define MAJOR_NUM 254 static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*); static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*); static int globalvar_open(struct inode *inode, struct file *filp); static int globalvar_release(struct inode *inode, struct file *filp); struct file_operations globalvar_fops = { read: globalvar_read, write: globalvar_write, open: globalvar_open, release: globalvar_release, }; static int global_var = 0; static int globalvar_count = 0; static struct semaphore sem; static spinlock_t spin = SPIN_LOCK_UNLOCKED; static int __init globalvar_init(void) { int ret; ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops); if (ret) { printk("globalvar register failure"); } else { printk("globalvar register success"); init_MUTEX(&sem); } return ret; } static void __exit globalvar_exit(void) { int ret; ret = unregister_chrdev(MAJOR_NUM, "globalvar"); if (ret) { printk("globalvar unregister failure"); } else { printk("globalvar unregister success"); } } static int globalvar_open(struct inode *inode, struct file *filp) { //获得自选锁 spin_lock(&spin); //临界资源访问 if (globalvar_count) { spin_unlock(&spin); return - EBUSY; } globalvar_count++; //释放自选锁 spin_unlock(&spin); return 0; } static int globalvar_release(struct inode *inode, struct file *filp) { globalvar_count--; return 0; } static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off) { if (down_interruptible(&sem)) { return - ERESTARTSYS; } if (copy_to_user(buf, &global_var, sizeof(int))) { up(&sem); return - EFAULT; } up(&sem); return sizeof(int); } static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off) { if (down_interruptible(&sem)) { return - ERESTARTSYS; } if (copy_from_user(&global_var, buf, sizeof(int))) { up(&sem); return - EFAULT; } up(&sem); return sizeof(int); } module_init(globalvar_init); module_exit(globalvar_exit); |