• 4412 并发


    一、并发基本概念

    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 <linux/init.h>
    #include <linux/module.h>
    
    /* device register */
    #include <linux/platform_device.h>
    /* register misc device */
    #include <linux/miscdevice.h>
    /* register device node */
    #include <linux/fs.h>
    /* atomic */
    #include <asm/types.h>
    #include <asm/atomic.h>
    
    #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!
    ");
    
            if(atomic_read(&value_atomic)) {
                    return -EBUSY;
            }
    
            atomic_inc(&value_atomic);
    
            printk(KERN_EMERG "atomic_int open success!
    ");
            return 0;
    }
    
    static int atomic_int_release(struct inode *inode, struct file *file)
    {
            printk(KERN_EMERG "atomic_int release
    ");
    
            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 "	initalized
    ");
            misc_register(&atomic_int_dev);
    
            return 0;
    }
    
    static int atomic_int_remove(struct platform_device *pdv)
    {
            printk(KERN_EMERG "	remvoe
    ");
            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 enter
    ");
            DriverState = platform_driver_register(&atomic_int_driver);
    
            printk(KERN_EMERG "	DriverState is %d
    ", DriverState);
            return 0;
    }
    
    static void atomic_int_exit(void)
    {
            printk(KERN_EMERG "atomic int exit
    ");
    
            platform_driver_unregister(&atomic_int_driver);
    }
    
    module_init(atomic_int_init);
    module_exit(atomic_int_exit);
    atomic.c

    open_one:

    #include <stdio.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    
    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!
    ", argv[0], atomic_int);
            } else {
                    printf("%s open %s success!
    ", argv[0], atomic_int);
            }
    
            while(1);
    }
    open_one

    opne_two:

    #include <stdio.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    
    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!
    ", argv[0], atomic_int);
            } else {
                    printf("%s open %s success!
    ", argv[0], atomic_int);
            }
    
            while(1);
    }
    open_two

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

     测试代码:

    #include <linux/init.h>
    #include <linux/module.h>
    
    /* device register */
    #include <linux/platform_device.h>
    /* register misc device */
    #include <linux/miscdevice.h>
    /* register device node */
    #include <linux/fs.h>
    /* atomic */
    #include <asm/types.h>
    #include <asm/atomic.h>
    
    #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!
    ");
    /*
            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!
    ");
            return 0;
    }
    
    static int atomic_bit_release(struct inode *inode, struct file *file)
    {
            printk(KERN_EMERG "atomic_int release
    ");
    
            //atomic_dec(&value_atomic);
    
            clear_bit(0, &value_bit);
    
            return 0;
    }
    
    static struct file_operations atomic_bit_ops = {
            .owner = THIS_MODULE,
            .open = atomic_bit_open,
            .release = atomic_bit_release,
    };
    
    static struct miscdevice atomic_bit_dev = {
            .minor = MISC_DYNAMIC_MINOR,
            .name = DEVICE_NAME,
            .fops = &atomic_bit_ops,
    };
    
    static int atomic_bit_probe(struct platfrom_device *pdv)
    {
            printk(KERN_EMERG "	initalized
    ");
            misc_register(&atomic_bit_dev);
    
            return 0;
    }
    
    static int atomic_bit_remove(struct platform_device *pdv)
    {
            printk(KERN_EMERG "	remvoe
    ");
            misc_deregister(&atomic_bit_dev);
    
            return 0;
    }
    
    struct platform_driver atomic_bit_driver = {
            .probe = atomic_bit_probe,
            .remove = atomic_bit_remove,
            .driver = {
                    .name = DRIVER_NAME,
                    .owner = THIS_MODULE,
            }
    };
    
    static int atomic_bit_init(void)
    {
            int DriverState;
    
            printk(KERN_EMERG "atomic bit enter
    ");
            DriverState = platform_driver_register(&atomic_bit_driver);
    
            printk(KERN_EMERG "	DriverState is %d
    ", DriverState);
            return 0;
    }
    
    static void atomic_bit_exit(void)
    {
            printk(KERN_EMERG "atomic bit exit
    ");
    
            platform_driver_unregister(&atomic_bit_driver);
    }
    
    module_init(atomic_bit_init);
    module_exit(atomic_bit_exit);
    atomic_bit

    open_ooopn:

    #include <stdio.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <errno.h>
    
    int main(int argc,char **argv){
        char *atomic_bit = "/dev/atomic_bit";
        int fd1;
        
        if((fd1 = open(atomic_bit,O_RDWR|O_NDELAY))==0){
            printf("%s open %s success
    ",argv[0],atomic_bit);
        }
        else{    
            perror(argv[0]);
        }    
        
        while(1);
        close(fd1);
    }
    open_one

    opne_two:

    #include <stdio.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <errno.h>
    
    int main(int argc,char **argv){
        char *atomic_bit = "/dev/atomic_bit";
        int fd1;
        
        if((fd1 = open(atomic_bit,O_RDWR|O_NDELAY))==0){
            printf("%s open %s success!
    ",argv[0],atomic_bit);
        }
        else{    
            perror(argv[0]);
        }    
        
        while(1);
        close(fd1);
    }
    open_two
  • 相关阅读:
    jquery1.9之学习笔记
    ERROR: Removing 'hello': Device or resource busy
    windows虚拟机性能调整
    kvm虚拟机控制台登录配置
    KVM虚拟机的管理
    window kvm 虚拟机的创建
    kvm虚拟化环境的搭建
    C实现哈希表
    哲学家就餐问题 C语言实现
    Linux面试题
  • 原文地址:https://www.cnblogs.com/ch122633/p/9488378.html
Copyright © 2020-2023  润新知