linux内核设计与实践第三版读书笔记

进程提供两种虚拟机制,虚拟cpu和虚拟内存
linux中所有的进程都在一个list中,可以通过下面的方法来访问集成中的子线程
struct task_struct *task;
struct list_head *list;
list_for_each(list,¤t->children)
{
	task=list_entry(list,struct task_struct,sibling);
}
这里的sibling是task_struct中的成员变量,表示这个task的所有子进程
遍历所有进程
struct task_struct *task;
for(task=current;task!=&init_task;task=task->parent)
获取下一个进程
struct task_struct *task;
list_entry(task->tasks.next;struct task_struct,tasks)
获取前一个进程
struct task_struct *task;
list_entry(task->tasks.prev;struct task_struct,tasks)
通过for_each_process可以遍历所有的task
struct task_struct *task;
for_each_process(task)
{
	printk("%s[%d]",task->comm,task->pid);
}
user space 通过fork/clone 来创建新的进程,在kernel中通过kthread_create/kthread_run来创建线程,
其中kthread_create创建的线程不会立即运行,而kthread_run创建的线程会立即运行.
这两者的关系如下:
#define kthread_run(threadfn, data, namefmt, ...)			   \
({									   \
	struct task_struct *__k						   \
		= kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
	if (!IS_ERR(__k))						   \
		wake_up_process(__k);					   \
	__k;								   \
})
可以在内核线程中调用do_exit()或者kthread_stop()来退出内核线程
cfs 调度不在有时间片的概念,而是确保每个进程公平的分配处理器运行时间
在kernel/sched_fair.c中的update_curr()函数会更新sched_entity 
struct sched_entity {
	/* For load-balancing: */
	struct load_weight		load;
	unsigned long			runnable_weight;
	struct rb_node			run_node;
	struct list_head		group_node;
	unsigned int			on_rq;

	u64				exec_start;
	u64				sum_exec_runtime;
	u64				vruntime;
	u64				prev_sum_exec_runtime;

	u64				nr_migrations;

	struct sched_statistics		statistics;

};
static void update_curr(struct cfs_rq *cfs_rq)
{
	struct sched_entity *curr = cfs_rq->curr;
	u64 now = rq_clock_task(rq_of(cfs_rq));
	u64 delta_exec;

	if (unlikely(!curr))
		return;
	#获得单签任务所占用的运行总时间
	delta_exec = now - curr->exec_start;
	if (unlikely((s64)delta_exec <= 0))
		return;
}
调度器的入口是schedule()函数,其要做的事情就会通过pick_next_task()来选择一个高优先级的进程
context_switch()来执行进程的切换
set_tsk_need_resched()来设置进程中的need_resched标志,clear_tsk_need_resched()来清除need_resched标志,need_resched()用来判断这个标志是否置位
用户抢占发生在:从系统调用返回用户空间,从中断处理程序返回用户空间
内核抢占发生在:中断程序返回内核空间之前,内核代码再一次具有可抢占性的时候,内核显示调用是schedule(),内核任务阻塞
用户空间程序可以条用sched_yield()来放弃cpu
遍历链表:list_for_each / list_for_each_entry /list_for_each_entry_reverse
遍历的同时删除list_for_each_entry_safe / list_for_each_entry_safe_reverse
内核中的队列是通过kfifo来实现的
映射是指一个key 关联一个指针
存储大量数据,并且要求检索迅速就用红黑树
异常与中断不同,它产生是必须考虑与处理器的时钟同步,所以异常也被称为同步中断
中断不可以重入,设置IRQF_SHARED标志可以共享中断,用参数dev可以却分是哪个设备的中断
软中断执行的是在:硬中断返回时/ksoftirq,显式调用软中断,软中断的入口函数是do_softirq()
taskset和软中断 可以工作在中断上下文,而workqueue 只能工作在进程上下文。
local_bh_disable/local_bh_enable 可以激活本地处理器的软中断和tasklet的处理
内核的同步方法有:原子操作/自旋锁/读写自旋锁/信号量/读写信号量/互斥体/完成量/顺序锁/顺序和屏障
vfs中的四个主要对象类型是:超级快对象,索引节点对象,目录项对象,文件对象
i/o调度策略:as预测,cfq 完全公正的排队,dealine 最终期限,noop,可以通过命令行仓鼠elevator=as来修改所有块设备的调度策略
使用depmod -A 产生模块依赖,模块依赖信息在/lib/modules/version/modules.dep中

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/81012057