30 spinlock_t自旋锁和semaphore信号量

来源:互联网 发布:人工智能在线观看 编辑:程序博客网 时间:2024/05/18 19:41

自旋锁是一直循环检查, 直到锁上为止(锁不上也不会让进程休眠)。自旋锁只有两种状态,可锁上和锁不上. 锁上后确保执行的代码为原子操作, 直到解锁为止. 注意不能长时间锁上自旋锁, 不能在临界区里休眠.

spinlock_t 自旋锁  #include <linux/spinlock.h>spinlock_t  mylock;spin_lock_init(&mylock);  //初始化自旋锁, 初始化过后是可锁上状态.上锁:       spin_lock(&mylock);  //spin_lock_irq 不让中断打断执行    ...    保护执行的代码         //临界区, 在临界区里不能执行会休眠的代码    ...    spin_unlock(&mylock); //spin_unlock_irq

当自旋锁锁上后, 拥有此锁的进程不能进入休眠. 自旋锁只适用于保护执行时间较短的代码.

//////
如用于前面的计数例子.
test.c

#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <asm/current.h>#include <linux/spinlock.h>int count = 0;spinlock_t mylock;ssize_t myread(struct file *fl, char __user *buf, size_t len, loff_t *off){    printk("pid = %d, %s, count = %d\n", current->pid, current->comm, count);    return 0;}ssize_t mywrite(struct file *fl, const char __user *buf, size_t len, loff_t *off){    spin_lock(&mylock);    count++;  //保护对count变量的操作.    spin_unlock(&mylock);    return len; //表示写操作成功}struct file_operations fops = {    .owner = THIS_MODULE,    .read = myread,    .write = mywrite,};struct miscdevice mymdev = {    .minor = MISC_DYNAMIC_MINOR,    .name = "mymdev",    .fops = &fops,};static int __init test_init(void){    spin_lock_init(&mylock);    return misc_register(&mymdev);}static void __exit test_exit(void){    misc_deregister(&mymdev);}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");

//////////////////////////////////////////////////////////////
信号量, 当锁不上时, 当前进程会进入睡眠状态, 直到被up唤醒为止.
信号量可用于生产/消费的模型. 信号量的状态可有多种,一个锁可被锁上多次, 只要有资源都可以上锁.

#include <linux/semaphore.h>struct semaphore {    spinlock_t   lock;  //用于保护对count, wait_list的操作    unsigned int     count; //当锁上时,count的值减1. 当解锁时,count的值加1. 如count的值为10表示此锁可被锁上10次.               //count的值当大于0时表示可锁, 等于0时表示没有资源分配(不可以锁上,再锁的话, 进程会被安排进入休眠)     struct list_head wait_list; //等待操作进程的链表};void sema_init(struct semaphore *sem, int val);//初始化信号量,count成员的值设为valvoid down(struct semaphore *sem); //上锁 count--int down_interruptible(struct semaphore *sem); //能被中断信号打断的上锁int down_trylock(struct semaphore *sem);int down_timeout(struct semaphore *sem, long jiffies); // down_timeout(&sem, HZ);void up(struct semaphore *sem); //解锁  count++

////////////
如用信号量实现生产/消费的模型. 一个进程读取驱动里的数据(消费), 另一个进程写入数据到驱动(生产).在驱动源码里把写入的数据用内核存放起来,当读进程获取数据后,还需从内核链表里移除数据.

test.c

#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <asm/current.h>#include <linux/spinlock.h>#include <linux/semaphore.h>#include <linux/slab.h>#include <asm/uaccess.h>spinlock_t mylock; //用于保护链表的操作struct semaphore sem;static LIST_HEAD(dlist); //用于存放数据的链表typedef struct {    char data[1000];    int len;    struct list_head list;}data_t;ssize_t myread(struct file *fl, char __user *buf, size_t len, loff_t *off){    int ret;    data_t *data;    struct list_head *tmp;    ret = down_interruptible(&sem);    if (ret < 0)        return -ERESTART;    tmp = dlist.next;    if (tmp == &dlist)        return -ENODATA;    data = container_of(tmp, data_t, list);    ret = copy_to_user(buf, data->data, data->len);    ret = data->len - ret;    spin_lock(&mylock);    list_del(tmp);    spin_unlock(&mylock);    kfree(data);    printk("after down: pid = %d, %s\n", current->pid, current->comm);    return ret;}ssize_t mywrite(struct file *fl, const char __user *buf, size_t len, loff_t *off){       data_t *data = kzalloc(sizeof(data_t), GFP_KERNEL);     int ret;    ret = copy_from_user(data->data, buf, len);    data->len = len-ret;            spin_lock(&mylock);    list_add_tail(&data->list, &dlist);    spin_unlock(&mylock);       up(&sem); // count++;       return len; }struct file_operations fops = {    .owner = THIS_MODULE,    .read = myread,    .write = mywrite,};struct miscdevice mymdev = {    .minor = MISC_DYNAMIC_MINOR,    .name = "mymdev",    .fops = &fops,};static int __init test_init(void){    sema_init(&sem, 0); //初始化count的值为0    spin_lock_init(&mylock);    return misc_register(&mymdev);}static void __exit test_exit(void){    misc_deregister(&mymdev);}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");
原创粉丝点击