内核中的RCU锁
admin
2024-02-17 16:12:13
0

RCU:Read-Copy-Update

已经有自旋锁,信号量,互斥锁等锁机制,为什么还需要RCU锁?
上述锁都使用了原子操作指令,即原子的访问内存,多CPU争用共享变量会让高速缓存一致性变得很糟,使得系统性能下降。

RCU实现目标

  • 读者线程没有开销或者开销很小。
  • 不使用原子操作指令和内存屏障指令也能正常访问。
  • 多写者存在需要额外的保护机制。

RCU实现关键原理
RCU记录了所有指向共享数据的指针的使用者,当要修改共享数据是,首先创建一个副本,在副本中修改,所有读者线程离开读者临街区后,指针指向修改后的副本,并且删除旧数据。

常见应用场景
使用RCU,链表可以有效的提高遍历读取数据的效率,读取链表成员使用rcu_read_lock函数,允许多线程同时读取该链表,并且允许一个线程同时修改链表。

如何保证链表访问的正确性?
读者在遍历链表时,一个线程删除了一个节点。删除线程会把这个节点从链表中移除,但是不会直接销毁它,RCU会等到所有线程读完链表数据后,才销毁这个节点。

RCU提供的接口

  • ruc_read_lock()/rcu_read_unlock,组成一个读者临界区
  • rcu_dereference(), 用于获取被RCU保护的指针,读者线程要访问RCU保护的共享数据,需要使用该函数创建一个新指针,并且指向被RCU保护的指针。
  • rcu_assign_pointer,通常用于写线程,在写者线程完成数据的修改后,调用该接口可以让被RCU保护的指针指向新创建的数据,用RCU的术语是发布更新后的数据。
  • synchronize_rcu,同步等待所有现存的读者访问完成1。
  • call_rcu,注册一个回调函数,当所有现存线程的读访问完成后,调用这个函数销毁旧数据。

测试代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include struct foo {int a;struct rcu_head rcu;
};static struct foo *g_ptr;static int myrcu_reader_thread1(void *data) //读者线程1
{struct foo *p1 = NULL;while (1) {if(kthread_should_stop())break;msleep(20);rcu_read_lock();mdelay(200);p1 = rcu_dereference(g_ptr);if (p1)printk("%s: read a=%d\n", __func__, p1->a);rcu_read_unlock();}return 0;
}static int myrcu_reader_thread2(void *data) //读者线程2
{struct foo *p2 = NULL;while (1) {if(kthread_should_stop())break;msleep(30);rcu_read_lock();mdelay(100);p2 = rcu_dereference(g_ptr);if (p2)printk("%s: read a=%d\n", __func__, p2->a);rcu_read_unlock();}return 0;
}static void myrcu_del(struct rcu_head *rh)
{struct foo *p = container_of(rh, struct foo, rcu);printk("%s: a=%d\n", __func__, p->a);kfree(p);
}static int myrcu_writer_thread(void *p) //写者线程
{struct foo *old;struct foo *new_ptr;int value = (unsigned long)p;while (1) {if(kthread_should_stop())break;msleep(250);new_ptr = kmalloc(sizeof (struct foo), GFP_KERNEL);old = g_ptr;*new_ptr = *old;new_ptr->a = value;rcu_assign_pointer(g_ptr, new_ptr);call_rcu(&old->rcu, myrcu_del);printk("%s: write to new %d\n", __func__, value);value++;}return 0;
}static struct task_struct *reader_thread1;
static struct task_struct *reader_thread2;
static struct task_struct *writer_thread;static int __init my_test_init(void)
{int value = 5;printk("figo: my module init\n");g_ptr = kzalloc(sizeof (struct foo), GFP_KERNEL);reader_thread1 = kthread_run(myrcu_reader_thread1, NULL, "rcu_reader1");reader_thread2 = kthread_run(myrcu_reader_thread2, NULL, "rcu_reader2");writer_thread = kthread_run(myrcu_writer_thread, (void *)(unsigned long)value, "rcu_writer");return 0;
}
static void __exit my_test_exit(void)
{printk("goodbye\n");kthread_stop(reader_thread1);kthread_stop(reader_thread2);kthread_stop(writer_thread);if (g_ptr)kfree(g_ptr);
}
MODULE_LICENSE("GPL");
module_init(my_test_init);
module_exit(my_test_exit);

