当前位置: 首页 > 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…...

CVPR 2022顶会模型MogFace:5分钟搭建本地高精度人脸检测工具,合影人数统计一键搞定

CVPR 2022顶会模型MogFace&#xff1a;5分钟搭建本地高精度人脸检测工具&#xff0c;合影人数统计一键搞定 1. 项目概述与核心价值 人脸检测作为计算机视觉的基础任务&#xff0c;在安防监控、社交应用、智能摄影等领域有着广泛应用。传统人脸检测工具往往面临两个痛点&#…...

RTKLIB 2.4.2 保姆级安装与配置避坑指南:从下载到RTKNAVI实时定位

RTKLIB 2.4.2 从零到精通的实战指南&#xff1a;避坑技巧与高阶配置 第一次打开RTKLIB压缩包时&#xff0c;面对密密麻麻的文件夹和数十个可执行文件&#xff0c;大多数新手都会陷入迷茫——该从哪里开始&#xff1f;为什么同样的配置别人能跑通而自己总是报错&#xff1f;本文…...

NifSkope:破解3D模型格式壁垒的开源瑞士军刀

NifSkope&#xff1a;破解3D模型格式壁垒的开源瑞士军刀 【免费下载链接】nifskope A git repository for nifskope. 项目地址: https://gitcode.com/gh_mirrors/ni/nifskope 在游戏开发的隐秘角落里&#xff0c;存在着一个被称为"格式迷宫"的困境&#xff1a…...

阿里云盘Refresh Token技术指南:从获取到企业级应用实践

阿里云盘Refresh Token技术指南&#xff1a;从获取到企业级应用实践 【免费下载链接】aliyundriver-refresh-token QR Code扫码获取阿里云盘refresh token For Web 项目地址: https://gitcode.com/gh_mirrors/al/aliyundriver-refresh-token 1. 价值定位&#xff1a;解密…...

MinIO双端口配置全指南:解决Web控制台和Java客户端同时访问的难题

MinIO双端口配置全指南&#xff1a;解决Web控制台和Java客户端同时访问的难题 在云原生存储领域&#xff0c;MinIO凭借其轻量级、高性能和S3兼容性成为众多开发者的首选。然而当我们将MinIO部署在Docker环境中时&#xff0c;经常会遇到一个看似简单却令人困惑的问题&#xff1a…...

保姆级教学:从零部署Qwen3-ASR,打造你的语音转文字工具

保姆级教学&#xff1a;从零部署Qwen3-ASR&#xff0c;打造你的语音转文字工具 1. 引言&#xff1a;为什么选择Qwen3-ASR&#xff1f; 语音识别技术正在改变我们与数字世界互动的方式。想象一下&#xff0c;会议录音自动转文字、方言视频自动生成字幕、智能家居听懂你的指令—…...

OpenClaw故障排查手册:Qwen3-32B镜像连接失败7种解决方案

OpenClaw故障排查手册&#xff1a;Qwen3-32B镜像连接失败7种解决方案 1. 问题背景与典型症状 上周在本地部署Qwen3-32B镜像时&#xff0c;我的OpenClaw突然报出ModelProviderConnectionError错误。这个RTX4090D优化版镜像本应是开箱即用的&#xff0c;但实际对接过程中遇到了…...

如何为Go项目搭建完整的CI/CD流水线:从零到一的自动化部署终极指南

如何为Go项目搭建完整的CI/CD流水线&#xff1a;从零到一的自动化部署终极指南 【免费下载链接】read 项目地址: https://gitcode.com/gh_mirrors/re/read Go语言作为现代高性能编程语言的代表&#xff0c;其项目开发需要高效的持续集成和持续部署流程。本文将为你详细…...

Open-Set检测器调参指南:用Domain Prompter解决跨域风格迁移难题

Open-Set检测器调参实战&#xff1a;Domain Prompter在跨域风格迁移中的高阶应用 当你在开发一个需要识别动漫人物的商品推荐系统时&#xff0c;训练数据可能主要来自写实风格的电商图片&#xff0c;而实际应用中却要处理手绘风格的二次元图像——这正是跨域目标检测&#xff0…...

Candy vs Zerotier:轻量级组网工具横评(含独立网络配置避坑指南)

Candy vs Zerotier&#xff1a;轻量级组网工具深度横评与实战避坑指南 在远程办公和分布式团队成为常态的今天&#xff0c;轻量级组网工具正在重新定义企业内网访问的边界。不同于传统VPN的复杂配置&#xff0c;新一代工具如Candy和Zerotier以"零配置"为卖点&#xf…...