Linux中的内核链表
链表中一般都要进行初始化、插入、删除、显示、释放链表,寻找节点这几个操作,下面我对这几个操作进行简单的介绍,因为我的能力不足,可能有些东西理解的不够深入,造成一定的错误,请各位博友指出。
A、Linux内核链表中的几个主要函数(下面是内核中的源码拿出来给大家分析一下)
1)初始化:
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0) // ptr为struct list_head,其中包括两个指针next和prev,这里已经可以看出内核链表是双向循环链表
2)尾部插入:
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
} //尾部插入,传入的参数是新节点中的两个指针和头结点中的两个指针
3)头部插入函数
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
} //头插入函数,传入的参数是新节点中的两个指针和头结点中的两个指针
4)删除节点函数
static inline void list_del(struct list_head *entry) //传入要删除节点中的指针域
{
__list_del(entry->prev, entry->next);//两个参数分别为所删除节点前一个节点和后一个节点
entry->next = (void *) 0;//删除节点后置为空
entry->prev = (void *) 0;
}
5)显示函数(如果要打印出链表中的信息的话要自己写成打印的函数,比如printf,因为这个其实是一个遍历的函数,没有显示的功能)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/* 这个函数用于遍历链表
pos为节点指针,
head是头结点中的两个指针的地址
member为各节点中的指针域
*/
6)删除链表
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
//这里面的pos和n都是list_head指针,n指针是用于在删除时不让链表断链
7)寻找节点(这也是用的内核中的遍历函数)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
B.下面来段代码给大家看看具体的运用方法
#include"kernel.h" //这是内核链表的头文件,一定要包含
#include<errno.h>
#include<stdio.h>
#include<stdlib.h> typedef struct list_node
{
int data;
struct list_head list;//节点的指针域是被封装在struct list_head这个结构体内
//这个结构体中包括struct list_head *next,*prev
}*node,node1; node init_head(node head)//初始化空链表
{
head = (node)malloc(sizeof(node1));//为节点分配空间
if(head == NULL)
{
perror("head");
return NULL;
}
INIT_LIST_HEAD(&(head->list));//#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while ()//调用内核中的初始化函数,传入的参数是
//节点的中两个指针,即struct list_head结构体中的两个指针
return head;
} node insert_tail(node head,int data)//尾部插入函数
{
node new = (node)malloc(sizeof(node1));//为新节点分配空间
if(new == NULL)//判断一下分配空间是否成功
{
perror("new:");
return NULL;
}
new->data = data;
list_add_tail(&(new->list),&(head->list));//调用内核中的从尾部插入的函数,传入的参数为新节点中的两个指针
//和头结点中的两个指针
return ;
} head_insert_node(node head,int data)//头插入函数
{
node new;//创建一个新节点
new = (node)malloc(sizeof(node1));//为新节点分配空间
if(new == NULL)//判断一下分配空间是否成功
{
perror("new:");
return ;
}
new->data = data;
list_add(&(new->list),&(head->list));//调用内核中从头插入的函数,传入的参数为新节点的两个指针和头结点的两个指针
return ;
} node search_node(node head,int data)//寻找节点函数
{
node p = NULL;
list_for_each_entry(p,&(head->list),list) //内核中的遍历函数
{
if(p->data == data) //p即为需要找的节点
{
printf("found the data:%d\n",p->data);
goto OK;
}
} puts("not found the data!");
return NULL; OK:
return p;
} int show_node(node tmp)
{
if(tmp == NULL)
{
puts("tmp is NULL!");
return -;
}
printf("the data is %d\n",tmp->data);
return ;
} int delete_node(node head,int data)
{
node p = NULL;
list_for_each_entry(p,&(head->list),list)
{
if(p->data == data)
{
printf("found the data which you want to delete!\n");
goto f;
}
} f:
list_del(&(p->list));
free(p);
return ;
} int show_list(node head)
{
node p = NULL;
list_for_each_entry(p,&(head->list),list)
{
printf("data:%d\n",p->data);
}
return ;
} int delete_list(node head)//删除链表函数
{
node p,q;
list_for_each_entry_safe(p,q,&(head->list),list)//这是内核中的安全删除函数
{
list_del(&(p->list));
free(p);
} list_del(&(head->list));
free(head);
return ;
}
int main(int argc,char **argv)
{
node head;
node tmp;
head = init_head(head);//初始化空链表函数
insert_tail(head,);//从末尾插入函数
insert_tail(head,);
insert_tail(head,); head_insert_node(head,);//从头插入函数
show_list(head); //显示链表函数 tmp = search_node(head,);//寻找结点函数
show_node(head);
delete_node(head,);
//show_list(head);
delete_list(head);//删除链表函数
return ;
}
Linux中的内核链表的更多相关文章
- Mysql : L闪存卡linux中的内核参数设置
将 Nytro WarpDrive 加速卡配置为文件系统 本节说明的操作使您可调整 Nytro WarpDrive 加速卡,增强使用 Oracle Linux with Unbreakable Ent ...
- linux中的内核级防火墙(SELINUX)
SElinux是基于内核开发出来的一种安全机制,被称之为内核级加强型防火墙,有力的提升了系统的安全性. SElinux的作用分为两方面:1.在服务上面加上标签: 2.在功能上面限制功能 在linux系 ...
- linux中文件内核数据结构
3.文件io 3.1 文件内核数据结构 3.2 复制文件描述符的内核数据结构 3.3 对指定的描述符打印文件标志 #include "apue.h" #include <fc ...
- 深入分析 Linux 内核链表--转
引用地址:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 一. 链表数据结构简介 链表是一种常用的组织有序数据 ...
- linux内核链表分析
一.常用的链表和内核链表的区别 1.1 常规链表结构 通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系.按照指针域的组织以及各个节 ...
- 深入分析 Linux 内核链表
转载:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/ 一. 链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指 ...
- Linux内核链表-通用链表的实现
最近编程总想着参考一些有名的开源代码是如何实现的,因为要写链表就看了下linux内核中对链表的实现. 链表是一种非常常见的数据结构,特别是在动态创建相应数据结构的情况下更是如此,然而在操作系统内核中, ...
- Linux 内核链表的使用及深入分析【转】
转自:http://blog.csdn.net/BoArmy/article/details/8652776 1.内核链表和普通链表的区别 内核链表是一个双向链表,但是与普通的双向链表又有所区别.内核 ...
- Linux内核链表复用实现栈
我们当然可以根据栈的特性,向实现链表一样实现栈.但是,如果能够复用已经经过实践证明的可靠数据结构来实现栈,不是可以更加高效吗? so,今天我们就复用Linux内核链表,实现栈这样的数据结构. 要实现的 ...
随机推荐
- JavaScript一个鼠标滚动事件的实例
<script type="text/javascript" src="./whenReady.js"></script> <!- ...
- Adobe系列软件下载地址
在前些上传的文章中已经讲了如何激活Adobe系列软件,在这放上Adobe系列软件下载地址: 1.Adobe After Effects 2017-14.0 32位下载地址: 链接:http://pan ...
- 关于Verilog HDL的一些技巧、易错、易忘点(不定期更新)
本文记录一些关于Verilog HDL的一些技巧.易错.易忘点等(主要是语法上),一方面是方便自己忘记语法时进行查阅翻看,另一方面是分享给大家,如果有错的话,希望大家能够评论指出. 关键词: ·技巧篇 ...
- 增强for循环赋值
增强for循环赋值 代码如下: double[] testList01 = new double[5]; java.util.Scanner sc = new java.util.Scanner(Sy ...
- 针对Oracle数据库中SCOTT方案的多表查询一个例子
查询出每个员工的姓名.职位.月薪.所属部门名.月薪等级及其领导的姓名.职位.所属部门名.月薪等级.select e.ename 员工姓名,e.job 员工职位,e.sal 员工月薪,d.dname 员 ...
- 如是使用JS实现页面内容随机显示
之前有个客户咨询我,因为他们公司的业务员有多个人,但公司网站的联系方式板块里只够放一个人的信息,所以就想能不能实现这个联系方式信息随机显示,对于业务或客服人员来说也能做到分配均匀公平.本文我们将和大家 ...
- maven - 引用本地jar,进行jar包移动
背景: 项目为maven工程,部分jar需要需用项目单独修改的本地jar包. 配置好scope后发现构建后引用的jar没有移动到对应的目录,百度后发现需要配置以下依赖 <plugin> & ...
- (转)Spring事务配置的五种方式
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...
- ReentrantLock实现原理及源码分析
ReentrantLock是Java并发包中提供的一个可重入的互斥锁.ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性.只不过相比原生的Sync ...
- Spring Boot整合Dubbo使用及开发笔记
一.概述: Spring Dubbo是我开发的一个基于spring-boot和dubbo,目的是使用Spring boot的风格来使用dubbo.(即可以了解Spring boot的启动过程又可以学习 ...