博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Samsung_tiny4412(驱动笔记07)----spinlock,semaphore,atomic,mutex,completion,interrupt
阅读量:5977 次
发布时间:2019-06-20

本文共 15079 字,大约阅读时间需要 50 分钟。

/*********************************************************************************** *                     *               spinlock,semaphore,atomic,mutex,completion,interrupt * *   声明: *       1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会 *         不对齐,从而影响阅读. *       2. 本文中有些源代码没有全部帖出来,主要是因为篇幅太大的原因; *       3. 基于2中的原因,本文借鉴了python中的缩进代码风格进行代码的体现: *           1. 有些代码中的"..."代表省略了不影响阅读的代码; *           2. 如下代码缩进代表在一个函数内部的代码,至于在什么函数里,不影响阅读: *               ... //省略代码 *               struct test_s { *               }; *               ... //省略代码 * *                   //进入临界区之前加锁     } *                   spin_lock(&p->lock);     |  *                                            |   | *                   /* 有效代码 */           |-->|采用缩进,代表在一个函数内 *                                            |   |的代码 *                   //出临界区之后解锁       | *                   spin_unlock(&p->lock);   } * *               ... //省略代码                                 *               int __init test_init(void) *               {    *                   ... //省略代码 *               }   *               ... //省略代码 * * *                                          2015-3-13 阴 深圳 尚观 Var 曾剑锋 **********************************************************************************/                        \\\\\\\\--*目录*--////                        |  一. spinlock接口;                             |  二. semaphore接口;                            |  三. atomic接口;                               |  四. mutex接口;                                |  五. completion接口;                           |  六. interrupt接口;                            |  七. 按键驱动大致写法;                        |  八. 测试按键驱动;                             \\\\\\\\\\\\//一. spinlock接口:    1. 声明:       spinlock_t lock;    2. 初始化:     spin_lock_init(&test.lock);    3. 获取自旋锁: spin_lock(&p->lock);    4. 释放自旋锁: spin_unlock(&p->lock);    5. spin_lock接口使用Demo:        ...        struct test_s {            struct file_operations fops;            spinlock_t lock;            int major;        };        ...            //进入临界区之前加锁            spin_lock(&p->lock);            for(i = 0; i < 3; i++)            {                printk("count = %d, %s", cnt++, kbuf);                /*msleep(10);*/                mdelay(10);            }            //出临界区之后解锁            spin_unlock(&p->lock);        ...        int __init test_init(void)        {               int ret;            // 初始化spin_lock               spin_lock_init(&test.lock);                    ret = register_chrdev(test.major,                    DEV_NAME, &test.fops);            if(ret > 0)            {                test.major = ret;                printk("major = %d\n", test.major);                ret = 0;            }                    return ret;        }          ...二. semaphore接口:    1. 定义: struct semaphore sem;    2. 定义一个信号量,并初始化: DEFINE_SEMAPHORE(name);    3. 初始化: sema_init(&test.sem, 1);    4. 3种获取信号量:         1. down(&p->sem);        2. down_interruptible(&p->sem);        3. down_trylock(&p->sem);    5. 释放信号量: up(&p->sem);    6. semaphore接口使用Demo:        ...        struct test_s {            struct file_operations fops;            /**             * spinlock_t lock;             * volatile int count;             */            struct semaphore sem;            int major;        };        ...            /**             * spin_lock(&p->lock);             * if(p->count <= 0)             * {             *     spin_unlock(&p->lock);             *     return -EAGAIN;             * }             * p->count--;             * spin_unlock(&p->lock);             */                    //加不了锁,睡眠等待            /*down(&p->sem);*/                    if(down_trylock(&p->sem))                return -EAGAIN;                    for(i = 0; i < 3; i++)            {                printk("count = %d, %s", cnt++, kbuf);                msleep(10);            }                    up(&p->sem);                    /**             * spin_lock(&p->lock);             * p->count++;             * spin_unlock(&p->lock);             */        ...        int __init test_init(void)        {            int ret;                    /**             * spin_lock_init(&test.lock);             * test.count = 1;             */                    sema_init(&test.sem, 1);                    ret = register_chrdev(test.major,                    DEV_NAME, &test.fops);            if(ret > 0)            {                test.major = ret;                printk("major = %d\n", test.major);                ret = 0;            }                    return ret;        }        ...三. atomic接口:    1. 头文件:   linux-3.5/include/linux/atomic.h    2. 声明定义: atomic_t val; atomic_t *v = &val;    3. 读取原子变量的值:   atomic_read(v);    4. 修改原子变量的值:   atomic_set(v, i);    5. 原子变量自加1:      atomic_inc(v); --> v += 1;    6. 原子变量自减1:      atomic_dec(v); --> v -= 1;    7. 原子变量自加1并检测是否为0:       atomic_inc_and_test(v); v += 1,判断结果是否为0    8. 原子变量自减1并检测是否为0:       atomic_dec_and_test(v); v -= 1,判断结果是否为0    9. 原子变量自加1并返回原子变量的值:  atomic_inc_return(v)    10. 原子变量自减1并返回原子变量的值: atomic_dec_return(v)    11. 比较变量i和原子变量的值是否相等: atomic_sub_and_test(i, v)    12. atomic接口使用Demo:        ...        struct test_s {            struct file_operations fops;            atomic_t v;            int major;        };        typedef struct test_s test_t;                static int test_open(struct inode *inode, struct file *file)        {            test_t *p;            p = container_of(file->f_op, test_t, fops);                    file->private_data = p;                    if(!atomic_dec_and_test(&p->v))            {                atomic_inc(&p->v);                return -EAGAIN;            }                    printk("Open.\n");                    return 0;        }                static int test_close(struct inode *inode, struct file *file)        {            test_t *p = file->private_data;                    printk("Close.\n");            atomic_inc(&p->v);                    return 0;        }        ...        int __init test_init(void)        {            int ret;                    atomic_set(&test.v, 1);                    ret = register_chrdev(test.major,                    DEV_NAME, &test.fops);            if(ret > 0)            {                test.major = ret;                printk("major = %d\n", test.major);                ret = 0;            }                    return ret;        }        ...四. mutex接口:    1. 定义: struct mutex lock;    2. 定义一个互斥锁,并初始化: DEFINE_MUTEX(mutexname);    3. 初始化: mutex_init(&lock);    4. 3种加锁方式:        1. mutex_lock(&lock);        2. mutex_lock_interruptible(&lock);        3. mutex_trylock(&lock);    5. 解锁: mutex_unlock(&lock);    6. mutex接口使用Demo:        ...        struct test_s {            struct file_operations fops;            /*struct semaphore sem;*/            struct mutex lock;            int major;        };        typedef struct test_s test_t;        ...            /*mutex_lock(&p->lock);*/                    /*             *if(mutex_lock_interruptible(&p->lock))             *    return -EINTR;             */                    if(!mutex_trylock(&p->lock))                return -EAGAIN;                    for(i = 0; i < 3; i++)            {                printk("count = %d, %s", cnt++, kbuf);                msleep(10);            }                    mutex_unlock(&p->lock);        ...        int __init test_init(void)        {            int ret;                    mutex_init(&test.lock);                    ret = register_chrdev(test.major, DEV_NAME, &test.fops);            if(ret > 0)            {                test.major = ret;                printk("major = %d\n", test.major);                ret = 0;            }                    return ret;        }五. completion接口:    1. 定义: struct completion com;    2. 定义一个完成量,并初始化: DECLARE_COMPLETION(work)    3. 初始化: init_completion(&com);    4. 2种等待完成:         1. wait_for_completion(&com);        2. wait_for_completion_interruptible(&com);    5. 2种通知完成量:        1. complete(&com);        2. complete_all(&com);    6. mutex接口使用Demo:        ...        struct test_s {            struct file_operations fops;            struct completion com;            int major;        };        typedef struct test_s test_t;        ...        static ssize_t test_read(struct file *file, char __user *buf, size_t count, loff_t *pos)        {            test_t *p = file->private_data;                        //在完成量com上阻塞            /*wait_for_completion(&p->com);*/                    if(wait_for_completion_interruptible(&p->com))                return -ERESTARTSYS;                            printk("Read data.\n");                            return count;        }                static ssize_t test_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)        {            test_t *p = file->private_data;                        printk("Write data.\n");                        /*complete(&p->com);*/                        //通知所有阻塞的进程            complete_all(&p->com);                        return count;        }          ...        int __init test_init(void)        {            int ret;                    init_completion(&test.com);            ret = register_chrdev(test.major,                                  DEV_NAME, &test.fops);            if(ret > 0)            {                test.major = ret;                printk("major = %d\n", test.major);                ret = 0;            }                    return ret;        }        ...六. interrupt接口:    1. 查看系统中断处理信息: cat /proc/interrupts    2. 申请并注册中断处理函数:        static inline int __must_check request_irq( unsigned int irq, irq_handler_t handler,                                      unsigned long flags, const char *name, void *dev_data);    3. 释放中断,并取消中断处理函数:        void free_irq(unsigned int irq, void *dev_data);    4. 代码执行环境:        1. 中断上下文:         in_interrupt(); ---> 判断执行环境是否是中断上下文            1. 软中断上下文:   in_softirq();   ---> 判断执行环境是否是soft irq            2. 外部中断上下文: in_irq();       ---> 判断执行环境是否是硬件中断处理环境        2. 进程上下文.    5. 共享中断方法:        1. request_irq()指定共享标志 IRQF_SHARED;        2. request_irq()最后一个参数不能传递NULL,传递当前驱动全局变量地址;    6. 将系统gpio编号转换成对应的外部中断: gpio_to_irq();    7. spinlock中断中使用Demo:        ...        struct test_s {            struct file_operations fops;            spinlock_t lock;            int major;        };        typedef struct test_s test_t;        ...        int critical(const char *s, spinlock_t *lock)        {            int i;            unsigned long flag;            static int cnt = 0;                    /*spin_lock(lock);*/            /*local_irq_disable();*/            /*local_irq_save(flag);*/            /*spin_lock_irq(lock);*/            spin_lock_irqsave(lock, flag);                    for(i = 0; i < 3; i++)            {                printk("count = %d, %s", cnt++, s);                mdelay(1000);            }                    spin_unlock_irqrestore(lock, flag);            /*spin_unlock_irq(lock);*/            /*local_irq_restore(flag);*/            /*local_irq_enable();*/            /*spin_unlock(lock);*/                    return 0;        }                static irqreturn_t irq_handler(int irq, void *arg)        {            test_t *p = arg;                    critical("irq\n", &p->lock);                    return IRQ_HANDLED;        }                static ssize_t test_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)        {            int ret;            char kbuf[count + 1];            test_t *p = file->private_data;                    ret = copy_from_user(kbuf, buf, count);            if(ret)                return -EFAULT;            kbuf[count] = '\0';                    if(critical(kbuf, &p->lock))                return -EAGAIN;                    return count;        }        ...        int __init test_init(void)        {            int ret;                    spin_lock_init(&test.lock);                    ret = register_chrdev(test.major,                    DEV_NAME, &test.fops);            if(ret > 0)            {                test.major = ret;                printk("major = %d\n", test.major);                ret = 0;            }                    ret = request_irq(IRQ_EINT(26), irq_handler,                              IRQF_TRIGGER_FALLING,                              "key1", &test);            if(ret)                unregister_chrdev(test.major, DEV_NAME);                    return ret;        }        ...七. 按键驱动大致写法:    #include 
#include
#include
#include
#include
#include
#include
#define DEV_NAME "test" struct timer_list timer; struct btn_desc { int gpio; int num; char *name; }; int ev_key = 0; char key_state[] = { 0, 0, 0, 0}; DECLARE_WAIT_QUEUE_HEAD(wq); struct btn_desc btn[] = { { EXYNOS4_GPX3(2), 0, "key1" }, { EXYNOS4_GPX3(3), 1, "key2" }, { EXYNOS4_GPX3(4), 2, "key3" }, { EXYNOS4_GPX3(5), 3, "key4" } }; void timer_main(unsigned long data) { ev_key = 1; wake_up_interruptible(&wq); printk("timer_main.\n"); } static irqreturn_t irq_handler(int irq, void *arg) { struct btn_desc *key = arg; key_state[key->num] = 1; mod_timer(&timer, jiffies + 20); return IRQ_HANDLED; } static int test_open(struct inode *inode, struct file *file) { int i, irq, ret; for(i = 0; i < ARRAY_SIZE(btn); i++) { //irq = IRQ_EINT(26+i); //irq可以通过这种方法获得 irq = gpio_to_irq(btn[i].gpio); ret = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING | IRQF_SHARED, btn[i].name, &btn[i]); if(ret) break; } if(ret) { for(--i; i >= 0; i--) { irq = gpio_to_irq(btn[i].gpio); free_irq(irq, &btn[i]); } return ret; } return 0; } static int test_close(struct inode *inode, struct file *file) { int i, irq; for(i = 0; i < ARRAY_SIZE(btn); i++) { irq = gpio_to_irq(btn[i].gpio); free_irq(irq, &btn[i]); } return 0; } static ssize_t test_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { int ret; if(count > ARRAY_SIZE(key_state)) count = ARRAY_SIZE(key_state); while(!ev_key) { if(file->f_flags & O_NONBLOCK) return -EAGAIN; if(wait_event_interruptible(wq, ev_key)) return -ERESTARTSYS; } ret = copy_to_user(buf, key_state, count); if(ret) return -EFAULT; memset(key_state, 0, sizeof(key_state)); ev_key = 0; return count; } static struct file_operations fops = { .owner = THIS_MODULE, .open = test_open, .release = test_close, .read = test_read, }; int major; int __init test_init(void) { int ret; setup_timer(&timer, timer_main, 11223344); ret = register_chrdev(major, DEV_NAME, &fops); if(ret > 0) { major = ret; printk("major = %d\n", major); ret = 0; } return ret; } void __exit test_exit(void) { del_timer_sync(&timer); unregister_chrdev(major, DEV_NAME); } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL");八. 测试按键驱动: #include
#include
#include
#include
#include
int main(int argc, char **argv) { int fd, i, ret; char buf[4]; fd = open(argv[1], O_RDWR); if(-1 == fd) { perror("open"); exit(1); } while(1) { ret = read(fd, buf, sizeof(buf)); if(4 != ret) continue; for(i = 0; i < sizeof(buf); i++) { if(buf[i] == 1) printf("key%d down.\n", i + 1); } } close(fd); return 0; }

 

转载地址:http://iusox.baihongyu.com/

你可能感兴趣的文章
SortedMap接口
查看>>
清理Mac上的软件容易吗?
查看>>
Leetcode[26]-Remove Duplicates from Sorted Array
查看>>
读书笔记6pandas简单使用
查看>>
CSS3鼠标悬停图片上浮显示描述代码
查看>>
python 函数的参数
查看>>
composer 报 zlib_decode(): data error
查看>>
利用ArcMap对tiff或jpg格式地图图片的配准步骤
查看>>
发现了一个好用的在线勾图的站点
查看>>
结合Jexus + Kestrel 部署 asp.net core 生产环境
查看>>
memcache的windows下的安装和简单使用
查看>>
记账类问题汇总
查看>>
URL编码总结
查看>>
JDBC 4.2 Specifications 中文翻译 -- 第九章 连接
查看>>
es6的Proxy(代理)
查看>>
CentOs 7.2下ELK日志分析系统搭建
查看>>
Eclipse Modeling Framework, 2nd Edition. (EMF)学习笔记(一)——EMF介绍
查看>>
Laravel 源码解读:php artisan make:auth
查看>>
2017-06-08 前端日报
查看>>
[转]json2.js 源码解读
查看>>