返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >详解C语言内核中的自旋锁结构
  • 489
分享到

详解C语言内核中的自旋锁结构

2024-04-02 19:04:59 489人浏览 安东尼
摘要

提到自旋锁那就必须要说链表,在上一篇《驱动开发:内核中的链表与结构体》文章中简单实用链表结构来存储进程信息列表,相信读者应该已经理解了内核链表的基本使用,本篇文章将讲解自旋锁的简单应

提到自旋那就必须要说链表,在上一篇《驱动开发:内核中的链表与结构体》文章中简单实用链表结构来存储进程信息列表,相信读者应该已经理解了内核链表的基本使用,本篇文章将讲解自旋锁的简单应用,自旋锁是为了解决内核链表读写时存在线程同步问题,解决多线程同步问题必须要用锁,通常使用自旋锁,自旋锁是内核中提供的一种高IRQL锁,用同步以及独占的方式访问某个资源。

首先以简单的链表为案例,链表主要分为单向链表与双向链表,单向链表的链表节点中只有一个链表指针,其指向后一个链表元素,而双向链表节点中有两个链表节点指针,其中Blink指向前一个链表节点flink指向后一个节点,以双向链表为例。

#include <ntifs.h>
#include <ntstrsafe.h>



typedef struct _MyStruct
{
  ULONG x;
  ULONG y;
  LIST_ENTRY lpListEntry;
}MyStruct,*pMyStruct;

VOID UnDriver(PDRIVER_OBJECT driver)
{
  DbgPrint("驱动卸载成功 \n");
}

// By: LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING ReGIStryPath)
{
  DbgPrint("By:LyShark \n");
  DbgPrint("Email:me@lyshark.com \n");
  // 初始化头节点
  LIST_ENTRY ListHeader = { 0 };
  InitializeListHead(&ListHeader);

  // 定义链表元素
  MyStruct testA = { 0 };
  MyStruct testB = { 0 };
  MyStruct testC = { 0 };

  testA.x = 100;
  testA.y = 200;

  testB.x = 1000;
  testB.y = 2000;

  testC.x = 10000;
  testC.y = 20000;

  // 分别插入节点到头部和尾部
  InsertHeadList(&ListHeader, &testA.lpListEntry);
  InsertTailList(&ListHeader, &testB.lpListEntry);
  InsertTailList(&ListHeader, &testC.lpListEntry);

  // 节点不为空 则 移除一个节点
  if (IsListEmpty(&ListHeader) == FALSE)
  {
    RemoveEntryList(&testA.lpListEntry);
  }

  // 输出链表数据
  PLIST_ENTRY pListEntry = NULL;
  pListEntry = ListHeader.Flink;

  while (pListEntry != &ListHeader)
  {
    // 计算出成员距离结构体顶部内存距离
    pMyStruct ptr = CONTAINING_RECORD(pListEntry, MyStruct, lpListEntry);
    DbgPrint("节点元素X = %d 节点元素Y = %d \n", ptr->x, ptr->y);

    // 得到下一个元素地址
    pListEntry = pListEntry->Flink;
  }

  Driver->DriverUnload = UnDriver;
  return STATUS_SUCCESS;
}

链表输出效果如下:

如上所述,内核链表读写时存在线程同步问题,解决多线程同步问题必须要用锁,通常使用自旋锁,自旋锁是内核中提供的一种高IRQL锁,用同步以及独占的方式访问某个资源。

#include <ntifs.h>
#include <ntstrsafe.h>



typedef struct _MyStruct
{
	ULONG x;
	ULONG y;
	LIST_ENTRY lpListEntry;
}MyStruct, *pMyStruct;

// 定义全局链表和全局锁
LIST_ENTRY my_list_header;
KSPIN_LOCK my_list_lock;

// 初始化
void Init()
{
	InitializeListHead(&my_list_header);
	KeInitializeSpinLock(&my_list_lock);
}

// 函数内使用锁
void function_ins()
{
	KIRQL Irql;

	// 加锁
	KeAcquireSpinLock(&my_list_lock, &Irql);

	DbgPrint("锁内部执行 \n");

	// 释放锁
	KeReleaseSpinLock(&my_list_lock, Irql);
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动卸载成功 \n");
}

