zoukankan      html  css  js  c++  java
  • 简例仿写 Linux 内核链表遍历

    一、测试源程序:

    【 list.h 文件 】

     1 #ifndef _LIST_HEAD_
     2 #define _LIST_HEAD_
     3 
     4 /* 链表节点结构 */
     5 struct list_head {
     6     struct list_head *prev;
     7     struct list_head *next;
     8 };
     9 
    10 /* 初始化链表 */
    11 #define LIST_HEAD_INIT(name) 
    12         {&(name), &(name)}
    13 
    14 /* 创建链表并初始化 */
    15 #define LIST_HEAD(name) 
    16         struct list_head name = LIST_HEAD_INIT(name)
    17 
    18 /* 得到结构体头至某成员的偏移量 */
    19 #define offsetof(type, member)     
    20         ((void*)(&((type*)0)->member))
    21 
    22 /* 由成员地址得到结构体首地址 */
    23 #define container_of(ptr, type, member)    
    24         ((type*)((void*)ptr-offsetof(type, member)))
    25 
    26 /* 链表中插入新节点 */
    27 static inline void _list_add(struct list_head *new,
    28     struct list_head *prev, struct list_head *next)
    29 {
    30     next->prev = new;
    31     prev->next = new;
    32     new->prev = prev;
    33     new->next = next;
    34 }
    35 
    36 #endif

    【 list.c 文件 】

     1 #include <stdio.h>
     2 #include "list.h"
     3 
     4 #define list_entry(ptr, type, member)    
     5         container_of(ptr, type, member)
     6 
     7 /* 利用 ptr 等于 head, 从而得到首个数据节点 */
     8 #define list_first_entry(ptr, type, member)    
     9         list_entry((ptr)->next, type, member)
    10 
    11 /* 遍历整个链表, 得到第个数据节点的结构体基址 */
    12 #define list_for_each_entry(entry, head, member)
    13     for(entry=list_first_entry(head,typeof(*entry),member);            
    14         &(entry)->member!=head;                                        
    15         entry=list_entry((entry)->member.next,typeof(*entry),member))
    16 
    17 /* 自定义三个测试变量 */
    18 struct student_info {
    19     char *name;
    20     struct list_head list;
    21 }xiaoming, xiaoqing, xiaoling;
    22 
    23 /* 从尾部插入新的数据节点 */
    24 void list_add_tail(struct list_head *new,
    25     struct list_head *head)
    26 {
    27     _list_add(new, head->prev, head);
    28 }
    29 
    30 /* 创建链表并初始化 */
    31 static LIST_HEAD(info_list);
    32 
    33 int main()
    34 {
    35     struct student_info *info = NULL;
    36 
    37     /* 初始化成员信息 */
    38     xiaoming.name = "xiao_ming";
    39     xiaoqing.name = "xiao_qing";
    40     xiaoling.name = "xiao_ling";
    41     
    42     /* 插入链表 */
    43     list_add_tail(&xiaoming.list, &info_list);
    44     list_add_tail(&xiaoqing.list, &info_list);
    45     list_add_tail(&xiaoling.list, &info_list);
    46 
    47     /* 遍历测试 */
    48     list_for_each_entry(info, &info_list, list)
    49         puts(info->name);
    50 
    51     return 0;
    52 }

    二、运行结果:

    $ ./a.out
    xiao_ming
    xiao_qing
    xiao_ling
  • 相关阅读:
    已开启博客园~
    友链
    javacv 接收RTSP流(或avi/mp4视频文件),输出byte[]
    Springboot项目中,使用logback来管理日志。
    PPT文件流转为图片,并压缩成ZIP文件输出到指定目录
    通过AOP自定义注解实现记录用户操作日志。
    使用javacv,解码socket接收的H264码流(byte[]),转为yuv处理,最后再合成转为H264
    idea 开始java之旅
    浅谈Winform控件开发(一):使用GDI+美化基础窗口
    WinformGDI+入门级实例——扫雷游戏(附源码)
  • 原文地址:https://www.cnblogs.com/GyForever1004/p/12418931.html
Copyright © 2011-2022 走看看