Linux内核之数据结构--队列

来源:互联网 发布:sum服务器监控软件 编辑:程序博客网 时间:2024/06/15 12:47

前言

Linux内核实现了以下常用的内建数据结构,主要有:
  链表
  队列
  映射
  二叉树
今天详细学习一下队列的知识,内核中的队列是以字节形式保存数据的,所以获取数据的时候,需要知道数据的大小。Linux内核通用队列实现称为kfifo。

kfifo

提供了两个主要操作:enqueue(入队列)和dequeue(出队列)。kfifo对象维护两个偏移量:入口偏移和出口偏移。入口偏移就是下次入队列时的位置,出口偏移就是下一次出队列时的位置。出口偏移总是小于等于入口偏移,否则无意义。

struct kfifo {       unsigned char *buffer;    //the buffer holding the data        unsigned int size;    //the size of the allocated buffer       unsigned int in;    //data is added at offset (in % size)      unsigned int out;//data is extracted from off. (out % size)      spinlock_t *lock;    //protects concurrent modifications };  

创建队列

动态创建和初始化kfifo:

int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);

该函数创建并且初始化一个大小为size的kfifo,同时为之分配了内存(kmalloc函数)。
值得注意的是,size必须是2的幂,若传入的size不是2的幂,函数就会向上扩展至2的幂。
若先前分配了内存空间buffer,将其初始化为kfifo:

void kfifo_init(struct kfifo *fifo, void *buffer, unsigned int size);

静态声明kfifo:

DECLARE_KFIFO(name, size);INIT_KFIFO(name);

推入数据队列

unsigned int kfifo_in(struct kfifo *fifo, const void *from, unsigned int len)

该函数把from指针所指的len字节的数据拷贝到fifo所指队列中。若成功,返回推入数据的字节大小;如果队列中空闲字节小于len,则拷贝剩余空间的字节数;若返回值为0,说明队列已满。

摘取队列数据

unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len);

该函数从fifo队列中拷贝长度为len字节的数据到to指向的缓冲区,成功则返回拷贝的数据长度,若队列中数据大小小于len则返回实际读取的数据长度。
若仅仅是想“偷窥”队列中的数据,而不想真的删除它:

unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, unsigned offset);

其中参数offset指向队列中的索引位置,若该参数为0,则读队列头。

获取队列长度

获取kfifo队列的大小:

static inline unsigned int kfifo_size(struct kfifo *fifo);

获取kfifo队列中已推入数据的大小:

static inline unsigned int kfifo_len(struct kfifo *fifo);

获取kfifo剩余空间的大小:

static inline unsigned int kfifo_avoil(struct kfifo *fifo);

判断队列是否为空:

static inline int kfifo_is_empty(struct kfifo *fifo);//若为空返回非0值,否则返回0

判断队列是否满:

static inline unsigned int kfifo_is_full(struct kfifo *fifo);//若队列已满返回非0值,否则返回0

重置和撤销队列

重置队列就是抛弃队列中的所有数据:

static inline void kfifo_reset(struct kfifo *fifo);

撤销一个使用kfifo_alloc()分配的队列:

void kfifo_free(struct kfifo *fifo);

若是使用kfifo_init()方法创建的队列,就需要手动去释放相关的内存。

0 0
原创粉丝点击