// By: LyShark
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("By:LyShark \n");
	DbgPrint("Email:me@lyshark.com \n");

	// 初始化链表
	Init();

	// 分配链表空间
	pMyStruct testA = (pMyStruct)ExAllocatePool(NonPagedPoolExecute, sizeof(pMyStruct));
	pMyStruct testB = (pMyStruct)ExAllocatePool(NonPagedPoolExecute, sizeof(pMyStruct));

	// 赋值
	testA->x = 100;
	testA->y = 200;

	testB->x = 1000;
	testB->y = 2000;

	// 向全局链表中插入数据
	if (NULL != testA && NULL != testB)
	{
		ExInterlockedInsertHeadList(&my_list_header, (PLIST_ENTRY)&testA->lpListEntry, &my_list_lock);
		ExInterlockedInsertTailList(&my_list_header, (PLIST_ENTRY)&testB->lpListEntry, &my_list_lock);
	}

	function_ins();

	// 移除节点A并放入到remove_entry中
	PLIST_ENTRY remove_entry = ExInterlockedRemoveHeadList(&testA->lpListEntry, &my_list_lock);

	// 输出链表数据
	while (remove_entry != &my_list_header)
	{
		// 计算出成员距离结构体顶部内存距离
		pMyStruct ptr = CONTAINING_RECORD(remove_entry, MyStruct, lpListEntry);
		DbgPrint("节点元素X = %d 节点元素Y = %d \n", ptr->x, ptr->y);

		// 得到下一个元素地址
		remove_entry = remove_entry->Flink;
	}

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

加锁后执行效果如下:

到此这篇关于详解C语言内核中的自旋锁结构的文章就介绍到这了,更多相关C语言内核 自旋锁内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 详解C语言内核中的自旋锁结构

