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

    Linux内核文件kfifo.h和kfifo.c

    举例

    #include <sys/mman.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    
    #define report_exceptional_condition() abort ()
    
    struct ring_buffer
    {
       void *address;
       unsigned long count_bytes;
       unsigned long write_offset_bytes;
       unsigned long read_offset_bytes;
    };
    
    // Warning order should be at least 12 for Linux
    void ring_buffer_create(struct ring_buffer *buffer, unsigned long order)
    {
       char path[] = "/dev/shm/ring-buffer-XXXXXX";
       int file_descriptor;
       void *address;
       int status;
       file_descriptor = mkstemp(path);
    
       if(file_descriptor < 0)
       {
          report_exceptional_condition();
       }
    
       status = unlink(path);
    
       if(status)
       {
          report_exceptional_condition();
       }
    
       buffer->count_bytes = 1UL << order;
       buffer->write_offset_bytes = 0;
       buffer->read_offset_bytes = 0;
       status = ftruncate(file_descriptor, buffer->count_bytes);
    
       if(status)
       {
          report_exceptional_condition();
       }
    
       buffer->address = mmap(NULL, buffer->count_bytes << 1, PROT_NONE,
                              MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    
       if(buffer->address == MAP_FAILED)
       {
          report_exceptional_condition();
       }
    
       address = mmap(buffer->address, buffer->count_bytes, PROT_READ | PROT_WRITE,
                      MAP_FIXED | MAP_SHARED, file_descriptor, 0);
    
       if(address != buffer->address)
       {
          report_exceptional_condition();
       }
    
       address = mmap(buffer->address + buffer->count_bytes,
                      buffer->count_bytes, PROT_READ | PROT_WRITE,
                      MAP_FIXED | MAP_SHARED, file_descriptor, 0);
    
       if(address != buffer->address + buffer->count_bytes)
       {
          report_exceptional_condition();
       }
    
       status = close(file_descriptor);
    
       if(status)
       {
          report_exceptional_condition();
       }
    }
    
    void ring_buffer_free(struct ring_buffer *buffer)
    {
       int status;
       status = munmap(buffer->address, buffer->count_bytes << 1);
    
       if(status)
       {
          report_exceptional_condition();
       }
    }
    
    void *ring_buffer_write_address(struct ring_buffer *buffer)
    {
       // void pointer arithmetic is a constraint violation.
       return buffer->address + buffer->write_offset_bytes;
    }
    
    void ring_buffer_write_advance(struct ring_buffer *buffer, unsigned long count_bytes)
    {
       buffer->write_offset_bytes += count_bytes;
    }
    
    void *ring_buffer_read_address(struct ring_buffer *buffer)
    {
       return buffer->address + buffer->read_offset_bytes;
    }
    
    void ring_buffer_read_advance(struct ring_buffer *buffer, unsigned long count_bytes)
    {
       buffer->read_offset_bytes += count_bytes;
    
       if(buffer->read_offset_bytes >= buffer->count_bytes)
       {
          //如果读指针大于等于缓冲区长度,那些读写指针同时折返回[0, buffer_size]范围内
          buffer->read_offset_bytes -= buffer->count_bytes;
          buffer->write_offset_bytes -= buffer->count_bytes;
       }
    }
    
    unsigned long ring_buffer_count_bytes(struct ring_buffer *buffer)
    {
       return buffer->write_offset_bytes - buffer->read_offset_bytes;
    }
    
    unsigned long ring_buffer_count_free_bytes(struct ring_buffer *buffer)
    {
       return buffer->count_bytes - ring_buffer_count_bytes(buffer);
    }
    
    void ring_buffer_clear(struct ring_buffer *buffer)
    {
       buffer->write_offset_bytes = 0;
       buffer->read_offset_bytes = 0;
    }
    
    void print(struct ring_buffer *buffer)
    {
       printf("ring_buffer_count_bytes %lu
    ", ring_buffer_count_bytes(buffer));
       printf("ring_buffer_count_free_bytes %lu
    ", ring_buffer_count_free_bytes(buffer));
       printf("ring_buffer_read_address %p
    ", ring_buffer_read_address(buffer));
       printf("ring_buffer_write_address %p
    ", ring_buffer_write_address(buffer));
    }
    
    int main()
    {
       struct ring_buffer buffer = {0};
    
       ring_buffer_create(&buffer, 16);
       print(&buffer);
    
       ring_buffer_write_advance(&buffer, 1140);
       print(&buffer);
    
       ring_buffer_read_advance(&buffer, 450);
       print(&buffer);
    
       ring_buffer_clear(&buffer);
       print(&buffer);
    
       ring_buffer_free(&buffer);
    
       return 0;
    }
    

    实验效果

    ring_buffer_count_bytes 0
    ring_buffer_count_free_bytes 65536
    ring_buffer_read_address 0x7fa76d30a000
    ring_buffer_write_address 0x7fa76d30a000
    ring_buffer_count_bytes 1140
    ring_buffer_count_free_bytes 64396
    ring_buffer_read_address 0x7fa76d30a000
    ring_buffer_write_address 0x7fa76d30a474
    ring_buffer_count_bytes 690
    ring_buffer_count_free_bytes 64846
    ring_buffer_read_address 0x7fa76d30a1c2
    ring_buffer_write_address 0x7fa76d30a474
    ring_buffer_count_bytes 0
    ring_buffer_count_free_bytes 65536
    ring_buffer_read_address 0x7fa76d30a000
    ring_buffer_write_address 0x7fa76d30a000
    
  • 相关阅读:
    使用某些 DOCTYPE 时会导致 document.body.scrollTop 失效
    VB.NET 笔记1
    知识管理系统Data Solution研发日记之一 场景设计与需求列出
    知识管理系统Data Solution研发日记之五 网页下载,转换,导入
    折腾了这么多年的.NET开发,也只学会了这么几招 软件开发不是生活的全部,但是好的生活全靠它了
    分享制作精良的知识管理系统 博客园博客备份程序 Site Rebuild
    知识管理系统Data Solution研发日记之四 片段式数据解决方案
    知识管理系统Data Solution研发日记之二 应用程序系列
    知识管理系统Data Solution研发日记之七 源代码与解决方案
    知识管理系统Data Solution研发日记之三 文档解决方案
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709321.html
Copyright © 2011-2022 走看看