zoukankan      html  css  js  c++  java
  • 环形缓冲区【转】

    本文转载自:http://blog.csdn.net/u013904227/article/details/51168398

    1、什么是环形缓冲区

    • 环形缓冲区,顾名思义就是一个环状的存储数据的区域,其空间使用数组进行构造(链表也可以)。环形缓冲区特点是读和写可以是分开的,写入数据之后可以先不去读取,等到需要读取的时候再去读取,并且数据一经读取之后下次就不能再去读取(当然也可以实现重复读取的效果,不过大多用作一次性读取),等于说是一次性的读取。
    • 假设一个长度为256字节的数组,构建出一个环形缓冲区,当写操作进行到数组的第256项之后,再一次写入就会回到第0个进行写入;同样读操作是读取到数组的第256项时,再一次进行读取就会回到数组的第一项。是谓环形缓冲

    2、环形缓冲区的作用

    用作需要大量写入并且大量一次性读写的数据缓存区

    比如视频的写入读取:在视频播放的时候需要不断的进行写入读取操作,而且数据一经读出就会显示出来,下次就不再需要已经读出的数据了。使用环形缓冲区可以满足这个要求,并且实现读写分别进行,而且节省了空间。

    用作进程间通信,减少加锁开销

    由于环形缓冲区的读写分开特性,当两个线程进行通信的时候,可以采用环形缓冲区进行交流,一个进程读取,一个进程写入,由于读写的位置不同,并不需要加锁进行并发控制,也就减少了锁的时间开销

    3、程序编写测试(基于嵌入式linux的kmesg方式建立)

    /* 使用printk函数打印调试信息,调试信息写到proc里面,形成一个环形缓冲区 */
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/fs.h>
    #include <linux/init.h>
    #include <linux/proc_fs.h>
    
    #include <asm/uaccess.h>
    
    /* proc的文件结构体 */
    struct proc_dir_entry *entry;
    
    #define MAX_COUNT 1024  //缓冲区长度
    static char proc_buffer[MAX_COUNT]; //缓冲区数组
    static int empty_flag = 0;  //是否为空,0表示为空
    static int last_r_pos = 0;
    static int mymsg_r = 0; //读位置
    static int mymsg_w = 0; //写位置
    
    /* 判断是否为空 */
    static int is_empty_mymsg(void)
    {
        if(((mymsg_w % MAX_COUNT)  == (mymsg_r % MAX_COUNT)) && (empty_flag == 0)){
            return 1;   //Is empty
        }
    
        return 0;   //Is not empty
    }
    
    /* 判断是否为满 */
    static int is_full_mymsg(void)
    {
        if(((mymsg_w % MAX_COUNT) == (mymsg_r % MAX_COUNT)) && (empty_flag != 0)){
            return 1;   //Is full
        }
    
        return 0;   //Is not full
    }
    
    /* 读取一个字节 */
    static int read_onebyte_mymsg(char *buf_p)
    {
        if(is_empty_mymsg()){
            return 0;   //empty buffer can't read
        }
    
        *buf_p = proc_buffer[mymsg_r % MAX_COUNT];
        mymsg_r = (mymsg_r + 1) % MAX_COUNT;
        empty_flag --;  //每读取一个字节空标志减去1
    
        return 1;
    }
    
    /* 写入一个字节 */
    static void write_onebyte_mymsg(char byte)
    {
        proc_buffer[mymsg_w % MAX_COUNT] = byte;
        if(is_full_mymsg()){
            mymsg_r = (mymsg_r + 1) % MAX_COUNT;
            empty_flag --;
        }
    
        mymsg_w = (mymsg_w + 1) % MAX_COUNT;
        empty_flag ++;  //每写入一个字节,空标志加一
    }
    
    /* 执行cat命令的时候会调用到,直到返回为空的时候cat才会返回 */
    static ssize_t printk_drv_read(struct file *f_name, char __user *buf, size_t cont, loff_t *lof)
    {
        char byte_to_user;
    
        cont = read_onebyte_mymsg(&byte_to_user);
        __put_user(byte_to_user, buf);
    
        return cont;
    }
    
    /* 自建打印函数,另带有往环形缓冲区里面写入数据的功能 */
    int myprintk(const char *fmt, ...)
    {
        va_list args;
        int r;
    
        va_start(args, fmt);
        r = vprintk(fmt, args);
        va_end(args);
    
        while(r --){
            write_onebyte_mymsg(*fmt++);
        }
    
        return r;
    }
    
    EXPORT_SYMBOL(myprintk);
    
    const struct file_operations proc_mymsg_operations = {
        .owner = THIS_MODULE,
        .read = printk_drv_read,
    };
    
    static int printk_drv_init(void)
    {   
        int i = 0;
    
        /* 打印测试 */
        for(i = 0; i < MAX_COUNT; i++){
            myprintk("F");
        }
        /* 边界测试 */
        for(i = 0; i < 5; i++){
            myprintk("Y");
        }
    //  myprintk("Function printk_drv_init is running
    ");
    
        entry = create_proc_entry("mymsg", S_IRUSR, &proc_root);
        if (entry)
            entry->proc_fops = &proc_mymsg_operations;
    
    //  myprintk("Function printk_drv_init finished
    ");
    
        return 0;
    }
    
    static void printk_drv_exit(void)
    {
        remove_proc_entry("mymsg", &proc_root);
    }
    
    module_init(printk_drv_init);
    module_exit(printk_drv_exit);
    MODULE_LICENSE("GPL");
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    4、测试结果

    insmod myprintk.ko FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFYYYYY cat /proc/mymsg FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFYYYYY //开始的5个F被清除掉了 cat /proc/mymsg 空

    5、判断环形缓冲区的空或者满

    设置额外的标志位

    例如上面例子中的empty_flag,写的时候加上1,读的时候减去1,当满足读等于写并且empty_flag为0,则说明缓冲区空了。如果满足读等于写并且empty_flag不为0,说明缓冲区满了。

    环形缓冲区始终空出一个值

    例如:

    /* 判断是否为空 */
    static int is_empty_mymsg(void)
    {
        //if(((mymsg_w % MAX_COUNT)  == (mymsg_r % MAX_COUNT)) && (empty_flag == 0)){
        if(((mymsg_w % MAX_COUNT)  == (mymsg_r % MAX_COUNT))){
            return 1;   //Is empty
        }
    
        return 0;   //Is not empty
    }
    
    /* 判断是否为满 */
    static int is_full_mymsg(void)
    {
        //if(((mymsg_w % MAX_COUNT) == (mymsg_r % MAX_COUNT)) && (empty_flag != 0)){
        if((((mymsg_w + 1) % MAX_COUNT) == (mymsg_r % MAX_COUNT))){
            return 1;   //Is full
        }
    
        return 0;   //Is not full
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这样就会导致在read位置前面的一个字节始终不能够写入数据,但是却很轻易的区分出来缓冲区是满还是空

  • 相关阅读:
    nodeJs小练习之爬取北京昌平区房价
    2016,加油,奋斗
    1339 字符串王国的种族
    1333 明信片和照片
    1316 你能知道这是几进制数?
    1309 简化版九宫格
    1295 爱翻译
    1288 幸运转盘(一)
    1287 孙武练兵
    1284 喜羊羊的新年礼物
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7268419.html
Copyright © 2011-2022 走看看