本文链接: https://lsjlt.com/news/168712.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解C语言内核中的自旋锁结构
    提到自旋锁那就必须要说链表,在上一篇《驱动开发:内核中的链表与结构体》文章中简单实用链表结构来存储进程信息列表,相信读者应该已经理解了内核链表的基本使用,本篇文章将讲解自旋锁的简单应...
    99+
    2024-04-02
  • 详解C语言内核中的链表与结构体
    Windows内核中是无法使用vector容器等数据结构的,当我们需要保存一个结构体数组时,就需要使用内核中提供的专用链表结构LIST_ENTRY通过一些列链表操作函数对结构体进行装...
    99+
    2024-04-02
  • C语言结构体内存对齐详解
    目录实例一:分析:存储结构图如下实例二: 分析:存储结构如下实例三:  分析:存储结构如下 实例四:分析:存储结构图如下总结1、结构体内存对齐...
    99+
    2024-04-02
  • C语言程序中结构体的内存对齐详解
    目录一、为什么存在内存对齐二、结构体的内存对齐四规则三、举例一、为什么存在内存对齐 1.平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某...
    99+
    2022-11-13
    C语言结构体内存对齐 C语言 内存对齐 C语言 结构体
  • 详解C语言中结构体的使用
    目录结构体的声明结构体成员的类型结构体成员的访问结构体的声明 结构体的定义:结构体是一些值的集合,这些值称为成员变量,结构体的每个成员可以是不同类型的变量。 举例: //定义结构体类...
    99+
    2024-04-02
  • C语言循环结构详解
    目录break语句continue语句C语言循环结构一、goto 语句(现在一般很少用) 1.语句介绍: 2.语法结构: 3.goto 语句程序示例: 二、do-while语句 1....
    99+
    2024-04-02
  • C语言结构体struct详解
    目录结构体的概念结构体类型的声明结构体变量的创建typedef关键字结构体的嵌套结构体变量的初始化结构体成员的访问结构体的传参总结结构体的概念 结构体是由一系列具有相同类型或不同类型...
    99+
    2024-04-02
  • C语言之结构体(struct)详解
    目录为什么需要引入结构体struct定义typedef与#define结构体变量初始化及成员访问结构体访问总结为什么需要引入结构体 原有的数据类型不能满足需求,因此才设计了构造类型结...
    99+
    2024-04-02
  • C语言if选择结构语句详解
    目录一.选择结构功能二.选择结构形式三.选择结构分类1.单分支选择结构2.双分支选择结构3.多分支选择结构四.条件表达式总结一.选择结构功能 根据给定的判断条件,控制程序执行流程的语...
    99+
    2024-04-02
  • C语言结构体(struct)的详细讲解
    目录引言1. 动态内存管理2. 结构体2.1 定义语法2.2 定义示例2.3 初始化2.4 结构体赋值2.5 结构体数组2.6 结构体指针赋值3. 学生管理系统附:结构体变量的存储原...
    99+
    2024-04-02
  • Go语言中的结构体详解
    Go语言中的结构体详解 Go语言是一种简单、高效、现代化的编程语言,其结构体是其最重要的数据类型之一。结构体在Go语言中扮演着非常重要的角色,类似于其他编程语言中的类和对象。本文将深入...
    99+
    2024-03-10
    go语言 详解 结构体
  • 详解mysql 中的锁结构
    Mysql 支持3中锁结构 表级锁,开销小,加锁快,不会出现死锁,锁定的粒度大,冲突概率高,并发度最低 行级锁,开销小,加锁慢,会出现死锁,锁定粒度小,冲突概率最低,并发度最高 页面锁,开销和加锁处于表...
    99+
    2022-05-29
    MySQL 锁结构 MySQL
  • C语言结构体超详细讲解
    目录前言1、结构体的声明1.1 结构的基础知识1.2 结构的声明1.3 结构成员的类型1.4 结构体变量的定义和初始化2、结构体成员的访问2.1 点操作符访问2.2 ->操作符...
    99+
    2024-04-02
  • 详解C语言数据结构之栈
    目录栈的链式实现主要内容代码实现:总结栈的链式实现 主要内容 (1) 栈包含7个元素,依次是67,3,88,6,1,7,0,采用尾插入法创建 栈,为该栈设置两个指针,一个bottom...
    99+
    2024-04-02
  • C语言详解热门考点结构体内存对齐
    目录一、为什么存在内存对齐二、如何计算?(考点)三、手撕代码一、为什么存在内存对齐         大...
    99+
    2024-04-02
  • C语言详细分析结构体的内存对齐
    目录一.结构体二.结构体内存对齐1.非嵌套结构体的大小2.含嵌套结构体的大小三.为什么要内存对齐1.平台原因(移植原因)2.性能原因一.结构体 结构体 (struct)是一种数据结构...
    99+
    2024-04-02
  • C语言结构体中内存对齐的问题理解
    目录前言思考结构体在内存中开辟空间时内存对齐的规则为什么存在内存对齐1.平台的原因2.性能的原因前言 学C的同学应该知道~ 想精通C语言就不得不面对—指针与内存 续上次指...
    99+
    2024-04-02
  • C语言中结构体的内存对齐规则讲解
    目录1.结构体的内存对齐规则2.例子3.为什么存在内存对齐4.如何修改默认对齐数1.结构体的内存对齐规则 1.第一个成员在与结构体变量偏移量为0的地址处。 2.其他成员变量都放在对齐...
    99+
    2024-04-02
  • C语言中互斥锁与自旋锁及原子操作使用浅析
    目录互斥锁自旋锁原子操作实操结果互斥锁 临界区资源已经被1个线程占用,另一个线程过来访问临界资源的时候,会被CPU切换线程,不让运行后来的这个线程 适用于 锁住的内容多,(例如红黑数...
    99+
    2023-01-11
    C语言互斥锁 C语言自旋锁 C语言原子操作
  • C语言二叉树的概念结构详解
    目录1、树的概念及结构(了解)1.1树的概念:1.2树的表示法:2、二叉树的概念及结构2.1二叉树的概念2.2特殊的二叉树2.2二叉树的性质2.3二叉树的顺序存储2.4二叉树的链式存...
    99+
    2022-11-13
    C语言二叉树 C语言二叉树的创建
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作