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
    
  • 相关阅读:
    c语言之数据类型
    C语言之概述
    012.day12
    011.day011
    010.day010
    010.day08
    010.周六自习
    009.day07
    008.day06
    007.day05
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709321.html
Copyright © 2011-2022 走看看