内核链表
接口
struct list_head { struct list_head *next, *prev;};//初始化head链表LIST_HEAD_INIT(name);//定义并初始化head链表LIST_HEAR(name);//往head链表后插入新元素list_add(struct list_head *new, struct list_head *head);//往head链表尾部插入新元素list_add_tail(struct list_head *new, struct list_head *head);//从链表中删除元素list_del(struct list_head *entry);//删除元素并把元素初始化list_del_init(struct list_head *entry);//替换元素list_replace(struct list_head *old,struct list_head *new);//替换元素并初始化旧元素list_replace_init(struct list_head *old,struct list_head *new);//把元素从链表删除后,再把它添加到head链表后list_move(struct list_head *list, struct list_head *head);//把元素从链表删除后,再把它添加到head链表的尾部list_move_tail(struct list_head *list,struct list_head *head);//判断元素是否是head这个链表的的尾int list_is_last(const struct list_head *list,const struct list_head *head);//遍历head链表 list_for_each(pos, head);//从尾部往前遍历链表list_for_each_prev(pos, head);//使用安全的方式遍历链表,用于遍历的时候修改元素,防止断链,n为临时结构体指针 list_for_each_safe(pos, n, head);//使用安全的方式从尾部往前遍历链表 list_for_each_prev_safe(pos, n, head);//取得链表所在数据结构的整个结构list_entry(ptr, type, member);
链表例子
#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/list.h>struct student{ char name[100]; int num; struct list_head list;};struct student *pstudent;struct student *tmp_student;struct list_head student_list;struct list_head *pos;static int __init list_init(void){ int i=0; //初始化链表头 INIT_LIST_HEAD(&student_list); for(i=0;i<5;i++){ pstudent = (struct student *)kmalloc(sizeof(struct student),GFP_KERNEL); sprintf(pstudent->name,"student%d",i); pstudent->num = i; //将新元素添加在链表头后 //list_add(&pstudent->list,&student_list); //将新元素添加在链表尾部 list_add_tail(&pstudent->list,&student_list); } //遍历链表 list_for_each(pos,&student_list){ //将链表转化链表所在整个数据结构 tmp_student = list_entry(pos,struct student,list); printk("student name:%s,student num:%d\n",tmp_student->name,tmp_student->num); } return 0;}static void __exit list_exit(void){ struct student *pos_tmp,*pos; //使用安全的方式遍历链表 list_for_each_entry_safe(pos,pos_tmp,&student_list,list){ printk("remove student num: %d, student name:%s\n",pos->num,pos->name); //删除链表 list_del(&(pos->list)); kfree(pos); }}module_init(list_init);module_exit(list_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Alex");MODULE_DESCRIPTION("ListModule");MODULE_ALIAS("List Module");
内核环形队列
接口
//头文件#include <linux/kfifo.h>//创建队列 size必须是2的幂.//动态创建int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);/* fifo: 指向kfifo的指针 * size: 动态创建的队列大小 * gfp_mask: GFP_KERNEL 无内存可用时可引起休眠. *///使用自定义Buffer创建和初始化void kfifo_init(struct kfifo *fito, void *buffer, unsigned int size);//入队usinged int kfifo_in(struct kfifo *fifo, const void *from, unsigned int len);;/* 从from中复制len个字节的数据到fifo队列 * fifo: 指向kfifo的指针 * from: 源指针 * len: 复制长度 * 返回值: 返回已复制数据的长度 *///出队unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len);/* 从队列中复制最多len个字节的数据到to * fifo: 指向kfifo的指针 * to: 指向目标buf * len: 复制长度 * 返回值: 返回已复制数据的长度 */unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, unsigned offset);/* 从列表的offset位置开始获取len字节的数据, 队列数据内容不会被改变 * fifo: 指向kfifo的指针 * to: 指向目标buf * len: 复制长度 * offset: 复制起始位置 *///获取队列大小static inline unsigned int kfifo_size(struct kfifo *fifo);/* 返回队列的空间总大小 */static inline unsigned int kfifo_len(struct kfifo *fifo);/* 返回队列中已入队字节数 */static inline unsigned int kfifo_avail(struct kfifo *fifo);/* 返回队列的可用空间的大小. */static inline int kfifo_is_empty(struct kfifo *fifo);/* 测试kfifo是否为空 */static inline int kfifo_is_full(struct kfifo *fifo);/* 测试kfifo是否已满 *///重置和销毁队列static inline void kfifo_reset(struct kfifo *fifo);/* 重置队列 */void kfifo_free(struct kfifo *fifo);/* 销毁用kfifo_alloc()创建的队列 */
队列例子
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kfifo.h>
void prt_kfifo_size(struct kfifo *fifo)
{
printk("kfifo size:%u bytes\n",kfifo_size(fifo));
printk("kfifo len:%u bytes\n",kfifo_len(fifo));
printk("kfifo avail:%u bytes\n",kfifo_avail(fifo));
}
static int kfifo_test_init(void)
{
struct kfifo fifo;
int ret;
int i;
int buf[1024];
int nbytes;
ret = kfifo_alloc(&fifo,1024,GFP_KERNEL);
if (ret){
printk("kfifo alloc fail\n");
return ret;
}
for(i=0;i<32;i++){
kfifo_in(&fifo,&i,sizeof(i));
}
prt_kfifo_size(&fifo);
nbytes = kfifo_out_peek(&fifo,buf,1024);
printk("peek:%d bytes\n",nbytes);
for(i=0;i<nbytes/sizeof(int);i++){
printk("%d\n",buf[i]);
}
printk("\n===== after peek =====\n");
prt_kfifo_size(&fifo);
nbytes = kfifo_out(&fifo,buf,sizeof(int));
printk("out : %d bytes\n",nbytes);
printk("\n===== after out ====\n");
prt_kfifo_size(&fifo);
return 0;
}
static void kfifo_test_exit(void)
{
kfifo_free(&fifo);
}
module_init(kfifo_test_init);
module_exit(kfifo_test_exit);
MODULE_AUTHOR("Alex");
MODULE_LICENSE("GPL");