读临界区

  • 通过rcu_read_lock()和rcu_read_unlock()函数来构建一个读者临界区。
  • 通过rcu_dereference()函数获取被保护数据的副本,即read线程的p1、p2指针,此时的p和g_ptr指针都指向旧的需要被保护的数据。
  • 读者线程延迟一段时间之后读取被保护的数据。

写临界区

  • 分配新的保护数据,并修改数据。
  • rcu_assign_pointer()函数让g_ptr指向新数据new_ptr。
  • call_rcu()函数注册一个回调函数,确保所有对旧数据的引用都执行完成之后,才调用回调函数删除旧数据old_data。
  • 写着线程延迟一段时间之后修改被保护数据。

相关内容

热门资讯

爱情的十字路口我该怎么选择? 爱情的十字路口我该怎么选择?真爱掌握在你自己手中!爱他就努力争取,不顾一切!还不是很爱他,那就等等,...
有没有和《恶魔狂想曲之明日骄阳... 有没有和《恶魔狂想曲之明日骄阳》差不多精彩的小说?女主角很多,个性鲜明,主角多情但不滥情,富于正义文...
功利主义是否认为道德应该是一种... 功利主义是否认为道德应该是一种绝对的命令?最源头的定义是边沁的观点,使所有人的快乐最大化。之后有缪尔...
什么是CC猫啊 什么是CC猫啊CC是一只可爱活泼的猫猫,因为诞生于沪江网校所以全称:沪江网校CC猫。CC猫常常出没于...
美剧迷失第三季好看吗? 美剧迷失第三季好看吗?个人觉得,迷失第一季还不错,很惊异.越往后看越没意思.相信我你会越看越迷失的....
求推荐一些奇幻和爱情主题的动漫 求推荐一些奇幻和爱情主题的动漫刀剑神域 强烈推荐妖精的尾巴哈尔的移动城堡~~强烈推荐刀剑神域!!!...
张晓风的这篇柳运用什么的修辞手... 张晓风的这篇柳运用什么的修辞手法张晓风的这片《柳》运用了比喻,对比的修辞手法。希望我的解答对我有帮助...
我想在手机上看童话书,请问在哪... 我想在手机上看童话书,请问在哪里找?我记得有类似的书,是不是一本红皮的?那个是有点类似杂志或者丛书的...
远古是一个怎样的世界 远古是一个怎样的世界漫漫四十多亿年哪,多长的时间呀,搞不好,以前主宰地球的物种的科技比我们还牛些的!...
有色没胆 有胆没色 有色没胆 有胆没色这两种男人有什么区别?哦这个.有色就是好色也不敢动手.有胆就是胆大不好色.或者是自...
华胥引中君伟的结局 华胥引中君伟的结局君玮最后是和苏仪在一起了。七七微段子里提到的慕言和阿拂家的孩子其实是君玮和苏仪的然...
带烁字的男孩名字 带烁字的男孩名字带烁字的男孩名字,用烁字起名烁(shuò):烁表示光亮、烁亮、烁烁。 繁体:烁;部首...
《披荆斩棘的哥哥》正在热播,看... 《披荆斩棘的哥哥》正在热播,看完这档节目后你有什么观后感?看完这档节目之后,我觉得挺好的,这次的节目...
我女儿的生辰八字:壬午年 丙... 我女儿的生辰八字:壬午年 丙午月 丙寅日 庚寅时 (2002年6月27日农历五月十七日早上...
点读机什么品牌好啊,怎么选啊? 点读机什么品牌好啊,怎么选啊?步步高点读机比较好,选大商场的正品,不要上网或电子市场买。
吴用只是个文弱书生,李逵为何会... 吴用只是个文弱书生,李逵为何会对他言听计从?尽管吴用只是一个文弱书生,但他对李逵忠心耿耿,所以李逵会...
开心星星球里甜心超人魔方玩了4... 开心星星球里甜心超人魔方玩了4秒是哪一集39集,新人。。。第四部《甜心超人的新爱好》
为什么会乐极生悲? 为什么会乐极生悲?从易经的观点看,任何事物都是相对立的。有生就有死,又高就有矮,有长久有段,同样,有...
一千零一夜中给国王讲故事的人是... 一千零一夜中给国王讲故事的人是谁山鲁佐德在《一千零一夜》中给萨桑王国国王讲故事的那位女性就是:萨桑王...
发生在别人身上是故事发生在自己... 发生在别人身上是故事发生在自己身上是事故是什么意思?这句话的意思是:友唯别人的经历或事件通常被视为故...