当前位置: 首页 > news >正文

内核链表在用户程序中的移植和使用

基础知识

struct list_head {struct list_head *next, *prev;
};

初始化:

#define LIST_HEAD_INIT(name) { (name)->next = (name); (name)->prev = (name);}

相比于下面这样初始化,前面初始化的好处是,处理链表的时候,不用判空了。太厉害了。

#define LIST_HEAD_INIT(name) { (name)->next = (NULL); (name)->prev = (NULL);}

 遍历链表:

/*** list_for_each	-	iterate over a list* @pos:	the &struct list_head to use as a loop cursor.* @head:	the head for your list.*/
#define list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)

添加节点:(表头开始添加)

/** Insert a new entry between two known consecutive entries.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{next->prev = new;new->next = next;new->prev = prev;prev->next = new;
}/*** list_add - add a new entry* @new: new entry to be added* @head: list head to add it after** Insert a new entry after the specified head.* This is good for implementing stacks.*/
static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}

添加节点:(表尾开始添加) 

/** Insert a new entry between two known consecutive entries.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{next->prev = new;new->next = next;new->prev = prev;prev->next = new;
}
/*** list_add_tail - add a new entry* @new: new entry to be added* @head: list head to add it before** Insert a new entry before the specified head.* This is useful for implementing queues.*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{__list_add(new, head->prev, head);
}

删除节点

/** Delete a list entry by making the prev/next entries* point to each other.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{next->prev = prev;prev->next = next;
}static inline void list_del(struct list_head *entry)
{__list_del(entry->prev, entry->next);LIST_HEAD_INIT(entry);
}

判空:

/*** list_empty - tests whether a list is empty* @head: the list to test.*/
static int list_empty(const struct list_head *head)
{return (head->next) == head;
}

基本功能就这些了

测试代码

