内核链表

接口

  1. struct list_head {
  2. struct list_head *next, *prev;
  3. };
  4. //初始化head链表
  5. LIST_HEAD_INIT(name);
  6. //定义并初始化head链表
  7. LIST_HEAR(name);
  8. //往head链表后插入新元素
  9. list_add(struct list_head *new, struct list_head *head);
  10. //往head链表尾部插入新元素
  11. list_add_tail(struct list_head *new, struct list_head *head);
  12. //从链表中删除元素
  13. list_del(struct list_head *entry);
  14. //删除元素并把元素初始化
  15. list_del_init(struct list_head *entry);
  16. //替换元素
  17. list_replace(struct list_head *old,struct list_head *new);
  18. //替换元素并初始化旧元素
  19. list_replace_init(struct list_head *old,struct list_head *new);
  20. //把元素从链表删除后,再把它添加到head链表后
  21. list_move(struct list_head *list, struct list_head *head);
  22. //把元素从链表删除后,再把它添加到head链表的尾部
  23. list_move_tail(struct list_head *list,struct list_head *head);
  24. //判断元素是否是head这个链表的的尾
  25. int list_is_last(const struct list_head *list,const struct list_head *head);
  26. //遍历head链表
  27. list_for_each(pos, head);
  28. //从尾部往前遍历链表
  29. list_for_each_prev(pos, head);
  30. //使用安全的方式遍历链表,用于遍历的时候修改元素,防止断链,n为临时结构体指针
  31. list_for_each_safe(pos, n, head);
  32. //使用安全的方式从尾部往前遍历链表
  33. list_for_each_prev_safe(pos, n, head);
  34. //取得链表所在数据结构的整个结构
  35. list_entry(ptr, type, member);

链表例子

  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/slab.h>
  5. #include <linux/list.h>
  6. struct student
  7. {
  8. char name[100];
  9. int num;
  10. struct list_head list;
  11. };
  12. struct student *pstudent;
  13. struct student *tmp_student;
  14. struct list_head student_list;
  15. struct list_head *pos;
  16. static int __init list_init(void)
  17. {
  18. int i=0;
  19. //初始化链表头
  20. INIT_LIST_HEAD(&student_list);
  21. for(i=0;i<5;i++){
  22. pstudent = (struct student *)kmalloc(sizeof(struct student),GFP_KERNEL);
  23. sprintf(pstudent->name,"student%d",i);
  24. pstudent->num = i;
  25. //将新元素添加在链表头后
  26. //list_add(&pstudent->list,&student_list);
  27. //将新元素添加在链表尾部
  28. list_add_tail(&pstudent->list,&student_list);
  29. }
  30. //遍历链表
  31. list_for_each(pos,&student_list){
  32. //将链表转化链表所在整个数据结构
  33. tmp_student = list_entry(pos,struct student,list);
  34. printk("student name:%s,student num:%d\n",tmp_student->name,tmp_student->num);
  35. }
  36. return 0;
  37. }
  38. static void __exit list_exit(void)
  39. {
  40. struct student *pos_tmp,*pos;
  41. //使用安全的方式遍历链表
  42. list_for_each_entry_safe(pos,pos_tmp,&student_list,list){
  43. printk("remove student num: %d, student name:%s\n",pos->num,pos->name);
  44. //删除链表
  45. list_del(&(pos->list));
  46. kfree(pos);
  47. }
  48. }
  49. module_init(list_init);
  50. module_exit(list_exit);
  51. MODULE_LICENSE("GPL");
  52. MODULE_AUTHOR("Alex");
  53. MODULE_DESCRIPTION("ListModule");
  54. MODULE_ALIAS("List Module");

内核环形队列

接口

  1. //头文件
  2. #include <linux/kfifo.h>
  3. //创建队列 size必须是2的幂.
  4. //动态创建
  5. int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);
  6. /* fifo: 指向kfifo的指针
  7. * size: 动态创建的队列大小
  8. * gfp_mask: GFP_KERNEL 无内存可用时可引起休眠.
  9. */
  10. //使用自定义Buffer创建和初始化
  11. void kfifo_init(struct kfifo *fito, void *buffer, unsigned int size);
  12. //入队
  13. usinged int kfifo_in(struct kfifo *fifo, const void *from, unsigned int len);;
  14. /* 从from中复制len个字节的数据到fifo队列
  15. * fifo: 指向kfifo的指针
  16. * from: 源指针
  17. * len: 复制长度
  18. * 返回值: 返回已复制数据的长度
  19. */
  20. //出队
  21. unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len);
  22. /* 从队列中复制最多len个字节的数据到to
  23. * fifo: 指向kfifo的指针
  24. * to: 指向目标buf
  25. * len: 复制长度
  26. * 返回值: 返回已复制数据的长度
  27. */
  28. unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, unsigned offset);
  29. /* 从列表的offset位置开始获取len字节的数据, 队列数据内容不会被改变
  30. * fifo: 指向kfifo的指针
  31. * to: 指向目标buf
  32. * len: 复制长度
  33. * offset: 复制起始位置
  34. */
  35. //获取队列大小
  36. static inline unsigned int kfifo_size(struct kfifo *fifo);
  37. /* 返回队列的空间总大小 */
  38. static inline unsigned int kfifo_len(struct kfifo *fifo);
  39. /* 返回队列中已入队字节数 */
  40. static inline unsigned int kfifo_avail(struct kfifo *fifo);
  41. /* 返回队列的可用空间的大小. */
  42. static inline int kfifo_is_empty(struct kfifo *fifo);
  43. /* 测试kfifo是否为空 */
  44. static inline int kfifo_is_full(struct kfifo *fifo);
  45. /* 测试kfifo是否已满 */
  46. //重置和销毁队列
  47. static inline void kfifo_reset(struct kfifo *fifo);
  48. /* 重置队列 */
  49. void kfifo_free(struct kfifo *fifo);
  50. /* 销毁用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");