利用Linux内核KFIFO代码,实现大量数据的写入与读出

参考Linux内核中的kfifo.h文件,进行简单修改以便使用,使用两个线程,其中一个线程(如Pthread_Write)进行写操作,另个一线程(如Pthread_Read)进行读操作;其中写入连续数字,读出的数据可以写入到一个文件中,但是读出的数据必须是连续的,数据个数60亿,期间不适用加锁机制;

写入时间,读取时间要统计出来显示,使用clock_gettime函数统计60亿的数据写完和读出所需要的时间。

ring_buffer.h文件:

#ifndef KFIFO_HEADER_H 

#define KFIFO_HEADER_H


#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>


//判断x是否是2的次方
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
//取a和b中最小值
#define min(a, b) (((a) < (b)) ? (a) : (b))


struct ring_buffer
{
    void         *buffer;     //缓冲区
    uint32_t     size;       //大小
    uint32_t     in;         //入口位置
    uint32_t       out;        //出口位置
};
//初始化缓冲区
struct ring_buffer* ring_buffer_init(void *buffer, uint32_t size, pthread_mutex_t *f_lock)
{
    assert(buffer);
    struct ring_buffer *ring_buf = NULL;
    if (!is_power_of_2(size))
    {
    fprintf(stderr,"size must be power of 2.\n");
        return ring_buf;
    }
    ring_buf = (struct ring_buffer *)malloc(sizeof(struct ring_buffer));
    if (!ring_buf)
    {
        fprintf(stderr,"Failed to malloc memory,errno:%u,reason:%s",
            errno, strerror(errno));
        return ring_buf;
    }
    memset(ring_buf, 0, sizeof(struct ring_buffer));
    ring_buf->buffer = buffer;
    ring_buf->size = size;
    ring_buf->in = 0;
    ring_buf->out = 0;
    return ring_buf;
}
//释放缓冲区
void ring_buffer_free(struct ring_buffer *ring_buf)
{
    if (ring_buf)
    {
    if (ring_buf->buffer)
    {
        free(ring_buf->buffer);
        ring_buf->buffer = NULL;
    }
    free(ring_buf);
    ring_buf = NULL;
    }
}


//缓冲区的长度
uint32_t __ring_buffer_len(const struct ring_buffer *ring_buf)
{
    return (ring_buf->in - ring_buf->out);
}


//从缓冲区中取数据
uint32_t __ring_buffer_get(struct ring_buffer *ring_buf, void * buffer, uint32_t size)
{
    assert(ring_buf || buffer);
    uint32_t len = 0;
    size  = min(size, ring_buf->in - ring_buf->out);        
    /* first get the data from fifo->out until the end of the buffer */
    len = min(size, ring_buf->size - (ring_buf->out & (ring_buf->size - 1)));
    memcpy(buffer, ring_buf->buffer + (ring_buf->out & (ring_buf->size - 1)), len);
    /* then get the rest (if any) from the beginning of the buffer */
    memcpy(buffer + len, ring_buf->buffer, size - len);
    ring_buf->out += size;
    return size;
}
//向缓冲区中存放数据
uint32_t __ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, uint32_t size)
{
    assert(ring_buf || buffer);
    uint32_t len = 0;
    size = min(size, ring_buf->size - ring_buf->in + ring_buf->out);
    /* first put the data starting from fifo->in to buffer end */
    len  = min(size, ring_buf->size - (ring_buf->in & (ring_buf->size - 1)));
    memcpy(ring_buf->buffer + (ring_buf->in & (ring_buf->size - 1)), buffer, len);
    /* then put the rest (if any) at the beginning of the buffer */
    memcpy(ring_buf->buffer, buffer + len, size - len);
    ring_buf->in += size;
    return size;
}


uint32_t ring_buffer_len(const struct ring_buffer *ring_buf)
{
    uint32_t len = 0;
    len = __ring_buffer_len(ring_buf);
    return len;
}


uint32_t ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, uint32_t size)
{
    uint32_t ret;
    ret = __ring_buffer_get(ring_buf, buffer, size);
    //buffer中没有数据
    if (ring_buf->in == ring_buf->out)
      ring_buf->in = ring_buf->out = 0;
    return ret;
}


uint32_t ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, uint32_t size)
{
    uint32_t ret;
    ret = __ring_buffer_put(ring_buf, buffer, size);
    return ret;
    


}
#endif

----------------------------------------------------------------------------------------------------

****.c文件


