内核链表
接口
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");