#include <stdio.h>
#include <stdlib.h>#define _DEBUG_INFO
#ifdef _DEBUG_INFO#define DEBUG_INFO(format,...)	\printf("%s:%d -- "format"\n",\__func__,__LINE__,##__VA_ARGS__)
#else#define DEBUG_INFO(format,...)
#endifstruct list_head {struct list_head *next, *prev;
};struct rcu_private_data{struct list_head list;
};struct my_list_node{struct list_head node;int number;
};/*** list_for_each	-	iterate over a list* @pos:	the &struct list_head to use as a loop cursor.* @head:	the head for your list.*/
#define list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)#define LIST_HEAD_INIT(name) { (name)->next = (name); (name)->prev = (name);}#define offsetof(TYPE, MEMBER)	((size_t)&((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({				\void *__mptr = (void *)(ptr);					\((type *)(__mptr - offsetof(type, member))); })/*** list_empty - tests whether a list is empty* @head: the list to test.*/
static int list_empty(const struct list_head *head)
{return (head->next) == head;
}/** Insert a new entry between two known consecutive entries.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{next->prev = new;new->next = next;new->prev = prev;prev->next = new;
}/*** list_add - add a new entry* @new: new entry to be added* @head: list head to add it after** Insert a new entry after the specified head.* This is good for implementing stacks.*/
static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}/*** list_add_tail - add a new entry* @new: new entry to be added* @head: list head to add it before** Insert a new entry before the specified head.* This is useful for implementing queues.*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{__list_add(new, head->prev, head);
}/** Delete a list entry by making the prev/next entries* point to each other.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{next->prev = prev;prev->next = next;
}static inline void list_del(struct list_head *entry)
{__list_del(entry->prev, entry->next);LIST_HEAD_INIT(entry);
}static int list_size(struct rcu_private_data *p){struct list_head *pos;struct list_head *head = &p->list;int count = 0;if(list_empty(&p->list)){DEBUG_INFO("list is empty");return 0;}list_for_each(pos,head){count++;}return count;
}static int show_list_nodes(struct rcu_private_data *p){struct list_head *pos;struct list_head *head = &p->list;int count = 0;struct my_list_node *pnode;if(list_empty(&p->list)){DEBUG_INFO("list is empty");return 0;}list_for_each(pos,head){pnode = (struct my_list_node*)container_of(pos,struct my_list_node,node);DEBUG_INFO("pnode->number = %d",pnode->number);count++;}return count;
}int main(int argc, char **argv){int i = 0;static struct my_list_node * new[6];struct rcu_private_data *p = (struct rcu_private_data*)malloc(sizeof(struct rcu_private_data));LIST_HEAD_INIT(&p->list);DEBUG_INFO("list_empty(&p->list) = %d",list_empty(&p->list));for(i = 0;i < 3;i++){new[i] = (struct my_list_node*)malloc(sizeof(struct my_list_node));LIST_HEAD_INIT(&new[i]->node);new[i]->number = i;list_add(&new[i]->node,&p->list);}for(i = 3;i < 6;i++){new[i] = (struct my_list_node*)malloc(sizeof(struct my_list_node));LIST_HEAD_INIT(&new[i]->node);new[i]->number = i;list_add_tail(&new[i]->node,&p->list);}//输出链表节点数DEBUG_INFO("list_size(&p->list) = %d",list_size(p));//遍历链表show_list_nodes(p);//删除指定节点list_del(&new[3]->node);DEBUG_INFO("list_size(&p->list) = %d",list_size(p));//遍历链表show_list_nodes(p);for(i = 0;i < 6;i++){list_del(&new[i]->node);}DEBUG_INFO("list_size(&p->list) = %d",list_size(p));//遍历链表show_list_nodes(p);for(i = 0;i < 6;i++){free(new[i]);}free(p);return 0;
}

 编译

gcc -o app app.c

执行结果:

 小结

相关文章:

内核链表在用户程序中的移植和使用

基础知识 struct list_head {struct list_head *next, *prev; }; 初始化&#xff1a; #define LIST_HEAD_INIT(name) { (name)->next (name); (name)->prev (name);} 相比于下面这样初始化&#xff0c;前面初始化的好处是&#xff0c;处理链表的时候&#xff0c;不…...

使用C#基于ComPDFKit SDK快速构建PDF阅读器

在当今世界&#xff0c;Windows 应用程序对我们的工作至关重要。随着处理 PDF 文档的需求不断增加&#xff0c;将 ComPDFKit PDF 查看和编辑功能集成到您的 Windows 应用程序或系统中&#xff0c;可以极大地为您的用户带来美妙的体验。 在本博客中&#xff0c;我们将首先探索集…...

el-tabel导出excel表格

1、安装插件 npm install file-saver --save npm install xlsx --save 2、引入插件 import FileSaver from "file-saver"; import * as XLSX from xlsx; 3、在tabel中添加ref属性和导出方法 4、添加方法 exportExcel (excelName) {try {const $e this.$refs[repo…...

双击start.bat文件闪退,运行报错“unable to access jarfile”

问题&#xff1a;电脑运行“start.bat”文件&#xff0c;无反应&#xff0c;闪退&#xff0c;管理员身份运行报错“unable to access jarfile” 解决思路&#xff1a; 1、由于该项目运行需要jdk环境&#xff0c;检查jdk版本需要是1.8.0_251版本 通过在 cmd 命令行输入java -v…...

大数据Flink(五十一):Flink的引入和Flink的简介

文章目录 Flink的引入和Flink的简介 一、Flink的引入 1、第1代——Hadoop MapReduce...

c语言的数据类型 -- 与GPT对话

1 c语言的数据类型 在C语言中,数据类型用于定义变量的类型和存储数据的方式。C语言支持多种数据类型,包括基本数据类型和派生数据类型。以下是C语言中常见的数据类型: 基本数据类型(Primary Data Types): int: 整数类型,通常表示带符号的整数。char: 字符类型,用于存储…...

Truffle 进行智能合约测试

其他依赖 node.js、 由于是利用npm进行&#xff0c;所以先设置国内镜像源。去网上搜 1.安装truffle npm install truffle -gtruffle --version 安装完其他项目依赖&#xff0c;能够产生一下效果 2.项目创建 创建test文件夹 mkdir test进入test cd test初始化项目 truffle …...

vb+access库存管理系统设计与实现

第一章库存信息管理系统的基本问题 1.1 库存信息管理系统的简介 本系统是为了提高腾达公司自动化办公的水平、经过详细的调查分析初步制定了腾达公司库存信息管理系统。基于WINDOWS 98 平台,使用Microsoft Access97, 在Visual Basic 6.0编程环境下开发的库存信息管理系统。该…...

机器学习03-数据理解(小白快速理解分析Pima Indians数据集)

机器学习数据理解是指对数据集进行详细的分析和探索&#xff0c;以了解数据的结构、特征、分布和质量。数据理解是进行机器学习项目的重要第一步&#xff0c;它有助于我们对数据的基本属性有全面的了解&#xff0c;并为后续的数据预处理、特征工程和模型选择提供指导。 数据理解…...

Hadoop生态体系-HDFS

目录标题 1、Apache Hadoop2、HDFS2.1 设计目标&#xff1a;2.2 特性&#xff1a;2.3 架构2.4 注意点2.5 HDFS基本操作2.5.1 shell命令选项2.5.2 shell常用命令介绍 3、HDFS基本原理3.1 NameNode 概述3.2 Datanode概述 1、Apache Hadoop Hadoop&#xff1a;允许使用简单的编程…...

《实战AI模型》——赶上GPT3.5的大模型LLaMA 2可免费商用,内含中文模型推理和微调解决方案

目录 准备环境及命令后参数导入: 导入模型: 准备LoRA: 导入datasets: 配置Config:...

工程安全监测无线振弦采集仪在建筑物的应用分析

工程安全监测无线振弦采集仪在建筑物的应用分析 工程安全监测无线振弦采集仪是一种在建筑物中应用的重要设备。它通过无线采集建筑物内部的振动信息&#xff0c;对建筑物的安全性进行监测和评估&#xff0c;为建筑物的施工和使用提供了可靠的技术支持。本文将详细介绍工程安全…...

OpenCV实现照片换底色处理

目录 1.导言 2.引言 3.代码分析 4.优化改进 5.总结 1.导言 在图像处理领域&#xff0c;OpenCV是一款强大而广泛应用的开源库&#xff0c;能够提供丰富的图像处理和计算机视觉功能。本篇博客将介绍如何利用Qt 编辑器调用OpenCV库对照片进行换底色处理&#xff0c;实现更加…...

安科瑞智能型BA系列电流传感器

安科瑞虞佳豪 壹捌柒陆壹伍玖玖零玖叁 选型...

Windows SMB 共享文件夹 排错指南

1 排错可能 是否系统名称为全英文格式 如果不是则 重命名 根据如下排错可能依次设置 1&#xff0c;在运行里面输入"secpol.msc"来启动本地安全设置&#xff0c;\ 然后选择本地策略–>安全选项 -->网络安全LAN 管理器身份验证级别&#xff0c;\ “安全设置”…...

nestjs+typeorm+mysql基本使用学习

初始化项目 安装依赖 npm i -g nest/cli 新建项目 nest new project-name 命令行创建 创建Controller&#xff1a;nest g co test 创建Module&#xff1a;nest g mo test 创建Service&#xff1a;nest g service test 请求创建 123123 接口文档swagger 安装依赖 npm…...

echarts柱状图每根柱子添加警戒值/阈值,分段警戒线

需求&#xff1a;柱状图每根柱子都添加单独的警戒值&#xff08;黄色线部分&#xff09;&#xff0c;效果图如下&#xff1a; 实现方式我这有两种方案&#xff0c;如下介绍。 方案1&#xff1a;使用echarts的标线markLine实现&#xff08;ps&#xff1a;此种方案有弊端&#x…...

边缘提取总结

边缘提取&#xff1a;什么是边缘&#xff1f; 图象的边缘是指图象局部区域亮度变化显著的部分&#xff0c;该区域的灰度剖面一般可以 看作是一个阶跃&#xff0c;既从一个灰度值在很小的缓冲区域内急剧变化到另一个灰度相 差较大的灰度值。 边缘有正负之分&#xff0c;就像…...

intellij 编辑器内性能提示

介绍 IntelliJ IDEA已经出了最新版的2023.2&#xff0c;最耀眼的功能无法两个 AI Assistant编辑器内性能提示 AI Assistant 已经尝试过了是限定功能&#xff0c;因为是基于open ai,所以限定的意思是国内无法使用&#xff0c;今天我们主要介绍是编辑器内性能提示 IntelliJ Pr…...

手机python怎么用海龟画图,python怎么在手机上编程

大家好&#xff0c;给大家分享一下手机python怎么用海龟画图&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 1、如何python手机版创造Al&#xff1f; 如果您想在手机上使用Python来创建AI&#xff08;人工智能&#xff09;程序&#xff0…...

谈谈你对Synchronized关键字的理解及使用

synchronized关键字最主要的三种使用方式的总结 修饰实例方法&#xff0c;作用于当前对象实例加锁&#xff0c;进入同步代码前要获得当前对象实例的锁修饰静态方法&#xff0c;作用于当前类对象加锁&#xff0c;进入同步代码前要获得当前类对象的锁 。也就是给当前类加锁&…...

移动硬盘文件或目录损坏且无法读取

早上插上硬盘&#xff0c;拔的时候不太规范&#xff0c;再插进去就显示无法读取了 搜了很多方法&#xff0c;很多让使用什么软件进行恢复 还参考了这个方法&#xff0c;但是我的属性打开跟博主的完全不一样 最后&#xff0c;参考移动硬盘“文件或目录损坏&#xff0c;无法读取…...

MySQL - 常用的命令

当涉及到具体的数据库操作时&#xff0c;我会给出实际的示例&#xff0c;以更清楚地说明每个命令的用法。 创建数据库&#xff1a; CREATE DATABASE students;列出数据库&#xff1a; SHOW DATABASES;使用数据库&#xff1a; USE students;创建表&#xff1a; CREATE TABL…...

【代理模式】了解篇:静态代理 动态代理~

目录 1、什么是代理模式&#xff1f; 2、静态代理 3、动态代理 3.1 JDK动态代理类 3.2 CGLIB动态代理类 4、JDK动态代理和CGLIB动态代理的区别&#xff1f; 1、什么是代理模式&#xff1f; 定义&#xff1a; 代理模式就是为其他对象提供一种代理以控制这个对象的访问。在某…...

LLM 大语言模型 Prompt Technique 论文精读-3

WebShop: Towards Scalable Real-World Web Interaction with Grounded Language Agents 面向可扩展的基于语言引导的真实世界网络交互 链接&#xff1a;https://arxiv.org/abs/2207.01206 摘要&#xff1a;现有的用于在交互环境中引导语言的基准测试要么缺乏真实世界的语言元…...

架构重构实践心得

一、前言 大多数的技术研发都对重构有所了解&#xff0c;而每个研发又都有自己的理解。从代码重构到架构重构&#xff0c;我参与了携程大型全链路重构项目&#xff0c;积累了一点经验心得&#xff0c;在此抛砖引玉和大家分享。 二、重构的定义 重构是指在不改变外部行为的情…...

【配置环境】Windows下 VS Code 远程连接虚拟机Ubuntu

一&#xff0c;环境 Windows 11 家庭中文版VMware Workstation 16 Pro &#xff08;版本&#xff1a;16.1.2 build-17966106&#xff09;ubuntu-22.04.2-desktop-amd64 二&#xff0c;关键步骤 Windows下安装OpenSSHVS Code安装Remote - SSH插件 三&#xff0c;详细步骤 在Ubun…...

【设计模式——学习笔记】23种设计模式——组合模式Composite(原理讲解+应用场景介绍+案例介绍+Java代码实现)

案例引入 学校院系展示 编写程序展示一个学校院系结构: 需求是这样&#xff0c;要在一个页面中展示出学校的院系组成&#xff0c;一个学校有多个学院&#xff0c;一个学院有多个系 【传统方式】 将学院看做是学校的子类&#xff0c;系是学院的子类&#xff0c;小的组织继承大…...

vue3+Luckysheet实现表格的在线预览编辑(electron可用)

前言&#xff1a; 整理中 官方资料&#xff1a; 1、github 项目地址https://github.com/oy-paddy/luckysheet-vue-importAndExport/tree/master/https://github.com/oy-paddy/luckysheet-vue-importAndExport/tree/master/ 2、xlsx vue3 json数据导出excel_vue3导出excel_羊…...

前端html中让两个或者多个div在一行显示,用style给div加上css样式

文章目录 前言一、怎么让多个div在一行显示 前言 DIV是层叠样式表中的定位技术&#xff0c;全称DIVision&#xff0c;即为划分。有时可以称其为图层。DIV在编程中又叫做整除&#xff0c;即只得商的整数。 DIV元素是用来为HTML&#xff08;标准通用标记语言下的一个应用&#x…...