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

简介: 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

运行结果

相关文章
|
2月前
|
Ubuntu Linux Python
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
在Linux系统中,使用Tkinter库时可能会遇到中文显示乱码的问题,这通常是由于字体支持问题导致的,可以通过更换支持中文的字体来解决。
176 0
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
|
3天前
|
存储 运维 监控
Linux--深入理与解linux文件系统与日志文件分析
深入理解 Linux 文件系统和日志文件分析,对于系统管理员和运维工程师来说至关重要。文件系统管理涉及到文件的组织、存储和检索,而日志文件则记录了系统和应用的运行状态,是排查故障和维护系统的重要依据。通过掌握文件系统和日志文件的管理和分析技能,可以有效提升系统的稳定性和安全性。
20 7
|
6天前
|
监控 安全 Linux
启用Linux防火墙日志记录和分析功能
为iptables启用日志记录对于监控进出流量至关重要
|
25天前
|
人工智能 安全 Linux
|
1月前
|
缓存 算法 Linux
Linux内核中的调度策略优化分析####
本文深入探讨了Linux操作系统内核中调度策略的工作原理,分析了不同调度算法(如CFS、实时调度)在多核处理器环境下的性能表现,并提出了针对高并发场景下调度策略的优化建议。通过对比测试数据,展示了调度策略调整对于系统响应时间及吞吐量的影响,为系统管理员和开发者提供了性能调优的参考方向。 ####
|
2月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
116 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
3月前
|
NoSQL Linux Redis
linux安装单机版redis详细步骤,及python连接redis案例
这篇文章提供了在Linux系统中安装单机版Redis的详细步骤,并展示了如何配置Redis为systemctl启动,以及使用Python连接Redis进行数据操作的案例。
94 2
|
3月前
|
人工智能 监控 Shell
常用的 55 个 Linux Shell 脚本(包括基础案例、文件操作、实用工具、图形化、sed、gawk)
这篇文章提供了55个常用的Linux Shell脚本实例,涵盖基础案例、文件操作、实用工具、图形化界面及sed、gawk的使用。
799 2
|
3月前
|
Unix Linux 网络安全
python中连接linux好用的模块paramiko(附带案例)
该文章详细介绍了如何使用Python的Paramiko模块来连接Linux服务器,包括安装配置及通过密码或密钥进行身份验证的示例。
153 1
|
3月前
|
监控 Linux Shell
30 个实用的 Linux 命令贴与技巧,提升你的效率(附实战案例)
本文介绍了30个实用的Linux命令及其应用场景,帮助你提升命令行操作效率。涵盖返回目录、重新执行命令、查看磁盘使用情况、查找文件、进程管理、网络状态监控、定时任务设置等功能,适合各水平的Linux用户学习和参考。