1. 从内核中寻找各种数据结构的应用,每个找一个例子
结合老师的pdf,内核中的基本数据结构,要查找的是:
双向链表:
出现位置:3c515.c
line: 301
代码: struct list_head list;
Hash链表:
出现位置: Af_decnet.c
line: 155
代码:static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
单向链表:内核无单向链表的定义(所以并没有找到)
出现位置:
line:
代码
红黑树:红黑树定义在 Rbtree.h 和 Rbtree.c 中,在内核中的使用情况是:
出现位置:As-iosched.c
line: 93
代码:struct rb_root sort_list[2];
2. 从内核中寻找同步机制的应用,每个找一个例子
查找关键字:锁的名称
自旋锁:spin_lock (简直太多了)
出现位置:Af_netlink.c
line:387
代码:spin_lock_init(&nlk->cb_lock);
内核信号量:sema_init, init_MUTEX
sema_init:
出现位置:Airo.c
line:2810
代码:sema_init(&ai->sem, 1); (碰巧出现在了自旋锁的后面)
init_MUTEX:
出现位置:Btree.c(fs\hfs) (在B树的c文件里面使用了 互斥信号量)
line:29
代码: init_MUTEX(&tree->tree_lock);
原子变量: atomic_add, atomic_sub , atomic_set,atomic_read
atomic_add:(使用SourceInsight查看Linux源码确实比较方便)
出现位置:Acenic.c (drivers\net):
line:1707
代码:atomic_add(i, &ap->cur_rx_bufs);
ap->rx_std_skbprd= idx;
completion同步机制:wait_for_completion, Complete
wait_for_completion:
As-iosched.c (block):1837
wait_for_completion(ioc_gone);
synchronize_rcu();
kmem_cache_destroy(arq_pool);
cpu变量:DEFINE_PER_CPU
DEFINE_PER_CPU:
Blktrace.c(block):27
staticDEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, };
staticunsigned int blktrace_seq __read_mostly = 1;
我觉得查找已经很熟练了,百度一下这些同步机制的概念。
RCU锁:RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU 保护的共享数据结构,读者不需要获得任何锁就可以访问它,但写者在访问它 时首先拷贝一个副 本,然后对副本进行修改,最后使用一个回调(callback)机制在适当的时机把指向原来数据的 指针重新指向新的被修改的数据。这个时 机就是所有引用该数据的CPU都退出对共享数据的操 作。
顺序锁:Linux 2.6中引入了顺序锁(seqlock),它与读/写自旋锁非常相似,只是它为写者赋予了 较高的优先级:事实上,即使在读者正在读的时候也允许写者继续运行。这种策略的好处是写者 永远不会等待读(除非另外一个写者正在写),缺点是有些时候读者不得不反复读多次相同的数 据直到它获得有效的结果。
然后发觉,也有点不太懂,额,继续进行下去在说。
3. 学习dead_line 调度算法(deadline-iosched.c)中红黑树的应用,重点deadline_add_request从deadline调度算法学习双向链表,hash链表的应用。
Hee
代码:
struct deadline_data {
/*
* run time data
*/
/*
* requests (deadline_rq s) are present on bothsort_list and fifo_list
*/
struct rb_rootsort_list[2]; /*红黑树的根节点*/
struct list_headfifo_list[2]; /*定义一个链表*/
/*
* next in sort order. read, write or both areNULL
*/
structdeadline_rq *next_drq[2];
structhlist_head *hash; /* request hash */ /*hash链表*/
unsigned intbatching; /* number of sequentialrequests made */
sector_tlast_sector; /* head position */
unsigned intstarved; /* times reads have starvedwrites */
/*
* settings that change how the i/o schedulerbehaves
*/
intfifo_expire[2];
int fifo_batch;
intwrites_starved;
intfront_merges;
mempool_t *drq_pool;
};
/*
* add drq torbtree and fifo
*/
static void
deadline_add_request(structrequest_queue *q, struct request *rq)
{
structdeadline_data *dd = q->elevator->elevator_data;
structdeadline_rq *drq = RQ_DATA(rq);
/*放入顺序队列中,这个顺序是sector在磁盘中的顺序*/
const intdata_dir = rq_data_dir(drq->request);
/*将请求加入到deadline调度器的sort_list红黑树中,注意这个函数会去判断rq的方向(读或写)来决定加入那颗树*/
deadline_add_drq_rb(dd,drq);
/*
* set expiretime (only used for reads) and add to fifo list
* 这句话翻译过来就是设置请求超时的时间,也就是说这个请求在
* 这个时间到了必须得到响应。参与调度了。
*/
drq->expires= jiffies + dd->fifo_expire[data_dir];
/*将请求加入deadline调度器的list_fifo链表中*/
list_add_tail(&drq->fifo,&dd->fifo_list[data_dir]);
if(rq_mergeable(rq))
deadline_add_drq_hash(dd,drq);
}
百度一下deadline调度算法,有一位先生的博客写得非常清晰:
link:http://blog.csdn.net/hs794502825/article/details/24664259
参考写出下面文字:
deadline算法的核心就是在传统的电梯算法中加入了请求超时的机制,该机制主要体现在两点:
1、请求超时时,对超时请求的选择。
2、没有请求超时时,当扫描完电梯最后一个request后,准备返回时,对第一个request的选择。基于以上两点,平衡了系统i/o吞吐量和响应时间。
此外,该算法还考虑到了读操作对写操作造成的饥饿。
通过查看这个能理解红黑树的使用。