当前位置: 首页 > news >正文

杭州网站设计首选柚米建设织梦网站模板

杭州网站设计首选柚米,建设织梦网站模板,友情链接网站大全,网站绑定微信号Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 先说点题外话#xff0c;上周参加行业年会#xff0c;停更了一周。接下来的周五就要开启国庆中秋双节模式#xff0c;所以有的时候#xff0c;尤其是工作以后…Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 先说点题外话上周参加行业年会停更了一周。接下来的周五就要开启国庆中秋双节模式所以有的时候尤其是工作以后想要好好的学习点东西是多么的难。并且学习必须是一个连续的过程。大家可能会有这样的体会本来做研发的过程中突然临时领导分配其他的工作并且要立马去做的。当集中几天精力完成了领导的任务再回头去看原来手里的工作时发现有很多东西都记不太清了。这也是我很头疼的一个问题大家有好的建议或是处理方法可以评论区给我留言。 本篇笔记主要是学习并发和竞争的实例主要内容包括原子操作、自旋锁操作、信号量和互斥体。 本笔记的思维导图很简单如下 一、原子操作 本节要实现的功能是利用原子操作来实现对LED设备的互斥操作。 32 /* gpioled 设备结构体 */ 33 struct gpioled_dev{ 34 dev_t devid; /* 设备号 */ 35 struct cdev cdev; /* cdev */ 36 struct class *class; /* 类 */ 37 struct device *device; /* 设备 */ 38 int major; /* 主设备号 */ 39 int minor; /* 次设备号 */ 40 struct device_node *nd; /* 设备节点 */ 41 int led_gpio; /* led 所使用的 GPIO 编号 */ 42 atomic_t lock; /* 原子变量 */ 43 }; 第 42 行原子变量 lock用来实现一次只能允许一个应用访问 LED 灯 led_init 驱动入口函数会将 lock 的值设置为 1。 54 static int led_open(struct inode *inode, struct file *filp) 55 { 56 /* 通过判断原子变量的值来检查 LED 有没有被别的应用使用 */ 57 if (!atomic_dec_and_test(gpioled.lock)) { 58 atomic_inc(gpioled.lock);/* 小于 0 的话就加 1,使其原子变量等于 0 */ 59 return -EBUSY; /* LED 被使用返回忙 */ 60 } 61 62 filp-private_data gpioled; /* 设置私有数据 */ 63 return 0; 64 } 第 57~60 行每次调用 open 函数打开驱动设备的时候先申请 lock如果申请成功的话就表 示 LED灯还没有被其他的应用使用如果申请失败就表示 LED灯正在被其他的应用程序使用。         每次打开驱动设备的时候先使用 atomic_dec_and_test 函数将 lock 减 1如果 atomic_dec_and_test函数返回值为真就表示 lock 当前值为 0说明设备可以使用。如果 atomic_dec_and_test 函数返回值为假就表示 lock 当前值为负数(lock 值默认是 1) lock 值为负数的可能性只有一个那就是其他设备正在使用 LED。其他设备正在使用 LED 灯那么就只能退出了在退出之前调用函数 atomic_inc 将 lock 加 1因为此时 lock 的值被减成了负数必须要对其加 1将 lock 的值变为 0。 上面一段说的可能有点绕总的意思就是要想要先申请。 111 * description : 关闭/释放设备 112 * param – filp : 要关闭的设备文件(文件描述符) 113 * return : 0 成功;其他 失败 114 */ 115 static int led_release(struct inode *inode, struct file *filp) 116 { 117 struct gpioled_dev *dev filp-private_data; 118 119 /* 关闭驱动文件的时候释放原子变量 */ 120 atomic_inc(dev-lock); 121 return 0; 122 } 第 120 行 LED 灯使用完毕应用程序调用 close 函数关闭的驱动文件 led_release 函数执行调用 atomic_inc 释放 lcok也就是将 lock 加 1。 142 /* 初始化原子变量 */ 143 atomic_set(gpioled.lock, 1); /* 原子变量初始值为 1 */ 第 143 行初始化原子变量 lock初始值设置为 1这样每次就只允许一个应用使用 LED 灯。 在测试的APP中有如下程序 62 /* 模拟占用 25S LED */ 63 while(1) { 64 sleep(5); 65 cnt; 66 printf(App running times:%d\r\n, cnt); 67 if(cnt 5) break; 68 } 第 63~68 行的模拟占用 25 秒 LED 的代码。测试 APP 在获取到 LED 灯驱动的使用权以后会使用 25S在使用的这段时间如果有其他的应用也去获取 LED 灯使用权的话肯定会失败 二、自旋锁 自旋锁保护的临界区要尽可能的短。 考虑驱动的兼容性合理的选择 API 函数。 33 /* gpioled 设备结构体 */ 34 struct gpioled_dev{ 35 dev_t devid; /* 设备号 */ 36 struct cdev cdev; /* cdev */ 37 struct class *class; /* 类 */ 38 struct device *device; /* 设备 */ 39 int major; /* 主设备号 */ 40 int minor; /* 次设备号 */ 41 struct device_node *nd; /* 设备节点 */ 42 int led_gpio; /* led 所使用的 GPIO 编号 */ 43 int dev_stats; /* 设备状态 0设备未使用;0,设备已经被使用 */ 44 spinlock_t lock; /* 自旋锁 */ 45 }; 第 43 行 dev_stats 表示设备状态如果为 0 的话表示设备还没有被使用如果大于 0 的 话就表示设备已经被使用了。第 44 行定义自旋锁变量 lock。 56 static int led_open(struct inode *inode, struct file *filp) 57 { 58 unsigned long flags; 59 filp-private_data gpioled; /* 设置私有数据 */ 60 61 spin_lock_irqsave(gpioled.lock, flags); /* 上锁 */ 62 if (gpioled.dev_stats) { /* 如果设备被使用了 */ 63 spin_unlock_irqrestore(gpioled.lock, flags); /* 解锁 */ 64 return -EBUSY; 65 } 66 gpioled.dev_stats; /* 如果设备没有打开那么就标记已经打开了 */ 67 spin_unlock_irqrestore(gpioled.lock, flags);/* 解锁 */ 68 69 return 0; 70 } 第 61~67 行使用自旋锁实现对设备的互斥访问第 61 行调用 spin_lock_irqsave 函数获 取锁为了考虑到驱动兼容性这里并没有使用 spin_lock 函数来获取锁。第 62 行判断 dev_stats 是否大于 0如果是的话表示设备已经被使用了那么就调用 spin_unlock_irqrestore 函数释放锁并且返回-EBUSY。如果设备没有被使用的话就在第 66 行将 dev_stats 加 1表 示设备要被使用了然后调用 spin_unlock_irqrestore 函数释放锁。自旋锁的工作就是保护 dev_stats 变量 真正实现对设备互斥访问的是 dev_stats。 121 static int led_release(struct inode *inode, struct file *filp) 122 { 123 unsigned long flags; 124 struct gpioled_dev *dev filp-private_data; 125 126 /* 关闭驱动文件的时候将 dev_stats 减 1 */ 127 spin_lock_irqsave(dev-lock, flags); /* 上锁 */ 128 if (dev-dev_stats) { 129 dev-dev_stats--; 130 } 131 spin_unlock_irqrestore(dev-lock, flags);/* 解锁 */ 132 133 return 0; 134 } 第 126~131 行在 release 函数中将 dev_stats 减 1表示设备被释放了可以被其他的应用程序使用。将 dev_stats 减 1 的时候需要自旋锁对其进行保护。 150 static int __init led_init(void) 151 { 152 int ret 0; 153 154 /* 初始化自旋锁 */ 155 spin_lock_init(gpioled.lock); ...... 212 return 0; 213 } 第 155 行在驱动入口函数 led_init 中调用 spin_lock_init 函数初始化自旋锁。 三、信号量 使用信号量实现了一次只能有一个应用程序访问 LED 灯信号量可以导致休眠因此信号量保护的临界区没有运行时间限制可以在驱动的 open 函数申请信号量然后在release 函数中释放信号量。但是信号量不能用在中断中。 14 #include linux/semaphore.h 33 /* gpioled 设备结构体 */ 34 struct gpioled_dev{ 35 dev_t devid; /* 设备号 */ 36 struct cdev cdev; /* cdev */ 37 struct class *class; /* 类 */ 38 struct device *device; /* 设备 */ 39 int major; /* 主设备号 */ 40 int minor; /* 次设备号 */ 41 struct device_node *nd; /* 设备节点 */ 42 int led_gpio; /* led 所使用的 GPIO 编号 */ 43 struct semaphore sem; /* 信号量 */ 44 }; 第 43 行在设备结构体中添加一个信号量成员变量 sem。 48 /* 49 * description : 打开设备 50 * param – inode : 传递给驱动的 inode 51 * param - filp : 设备文件 file 结构体有个叫做 private_data 的成员变量 52 * 一般在 open 的时候将 private_data 指向设备结构体。 53 * return : 0 成功;其他 失败 54 */ 55 static int led_open(struct inode *inode, struct file *filp) 56 { 57 filp-private_data gpioled; /* 设置私有数据 */ 58 59 /* 获取信号量,进入休眠状态的进程可以被信号打断 */ 60 if (down_interruptible(gpioled.sem)) { 61 return -ERESTARTSYS; 62 } 63 #if 0 64 down(gpioled.sem); /* 不能被信号打断 */ 65 #endif 66 67 return 0; 68 } 第 60~65行在 open函数中申请信号量可以使用 down 函数也可以使用 down_interruptible函数。如果信号量值大于等于 1 就表示可用那么应用程序就会开始使用 LED 灯。如果信号量值为 0 就表示应用程序不能使用 LED 灯此时应用程序就会进入到休眠状态。等到信号量值大于 1 的时候应用程序就会唤醒申请信号量获取 LED 灯使用权。 114 /* 115 * description : 关闭/释放设备 116 * param – filp : 要关闭的设备文件(文件描述符) 117 * return : 0 成功;其他 失败 118 */ 119 static int led_release(struct inode *inode, struct file *filp) 120 { 121 struct gpioled_dev *dev filp-private_data; 122 123 up(dev-sem); /* 释放信号量信号量值加 1 */ 124 125 return 0; 126 } 第 123 行在 release 函数中调用 up 函数释放信号量这样其他因为没有得到信号量而进 入休眠状态的应用程序就会唤醒获取信号量。 142 static int __init led_init(void) 143 { 144 int ret 0; 145 146 /* 初始化信号量 */ 147 sema_init(gpioled.sem, 1); ...... 204 return 0; 205 } 第 147 行在驱动入口函数中调用 sema_init 函数初始化信号量 sem 的值为 1相当于 sem 是个二值信号量。 四、互斥体 33 /* gpioled 设备结构体 */ 34 struct gpioled_dev{ 35 dev_t devid; /* 设备号 */ 36 struct cdev cdev; /* cdev */ 37 struct class *class; /* 类 */ 38 struct device *device; /* 设备 */ 39 int major; /* 主设备号 */ 40 int minor; /* 次设备号 */ 41 struct device_node *nd; /* 设备节点 */ 42 int led_gpio; /* led 所使用的 GPIO 编号*/ 43 struct mutex lock; /* 互斥体 */ 44 }; 第 43 行定义互斥体 lock。 55 static int led_open(struct inode *inode, struct file *filp) 56 { 57 filp-private_data gpioled; /* 设置私有数据 */ 58 59 /* 获取互斥体,可以被信号打断 */ 60 if (mutex_lock_interruptible(gpioled.lock)) { 61 return -ERESTARTSYS; 62 } 63 #if 0 64 mutex_lock(gpioled.lock); /* 不能被信号打断 */ 65 #endif 66 67 return 0; 68 } 第 60~65 行在 open 函数中调用 mutex_lock_interruptible 或者 mutex_lock 获取 mutex成功的话就表示可以使用 LED 灯失败的话就会进入休眠状态和信号量一样。 119 static int led_release(struct inode *inode, struct file *filp) 120 { 121 struct gpioled_dev *dev filp-private_data; 122 123 /* 释放互斥锁 */ 124 mutex_unlock(dev-lock); 125 126 return 0; 127 } 第 124 行在 release 函数中调用 mutex_unlock 函数释放 mutex这样其他应用程序就可以 获取 mutex 了。 143 static int __init led_init(void) 144 { 145 int ret 0; 146 147 /* 初始化互斥体 */ 148 mutex_init(gpioled.lock); ...... 205 return 0; 206 } 第 148 行在驱动入口函数中调用 mutex_init 初始化 mutex。 五、总结 本片笔记主要是巩固上次课学习的并发和竞争相关内容主要包括原子操作、自旋锁、信号量和互斥体。 本文为参考正点原子开发板配套教程整理而得仅用于学习交流使用不得用于商业用途。
http://wiki.neutronadmin.com/news/73255/

相关文章:

  • 房地产网站建设招商企业网络推广多喜爱
  • 广州网站制作哪家全面芜湖注册公司
  • 台州椒江网站制作公司wordpress 按装
  • 网站首页上的动画是咋做的建站之星怎么使用
  • 安康免费做网站公司python手机版
  • 求网站建设详细过程建网站需要什么步骤
  • 公司没网站怎么做dsp山东东营信息网
  • 提升网站权重的策略聚通装潢官网电话
  • 建设网站时间蜘蛛爬网站
  • 百度网站快速排名公司网站有什么用
  • 网站建设做哪 个会计科目杭州市建设工程交易网
  • 龙岗英文网站制作电子商务公司的经营范围
  • 开个人网站需要多少钱明星网站建设
  • 有做企业网站的吗邢台太行中学地址
  • 宿州企业网站建设Wordpress获取自定义分类
  • 专做轮胎的网站营销推广活动策划书模板
  • 微信网站建站平台网站怎么添加代码
  • 企业网站建设联系方式做一个推广网站多少钱
  • 怎么在ftp看网站后台地址发布外链
  • 装修公司网站源码php河北廊坊建筑模板厂家
  • 网站开发设计公司块位顺德电子商务网站建设
  • apache 配置网站地址东莞网站建设 汇卓
  • 网站开发e r图用自己主机做网站
  • 深圳 企业网站建设中国企业500强排行榜2021
  • 东胜网站制作中电建铁路建设公司网站
  • icp网站域名怎么填写乔拓云的品牌推广方案
  • 淘宝网网站开发沃尔沃公司网站建设
  • 做神马网站快速排国内上市的网络公司排名
  • 泌阳专业网站建设wordpress 置顶特色
  • 深圳制作网站主页wordpress在国内很慢