此博客写的匆忙并且全为个人见解,错误之处请大家赶快指出。
linux内核rcu机制,是在多读线程和一个写线程并发情况下对指针的保户机制,多写并发需要加锁。
常应用于链表的数据操作中。
linux内核rculist.h是对链表带rcu保护机制操作函数的实现和封装,位于kernel/include/linux/ruclist.h
下面介绍rculist中的函数或宏
1、list_next
/*
* return the ->next pointer of a list_head in an rcu safe
* way, we must not access it directly
*/
#define list_next_rcu(list) (*((struct list_head __rcu **)(&(list)->next)))
此宏目的是获取list->next成员的地址
# define __rcu __attribute__((noderef, address_space(4))) 标示在地址空间4,并且地址有效
此宏是判断该地址是否有效
2、list_add
/**
* list_add_rcu - add a new entry to rcu-protected list
* @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.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as list_add_rcu()
* or list_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* list_for_each_entry_rcu().
*/
static inline void list_add_rcu(struct list_head *new, struct list_head *head)
{
__list_add_rcu(new, head, head->next);
}
此函数是添加新条目到一个条目之后,是基于__list_add_rcu的上层函数。
/*
* 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_rcu(struct list_head *new,
struct list_head *prev, struct list_head *next)
{
new->next = next;
new->prev = prev;
rcu_assign_pointer(list_next_rcu(prev), new);
next->prev = new;
}
此函数添加一个新条目到两个条目之间
new->next = next;
new->prev = prev;
必须是先给新条目next、prev值,然后再修改旧next、prev条目值,这样让已经获取prev条目值的并发读遍历线程不会中断
rcu_assign_pointer(list_next_rcu(prev), new); 这是给rcu机制保护的指针赋值,list_next_rcu(prev)这是获取前条目的next地址,rcu_assign_pointer这是rcu的发布订阅机制,保证读线程要不就是获取前条目next的旧值,要不就是赋值完成后的新值,这个rcu保护机制是防止编译器优化时将语句顺序优化,从而导致读线程获取的地址是未赋值的或不完全的,出现错误,这个机制是通过smp内存屏障实现的,内存屏障保证指针的内存数据已经赋值完成。
3、/**
* list_add_tail_rcu - add a new entry to rcu-protected list
* @new: new entry to be added
* @head: list head to add it before
*