4412 并发

发布者:京玩儿最新更新时间:2022-01-27 来源: eefocus关键字:并发 手机看文章 扫描二维码
随时随地手机看文章

一、并发基本概念

1.并发

  • 并发的概念是:多个执行单元同时、并行被执行

  • Linux系统是多任务的,很多任务会同时执行

  • 假如有三个执行单元ABC,共享了内存资源

    • 执行单元A对Buffer写1000个"a";

    • 执行单元B对Buffer写1000个"b";

    • 执行单元C从Buffer中读取数据。

    • 如果按照A写→C读→B写→C读,当然没有问题。

    • 但是如果A写→B写→C读,执行单元C就出问题了。

  • 当然比这个复杂更多,更加混乱的并发操作存在设备驱动中。

  • 只要有多个进程对共享资源的同时访问,就可能出现竞争。

2.竞态

  • 以下三种情况会导致竞态

  • 对称多处理的多个CPU

  • 单CPU内进程和强占它的进程

  • 中断和进程

3.竞态的解决办法

  • 解决竞态的途径是“保证对共享资源的互斥访问”

  • 也就是一个执行单元在访问共享资源的时候,其他的执行单元被禁止访问。

  • 访问共享资源的代码区称为临界区,临界区需要使用互斥机制来保护。

4.Linux操作系统中提供实现互斥的方法

  • 原子操作、自旋锁、信号量、互斥体等。

  • 后续视频介绍原子操作,自旋锁,互斥体

 

二、并发控制之原子操作

1.直接列出内核中提供的宏定义