#include "ring_buffer.h"
#include <pthread.h>
#include <time.h>
#include <stdio.h>


#define  BUFFER_SIZE         1024 * 1024
#define  MAX_VALUE          (long long)6000000000ll    /*数据最大值*/
#define  SECOND_TO_NSECOND   (int)1000000000  /*秒向纳秒转换*/
long long i=0;
long long dataVal=0;


/****************取数据函数*********************/
void * ReadData(void *arg)
{
    struct ring_buffer *ring_buf = (struct ring_buffer *)arg; 
    long long getDataTemp=0; 
    int second1=0;
    int nsecond1=0; 
    FILE *fp;        
    fp=fopen("data.txt","w"); /*打开文件*/ 
      if(!fp)
       {
           fprintf(stderr,"Failed to Open the File!!");
       }
    struct timespec get_start_time;
    struct timespec get_stop_time;


    int  getDataFlag=1;


    while(getDataFlag)
    {
     ring_buffer_get(ring_buf, (void *)&getDataTemp , sizeof(getDataTemp));




      if((getDataTemp > 1000000000) && (getDataTemp < 1000100000))
          {
           fprintf(fp,"%lld  ",getDataTemp);  /*输出获取的数据到文本文件*/
        }


   if(0==getDataTemp)   /*取第一个数据时记录时间*/
      {
          clock_gettime(CLOCK_REALTIME, &get_start_time); 
      }
      if(MAX_VALUE-1==getDataTemp)
         {
         getDataFlag=0;    /*取数据标志位置0结束取数据*/ 
         clock_gettime(CLOCK_REALTIME, &get_stop_time);   /*取最后一个数据时记录时间*/ 
         if(get_stop_time.tv_nsec < get_start_time.tv_nsec)   /*结束时的纳秒值小于开始时的纳秒时进行判断处理*/
               {
             second1=(get_stop_time.tv_sec-get_start_time.tv_sec)-1;
             nsecond1=SECOND_TO_NSECOND+get_stop_time.tv_nsec-get_start_time.tv_nsec;
             }
         else
               {    
             second1=get_stop_time.tv_sec-get_start_time.tv_sec;
             nsecond1=get_stop_time.tv_nsec-get_start_time.tv_nsec;
               }
       printf("Last Get Data: %lld\n",getDataTemp);
       printf("Get Data Complete!\n");
       printf("Get Data Cost Time:%ds %dns\n\n",second1,nsecond1);  /*打印取数据消耗的时间*/ 
        
        }
      
    } 
     if(ring_buffer_len(ring_buf)<=10)    /*取数据过快时减小取数据的速度*/ 
      {
        usleep(1);
      } 
     
    fclose(fp);   /*关闭文件*/ 
    return (void *)ring_buf;
}


/****************写数据函数*********************/
void * WriteData(void *arg)
{


    struct ring_buffer *ring_buf = (struct ring_buffer *)arg;
    struct timespec put_start_time;
    struct timespec put_stop_time;
    int putDataFlag=1;  /*写数据标志为*/ 
    long long *in_data = &dataVal;
    int second=0;
    int nsecond=0;
    while(putDataFlag)
    {
 
      
      ring_buffer_put(ring_buf, (void *)in_data, sizeof(dataVal));
      if(0==dataVal)   /*写第一个数据时记录时间*/
         {
          clock_gettime(CLOCK_REALTIME, & put_start_time); 
         }
      dataVal++;
      if(MAX_VALUE==dataVal) 
         {       
         clock_gettime(CLOCK_REALTIME, &put_stop_time);   /*写最后一个数据时记录时间*/ 
         if(put_stop_time.tv_nsec < put_start_time.tv_nsec)   /*结束时的纳秒值小于开始时的纳秒时进行判断处理*/
             {
            second=(put_stop_time.tv_sec-put_start_time.tv_sec)-1;
            nsecond=SECOND_TO_NSECOND+put_stop_time.tv_nsec-put_start_time.tv_nsec;
             }
        else
             {    
            second=put_stop_time.tv_sec-put_start_time.tv_sec;         
            nsecond=put_stop_time.tv_nsec-put_start_time.tv_nsec;
              }
         printf("Last Put Data: %lld\n",dataVal-1);
         printf("Put Data Complete!\n");
         printf("Put Data Cost Time:%ds %dns\n\n",second,nsecond);   /*打印写数据消耗的时间*/   
         putDataFlag=0;
        }
      
      if(ring_buffer_len(ring_buf)>=BUFFER_SIZE-100)
         {
         usleep(1);
         }   
    }
    
    return (void *)ring_buf;
}


int Pthread_Read(void *arg)
{
    int err;
    pthread_t tid;
    err = pthread_create(&tid, NULL, ReadData, arg);  /*创建读数据线程*/
    if (err != 0)
      {
       fprintf(stderr, "Failed to create consumer thread.errno:%u, reason:%s\n",
       errno, strerror(errno));
       return -1;
      }
    return tid;
}
int Pthread_Write(void *arg)
{
    int err;
    pthread_t tid;
    err = pthread_create(&tid, NULL, WriteData, arg);   /*创建写数据线程*/
    if (err != 0)
    {
    fprintf(stderr, "Failed to create consumer thread.errno:%u, reason:%s\n",
        errno, strerror(errno));
    return -1;
    }
    return tid;
}




int main()
{
    void * buffer = NULL;
    uint32_t size = 0;
    struct ring_buffer *ring_buf = NULL;
    pthread_t consume_pid, produce_pid;


    pthread_mutex_t *f_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(f_lock, NULL) != 0)
    {
    fprintf(stderr, "Failed init mutex,errno:%u,reason:%s\n",
        errno, strerror(errno));
    return -1;
    }
    buffer = (void *)malloc(BUFFER_SIZE);
    if (!buffer)
    {
    fprintf(stderr, "Failed to malloc memory.\n");
    return -1;
    }
    size = BUFFER_SIZE;
    ring_buf = ring_buffer_init(buffer, size, f_lock);
    if (!ring_buf)
    {
    fprintf(stderr, "Failed to init ring buffer.\n");
    return -1;
    }


    printf("Pthread_Write is running.......\n");
    printf("Pthread_Read  is running.......\n\n");
    produce_pid  = Pthread_Write((void*)ring_buf);
    consume_pid  = Pthread_Read((void*)ring_buf);
    pthread_join(produce_pid, NULL);/*等待线程的结束*/
    pthread_join(consume_pid, NULL);
    ring_buffer_free(ring_buf);
    free(f_lock);
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以参考以下代码实现一个简单的Linux kfifo demo: ``` #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/slab.h> #include <linux/kfifo.h> #define FIFO_SIZE 1024 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A Linux kfifo demo"); static char *fifo_buffer; static struct kfifo my_fifo; static int my_open(struct inode *inode, struct file *file) { printk(KERN_INFO "my device opened\n"); return 0; } static int my_close(struct inode *inode, struct file *file) { printk(KERN_INFO "my device closed\n"); return 0; } static ssize_t my_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { ssize_t ret; if (kfifo_is_empty(&my_fifo)) { return -EAGAIN; } ret = kfifo_to_user(&my_fifo, user_buf, count, ppos); if (ret) { printk(KERN_INFO "Read %ld bytes\n", (long)ret); } else { printk(KERN_ERR "Failed to read\n"); } return ret; } static ssize_t my_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { ssize_t ret; if (kfifo_avail(&my_fifo) < count) { return -ENOMEM; } ret = kfifo_from_user(&my_fifo, user_buf, count, ppos); if (ret) { printk(KERN_INFO "Wrote %ld bytes\n", (long)ret); } else { printk(KERN_ERR "Failed to write\n"); } return ret; } static struct file_operations my_fops = { .owner = THIS_MODULE, .open = my_open, .release = my_close, .read = my_read, .write = my_write, }; static int __init my_init(void) { int ret; fifo_buffer = kmalloc(FIFO_SIZE, GFP_KERNEL); if (!fifo_buffer) { return -ENOMEM; } ret = kfifo_init(&my_fifo, fifo_buffer, FIFO_SIZE); if (ret) { kfree(fifo_buffer); return ret; } ret = register_chrdev(0, "my_device", &my_fops); if (ret < 0) { kfifo_free(&my_fifo); kfree(fifo_buffer); return ret; } printk(KERN_INFO "my device registered with major number %d\n", ret); return 0; } static void __exit my_exit(void) { unregister_chrdev(0, "my_device"); kfifo_free(&my_fifo); kfree(fifo_buffer); printk(KERN_INFO "my device unregistered\n"); } module_init(my_init); module_exit(my_exit); ``` 该代码实现了一个简单的字符设备,它使用了Linux内核中提供的kfifo数据结构来实现队列的功能,用户可以通过该设备的文件描述符进行读写操作,读取数据会将队列中的数据写入用户缓冲区,写入数据会将用户缓冲区中的数据写入队列中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值