Linux内核双向链表运用实例

1.1 内核双向链表实现

list_head.c

#include "list_head.h"

void INIT_LIST_HEAD(struct list_head *list)//初始化通用链表
{
    //前后级指针都指向本身
    list->next=list;
    list->prev=list;
}
void list_add(struct list_head *node,struct list_head *head)//插入节点
{
    node->next=head->next;
    node->prev=head;
    head->next->prev=node;
    head->next=node;

}
void list_add_tail(struct list_head *node,struct list_head *head)//尾插
{
    node->next=head->prev;
    node->prev=head;
    head->prev->next=node;
    head->prev=node;
}
void list_del(struct list_head *node)//删除节点
{
        node->prev->next=node->next;
        node->next->prev=node->prev;
}

list_head.h

#ifndef __LIST_HEAD_H__
#define __LIST_HEAD_H__

//通用链表节点类型  双向链表
struct list_head{
    struct list_head *prev; //前级指针
    struct list_head *next;//后级指针
};

void INIT_LIST_HEAD(struct list_head *list);//初始化通用链表
void list_add(struct list_head *node,struct list_head *head);//插入节点
void list_add_tail(struct list_head *node,struct list_head *head);//尾插
void list_del(struct list_head *node);//删除节点

/*遍历链表  依次为:从头节点的下一个节点开始遍历   
*           从头节点的上一个节点开始遍历
*(以list_for_next_each为例理解:首先节点指针pos指向头节点的下一个节点,判断 
pos是否指向头节点,不是的话就向后继续遍历)
*/
#define list_for_next_each(pos,head)\
    for(pos=(head)->next;pos!=(head);pos=pos->next)

#define list_for_prev_each(pos,head)\
    for(pos=(head)->prev;pos!=(head);pos=pos->prev)

//提取数据结构   ptr 是链接因子的指针  type是包含了链接因子的数据类型  member是链接因子成员名。注意:系统不同,指针类型占用的空间不同。
#define container_of(ptr,type,member)\
    (type *)( (long int)ptr - (long int)(&((type *)0)->member) )

#endif

1.2 运用实例

stu.h

#ifndef __STU_H__
#define __STU_H__
#define N 32
#include "list_head.h"
struct STU{
    struct list_head list;//链接因子,放在最前或最后
    int id;
    char name[N];
    char pwd[N];
    float score;
};

#endif

test.c

#include <stdio.h>
#include <stdlib.h>
#include "list_head.h"
#include "stu.h"

#define DBG_MSG(fmt, arg...) do {  \
	printf("[%s] [%-10s] [%-4d] " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##arg); \
} while(0)

int main(int argc, const char *argv[])
{
    int i;
    struct STU *stu;
    struct STU *stup;
    struct list_head *pos;
    struct list_head stu_list;//学生表的首节点

    stu=(struct STU *)malloc(sizeof(struct STU)*5);  //分配节点空间
    if(!stu)
    {
        perror("fail to malloc");
        return -1;
    }

    //初始化通用链表
    INIT_LIST_HEAD(&stu_list);
    for(i=0;i<5;i++)  //赋值学生信息
    {
        stu[i].id=i;
        sprintf(stu[i].name,"stu%d",i);
        sprintf(stu[i].pwd,"160%d",i);
        stu[i].score=10*i;
        list_add(&stu[i].list,&stu_list);//插入链表,头插法
        //list_add_tail(&stu[i].list,&stu_list);//插入链表,尾插发
    }

    //遍历学生信息
    list_for_next_each(pos,&stu_list)
    {
        stup=container_of(pos,struct STU,list);
        printf("stu:id=%d,name=%s,pwd=%s,score=%f\n",\
                stup->id,stup->name,stup->pwd,stup->score);
    }

    puts("--------------------------------");

    list_for_prev_each(pos,&stu_list)
    {
        stup=container_of(pos,struct STU,list);
        //stup=(struct STU *)pos;//如果把通用链表放在结构体首部,则可以不用container_of
        printf("stu:id=%d,name=%s,pwd=%s,score=%f\n",\
                stup->id,stup->name,stup->pwd,stup->score);
    }
    
    return 0;
}

1.3 Makefile

######################################
#
######################################
#source file
#源文件,自动找所有.c和.cpp文件,并将目标定义为同名.o文件
SOURCE  := $(wildcard *.c) $(wildcard *.cpp)
OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
  
#target you can change test to what you want
#目标文件名,输入任意你想要的执行文件名
TARGET  := test
  
#compile and lib parameter
#编译参数
CC      := gcc
LIBS    :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H
  
  
#i think you should do anything here
#下面的基本上不需要做任何改动了
.PHONY : everything objs clean veryclean rebuild
  
everything : clean $(TARGET)

objs : $(OBJS)

rebuild: veryclean everything
                
clean :
	@rm -fr *.so
	@rm -fr *.o
    
veryclean : clean
	@rm -fr $(TARGET)

$(TARGET) : $(OBJS)
	@$(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)
	@chmod +x $(TARGET)
	
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值