解决竞态的途径是"保证对共享资源的互斥访问"

  • 变量:atomic_t 整型变量

  • 宏定义:atomic_read    (*(volatile int *)&(v)->counter)

    • volatile关键词:表示变量每次被访问,执行单元每次从内存单元中取值。

    • 不带关键词:表示变量在编译的时候可能被"优化"。(可能是CPU内部寄存器

    • 保证对特殊地址的稳定访问!

  • 宏定义:atomic_inc  atomic_add(1, (v))  变量加1

  • 宏定义:atomic_dec        变量减1

  • 宏定义:ATOMIC_INIT        赋值

 2.如何使用

假设任务单元A第一个申请"共享单元"。则先读变量,如果0,则对变量加1,然后对共享资源进行操作。操作完毕之后对变量赋值。

假设任务单元B要申请"共享单元"。则先读变量,如果0,则对变量加1,然后对共享资源进行操作。操作完毕之后对变量赋值。如果为1,直接返回。

3.代码分析

open_atomic_int_one以及open_atomic_int_two两个程序

要对/dev/atomic_int设备节点镜像操作

先运行的程序,将变量赋值为1,释放的时候赋值为0

如果程序1在没有释放的情况下,程序2调用设备节点则会直接返回,无法调用。

如果程序1在在没有释放的情况下,程序2调用则会直接返回,无法调用。

atomic

#include

#include


/* device register */

#include

/* register misc device */

#include

/* register device node */

#include

/* atomic */

#include

#include


#define DRIVER_NAME "atomic_int"

#define DEVICE_NAME "atomic_int"


MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("Topeet");


static atomic_t value_atomic = ATOMIC_INIT(0);


static int atomic_int_open(struct inode *inode, struct file *file)

{

        printk(KERN_EMERG "atomic_int open in!n");


        if(atomic_read(&value_atomic)) {

                return -EBUSY;

        }


        atomic_inc(&value_atomic);


        printk(KERN_EMERG "atomic_int open success!n");

        return 0;

}


static int atomic_int_release(struct inode *inode, struct file *file)

{

        printk(KERN_EMERG "atomic_int releasen");


        atomic_dec(&value_atomic);


        return 0;

}


static struct file_operations atomic_int_ops = {

        .owner = THIS_MODULE,

        .open = atomic_int_open,

        .release = atomic_int_release,

};


static struct miscdevice atomic_int_dev = {

        .minor = MISC_DYNAMIC_MINOR,

        .name = DEVICE_NAME,

        .fops = &atomic_int_ops,

};


static int atomic_int_probe(struct platfrom_device *pdv)

{

        printk(KERN_EMERG "tinitalizedn");

        misc_register(&atomic_int_dev);


        return 0;

}


static int atomic_int_remove(struct platform_device *pdv)

{

        printk(KERN_EMERG "tremvoen");

        misc_deregister(&atomic_int_dev);


        return 0;

}


struct platform_driver atomic_int_driver = {

        .probe = atomic_int_probe,

        .remove = atomic_int_remove,

        .driver = {

                .name = DRIVER_NAME,

                .owner = THIS_MODULE,

        }

};


static int atomic_int_init(void)

{

        int DriverState;


        printk(KERN_EMERG "atomic int entern");

        DriverState = platform_driver_register(&atomic_int_driver);


        printk(KERN_EMERG "tDriverState is %dn", DriverState);

        return 0;

}


static void atomic_int_exit(void)

{

        printk(KERN_EMERG "atomic int exitn");


        platform_driver_unregister(&atomic_int_driver);

}


module_init(atomic_int_init);

module_exit(atomic_int_exit);


open_one:

#include


#include

#include

#include

#include

#include


int main(int argc, char *argv[])

{

        char *atomic_int = "/dev/atomic_int";

        int fd;


        if((fd = open(atomic_int, O_RDWR|O_NDELAY)) < 0) {

                printf("%s open %s fialed!n", argv[0], atomic_int);

        } else {

                printf("%s open %s success!n", argv[0], atomic_int);

        }


        while(1);

}


opne_two:

#include


#include

#include

#include

#include

#include


int main(int argc, char *argv[])

{

        char *atomic_int = "/dev/atomic_int";

        int fd;


        if((fd = open(atomic_int, O_RDWR|O_NDELAY)) < 0) {

                printf("%s open %s fialed!n", argv[0], atomic_int);

        } else {

                printf("%s open %s success!n", argv[0], atomic_int);

        }


        while(1);

}

 

4.测试结果

[root@iTOP-4412]# insmod atomic.ko                                                     

[   69.905118] atomic int enter

[   69.906830]  initalized

[   69.925677]  DriverState is 0

[root@iTOP-4412]# ls /dev/atomic_int -l                                                

crw-rw----    1 root     0          10,  47 Jan  1 01:47 /dev/atomic_in


[root@iTOP-4412]# ./open_atomic_int_one &                                              

[root@iTOP-4412]# [   83.577155] atomic_int open in!

[   83.578851] atomic_int open success!

./open_atomic_int_one open /dev/atomic_int sucess!


[root@iTOP-4412]# ./open_atomic_int_two                                                

[   92.529032] atomic_int open in!

./open_atomic_int_two open /dev/atomic_int failed!


[root@iTOP-4412]# kill 1659                                                            

[root@iTOP-4412]#[  115.020445] atomic_int release

 

[1]+  Terminated                 ./open_atomic_int_one

[root@iTOP-4412]# ./open_atomic_int_two                                                

[  120.023368] atomic_int open in!

[  120.025137] atomic_int open success!

./open_atomic_int_two open /dev/atomic_int sucess!


^C[  123.292457] atomic_int release


遇到的问题:

一开始注册,没有运行probe函数。所以需要对内核裁剪(driver/char/Kconfig和arch/arm/mach-exynos/mach-top4412.c的修改)。

增减ATOMIC_INT_CONFIG,并编译内核后烧录。

 

三、并发控制之位原子操作

1.直接列出内核中提供的宏定义

宏定义:test_bit 返回位原子值

宏定义:set_bit 设置位

宏定义:clear_bit 清除位

 

2.如果使用

类似整型的原子操作

 

3.代码分析

  • open_atomic_bit_two以及open_atomic_bit_one两个程序

  • 要对/dev/atomic_bit这个设备节点进行操作

  • 先运行open之后,将变量赋值为1,释放的时候赋值为0

  • 如果在其中一个程序调用的过程中没有释放,第二个程序要对节点操作,则会直接返回错误。

 测试代码:

atomic_bit

#include

#include


/* device register */

#include

/* register misc device */

#include

/* register device node */

#include

/* atomic */

#include

#include


#define DRIVER_NAME "atomic_bit"

#define DEVICE_NAME "atomic_bit"


MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("Topeet");


//static atomic_t value_atomic = ATOMIC_INIT(0);

unsigned long int value_bit = 0;


static int atomic_bit_open(struct inode *inode, struct file *file)

{

        printk(KERN_EMERG "atomic_int open in!n");

/*

        if(atomic_read(&value_atomic)) {

                return -EBUSY;

        }


        atomic_inc(&value_atomic);

*/

        if(test_bit(0, &value_bit) != 0) {

                return -EBUSY;

        }


        set_bit(0, &value_bit);


        printk(KERN_EMERG "atomic_int open success!n");

        return 0;

}


static int atomic_bit_release(struct inode *inode, struct file *file)

{

        printk(KERN_EMERG "atomic_int releasen");


        //atomic_dec(&value_atomic);


        clear_bit(0, &value_bit);


        return 0;

}


static struct file_operations atomic_bit_ops = {

        .owner = THIS_MODULE,

[1] [2]
关键字:并发 引用地址:4412 并发

上一篇:4412 RS485
下一篇:4412 GPIO读 和 ioremap控制GPIO寄存器

推荐阅读最新更新时间:2024-11-17 11:17

STM32l151带MPU6050中断唤醒并发送数据到云平台
最近在调试STM32L151带mpu6050的中断唤醒的项目,下面写一下项目经历: 1.首先贴出我的主函数 int main(void) { SystemInit(); delay_init(72); //初始化延时函数 MY_GPIO_AN();//全部 模拟输入 //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 Base_TIM6_Init(); uart_init(115200); //初始化串口波特率为115200 SYS_RTCInit(60*5); //12h*/ RTC_WakeUpCmd(DISA
[单片机]
iTOP-4412开发板驱动lcd显卡以及linux开机log的修改方法
iTOP-4412 开发板 LCD 的屏幕驱动,iTOP-4412 开发板支持 4.3寸,7 寸,9.7 寸的 lcd 显示屏。其中 4.3 寸屏是用的 cpu 直接出来的 RGB 信号,7 寸屏和 9.7寸屏是用的 LVDS 信号,硬件上使用了一个 RGB 转 LVDS 的芯片实现的。我们来看下显示驱动,显示驱动在内核的“drivers/video/samsung”目录下面,这个驱动是三星提供好的,我们这支只讲下我们需要修改的几个文件。 首先是关于屏幕的分辨率的修改, 因为不同的屏幕分辨率, 频率以及其他一些硬件参数是不同的,所以我们需要根据这些参数去配置 cpu 的显示控制器,关于这些参数是在“driversvideo/s
[单片机]
4412开发板Android4.4.4环境的搭建和编译
刚刚到手的板子,按手册步骤成功烧写了系统,o( ̄▽ ̄)d,分享一下。 Android4.4.4 的编译环境,是在迅为的网盘或者 github中下载 Android4.4 的源码压缩包。解压后可以得到Android4.4.4 和 Kernel 的源码。 第一步,uboot的编译 uboot 源码在用户光盘“Android 源码”文件夹中的压缩包 “iTop4412_uboot_xxx_xxx.tar.gz”中,如下图所示。 如上图所示,编译 uboot 还需要将一个工具文件夹“CodeSign4SecureBoot”,这个工 具文件夹在4412光盘“Android 源码”文件夹中。这个工具文件夹需要和 uboot
[单片机]
<font color='red'>4412</font>开发板Android4.4.4环境的搭建和编译
tiny4412开发板icache操作程序
首先,来介绍关于cache的概念。 cache的作用: 基于程序访问的局限性,在主存和CPU通用寄存器之间设置了一个高速的、容量相对较小的存储器,把正在执行的指令地址附近的一部分指令或数据从主存调入这个存储器,供CPU在一段时间内使用,这对提高程序的运行速度有很大的作用。这个介于主存和CPU之间的高速小容量存储器称作高速缓存存储器(Cache)。 启用Cache后,CPU读取数据时,如果Cache中有这个数据的复本则直接返回,否则从主存中读入数据,并存入Cache中,下次再使用(读/写)这个数据时,可以直接使用Cache中的复本。 启用Cache后,CPU写数据时有写穿式和回写式两种方式。 (1)写穿式(Wri
[单片机]
迅为4412开发板V_4.0 ubuntu 在Android4.4.4的内核下移植wifi
背景:由于厂家迅为的全能版的V4.0底板和V3.5底板的wifi部分有改动,所以需要重新移植wifi 软件基础 :基于迅为提供的全能版V_4.0的Android4.4.4源码编译出来的ubuntu内核之上移植ubuntu文件系统 硬件基础:全能版V4.0底板,4412的scp大内存,或者pop大内存都行 一. 预备知识: 1.WPA Supplicant,这里我使用的是wpa_supplicant-2.5.tar.gz 简介:WPA Supplicant is a Wi-Fi Protected Access (WPA) client and IEEE 802.1X supplicant. It
[单片机]

推荐帖子

十进制转换成BCD的汇编程序
十进制转换成BCD的汇编程序十进制转换成BCD的汇编程序路过支持一下!帮顶
shangwlscp 嵌入式系统
无线模块nRF905最全资料(包括AVR,C51的测试程序)
无线模块nRF905最全资料,包括AVR(ATmega16),C51的测试程序。无线通信模块选型指南,无线通信计算方法无线模块nRF905最全资料(包括AVR,C51的测试程序)看看好不,正要用这个这些资料太好了,多谢分享太好了今年的无线通信模块是用到控制类上吗很好很强大的哇,楼主很犀利楼主还是感谢你两回吧,我没钱啦楼主还是感谢你两回吧,我没钱啦貌似很多人都用这个模块,会不会考虑使用ZigBee呢?大赛要用这个啊元器件清单出来了,楼主的帖子一定很受欢迎,呵呵。我也收下了
lly200 电子竞赛
[转]IDC年度盛典,指引中国IDC产业发展新方向
来源:IT资源库http://news.itdb.cn/n/200801/15/u20080115_1257.shtml中国IDC产业年度大典即将于2008年1月16日盛大开幕。这是中国IDC产业进入新年的头件大事。信产部的有关领导和业内专家将在会上全面解读2008年中国IDC行业的市场环境及监管政策,为IDC服务商的稳定发展指明方向。届时,国内外知名的电信运营商、IDC服务商、互联网增值服务商都将高度参与和关注此次盛典。回顾2007年,中国的IDC产业一直处于调整和发展之中,大多
ll19860607 RF/无线
H264编解码相关问题
我的设备是8127,H264编解码基础问题想请教一下:1、8127中的videoM3编码的输出,也就是每次ipcbitsout的输出就是一个NALU单元吗?2、我想读入本地的H264文件,然后交给videoM3解码,请问我每次应该读入多少内容呢?就一个NALU单元吗?H264编解码相关问题
comeback DSP 与 ARM 处理器
ULP Advisor 使用期间bug说明
小右派说::论坛上下载的IARMSP4305.5集成了ULPadvisor,具体解释ULPadvisor就是ultralowpoweradvisor,即使这个ULP.exe程序会对你的代码检查,给你提供省电的建议。小右派说::看图1,IAR中的ULPadvisor,对准工程名称,右键,选择option,找到Tiulpadvsor,选中enable框,这样就可以对你的代码进行检查,给出优化提示。对于我很有帮助。小右派说::执行complies,make,给出如图的提
小右派 微控制器 MCU
【英飞凌XENSIV™ PAS CO2传感器】CO2标气测试
CO2标气测试肆虐的口罩终于算是有了一个阶段了,终于让我拿到了CO2的标气,根据英飞凌CO2传感器的显示范围,选取的是25000PPM(2.5%)的标气,填充气为氮气。一直在思索如何测试能减少干扰呢?压力会对结果产生影响,所以不能用流动的气体吹;完全封闭的盒子还不太好实现,还需要透明可以看到示数;透明的袋子呢,这个相对比较好实现一点。找来一个比较大的透明袋子,严密性良好,将测试设备放入其中,尽可能的排出空气(没有抽气设
秦天qintian0303 传感器
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多每日新闻

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved