Linux源码阅读笔记12-RCU案例分析

之前的文章中我们已经了解了RCU机制的原理和Linux的内核源码,这里我们要根据RCU机制写一个demo来展示他应该如何使用。

RCU机制的原理

  • RCU(全称为Read-Copy-Update),它记录所有指向共享数据的指针的使用者,当要修改构想数据时,首先创建一个副本,并在副本中修改,所哟访问线程都离开读临界区后,使用者的指针指向修改后的副本,并且删除旧数据。

  • 他是一种在共享数据结构中实现高效读取和低延迟写入操作的技术。在Linux内核中,RCU是一种基于时间窗口的锁机制,通过充分利用多核处理器和内存系统的特性,在保证并发性的同时提供高性能。

代码示例

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>

struct RCUStruct {

	int a;
	struct rcu_head rcu;
};

static struct RCUStruct* Global_pointer;

static struct task_struct* RCURDThread1, *RCURDThread2, *RCUWTThread;

static int RCURDThreadFunc1(void* argc) {

	struct RCUStruct* pointer = NULL;

	while(1) {

		msleep(5);

		rcu_read_lock();

		mdelay(10);
		pointer = rcu_dereference(Global_pointer);
		if(pointer)
			printk("%s : read a = %d\n", __func__, pointer->a);

		rcu_read_unlock();
	}

	return 0;
}

static int RCURDThreadFunc2(void* argc) {

	struct RCUStruct* pointer = NULL;

	while(1) {

		msleep(5);

		rcu_read_lock();

		mdelay(10);
		pointer = rcu_dereference(Global_pointer);
		if(pointer)
			printk("%s : read a = %d\n", __func__, pointer->a);

		rcu_read_unlock();
	}

	return 0;
}

static void MyRCUDel(struct rcu_head* rcuh) {

	struct RCUStruct* p = container_of(rcuh, struct RCUStruct, rcu);
	printk("%s : a = %d\n", __func__, p->a);
	kfree(p);
}

static int RCUWTThreadFunc(void* argc) {

	struct RCUStruct* old_pointer;
	struct RCUStruct* new_pointer;

	int value = (unsigned long)argc;

	while(1) {

		msleep(10);

		new_pointer = kmalloc(sizeof(struct RCUStruct), GFP_KERNEL);

		old_pointer = Global_pointer;
		*new_pointer = *old_pointer;
		new_pointer->a = value;

		rcu_assign_pointer(Global_pointer, new_pointer);
		call_rcu(&old_pointer->rcu, MyRCUDel);
		printk("%s : write to new %d\n", __func__, value);
		value++;
	}

	return 0;
}

static int __init RCUFuncInit(void) {

	int value = 2;
	printk("Prompt:Successfully initialized the kernel module.\n");

	Global_pointer = kzalloc(sizeof(struct RCUStruct), GFP_KERNEL);

	RCURDThread1 = kthread_run(RCURDThreadFunc1, NULL, "RCURD1");
	RCURDThread2 = kthread_run(RCURDThreadFunc2, NULL, "RCURD2");

	RCUWTThread = kthread_run(RCUWTThreadFunc, (void*)(unsigned long)value, "RCUWT");

	return 0;
}

static void __exit RCUFuncExit(void) {

	printk("Prompt:Successfully uninstalled kernel module!\n");

	kthread_stop(RCURDThread1);
	kthread_stop(RCURDThread2);
	kthread_stop(RCUWTThread);

	if(Global_pointer)
		kfree(Global_pointer);
}

module_init(RCUFuncInit);
module_exit(RCUFuncExit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lenn louis");
  • Makefile
obj-m:=rcu.o	

CURRENT_PAHT:=$(shell pwd) 
LINUX_KERNEL:=$(shell uname -r)   

LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
all:

	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) modules

clean:

	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) cleals

运行结果

推荐课程:https://xxetb.xetslk.com/s/3oyV5o

  • 23
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值