现在的位置: 首页 > 综合 > 正文

Linux内核设计与实现(原书第3版)笔记

2016年07月28日 ⁄ 综合 ⁄ 共 3529字 ⁄ 字号 评论关闭

Linux内核设计与实现(原书第3版)

跳转至:
导航

搜索
  1. p28 do_fork():有意让child先执行,一般child马上会exec(),避免了CoW的额外开销 ...?
  2. 线程创建/fork/vfork 3者调用clone()时参数的不同
  3. wait4
  4. O(1)调度:根据nice分配时间片
  5. 调度器类?CFS是normal情况下的?
  6. CFS:优化交互任务的实时响应,挑选vruntime最小的那个,rbtree中的leftmost
  7. p47 规划化:
    if(!sleep) se->vruntime -= cfs_rq->min_vruntime;
  8. 休眠进程:位于某个wait_queue上(等待队列使用:inotify_read(),这里是异步IO吗?)
    1. 可中断的:如果收到信号,会提前醒过来
  9. 用户抢占:内核返回user space时,如果need_sched,会导致schedule()调用
  10. 内核抢占:只要没有持有锁,正在执行的代码就是可重入的,也是可抢占的(安全性指的是不会崩溃?但正确性需要用户自己保证?)
    1. thread_info#preempt_count 加锁的次数
    2. if( need_sched && !preempt_count) schedule();
    3. 如果代码自行调用schedule(),它应该保证该抢占调度是安全的
  11. 2种实时调度:SCHED_FIFO(一直执行,除非让出CPU)、SCHED_RR(一直执行,直到时间片用光,带deadline的执行?)
  12. 处理器绑定:task_struct#cpus_allowed sched_setaffinity()
  13. syscall
    1. *为什么getpid()返回的是tgid
    2. 软中断:int $0x80,或sysenter(更快地陷入)
    3. 权限检查:suser() --> capable()
    4. 用户空间访问系统调用(C库的实现方式):_syscalln() n为0~6,代表需要传递的参数个数
    5. 确保你需要syscall,否则使用sysfs更好
  14. 内核数据结构
    1. list_head:要遍历的同时删除,list_for_each_entry_safe(p, next, header, member_name)
    2. 队列 kfifo
    3. idr:映射用户空间UID
    4. rbtree
  15. 中断
    1. 注册:request_irq(irq_number, handler, flags*, name, dev) 由于它最终会调用kmalloc(),可能会睡眠!
    2. 无须可重入
    3. handler:使用spin_lock以避免SMP上其他CPU同时访问
    4. ret_from_intr()
    5. /proc/interrupts
    6. local_irq_disable();之前,先local_irq_save(&flags);安全一点,flags不能传递给另一函数,必须是同一stack frame
    7. 状态判断:in_interrupt()(中断处理)、in_irq()(下半部)
  16. 下半部
    1. 最早的叫bottom half(BH)
    2. 任务队列(task queue):不够灵活,对于性能要求高的网络子系统,不能胜任
    3. 2.3+ 软中断与tasklet:2个不同类型的tasklet可同时执行
    4. 2.5+ 彻底丢弃BH、任务队列 --> 工作队列
    5. 软中断:softirq_action、softirq_vec[NR_SOFTIRQ=32](实际使用9个,映射为优先级?)
    6. tasklets:HI_SOFTIRQ TASKLET_SOFTIRQ(内部用动态的链表组织)
      1. ksoftirqd/n
    7. work queue:退后到某个内核线程执行(!oi see)
      1. workqueue_struct 工作线程worker_thread()
      2. cpuworkqueue_struct 每CPU的
      3. work_struct
    8. 老的任务队列及keventd
  17. 内核同步
    1. atomic_t
    2. spin lock
      1. 如果确定中断在加锁前是激活的,则无须保存irq状态:spin_lock_irq(&lk);//这个函数名其实挺费解的~~
      2. spin_lock_bh():加锁,同时禁止所有下半部的执行
    3. 读写自旋锁(rwlock):递归地获得同一个读锁是安全的
    4. 信号量
      1. 不一致的命名方法:init_MUTEX?
      2. down_interruptable/up(&mr_sem);
      3. rw_semaphore
    5. 互斥体(mutex)指的是任何可以睡眠的强制互斥锁,比如计数为1的信号量
    6. 完成变量(completion)
    7. 历史遗留话题:BLK
    8. 2.6+ 顺序锁(seqlock_t):类似于STM?,seq锁对写更优先
    9. 抢占:preempt_disable(); 支持嵌套
    10. barrier:rmb(); wmb(); read_barrier_depends();*(确保屏障前的读在屏障后的读之前完成)barrier()(编译器屏障)
  18. 定时器和时间管理
    1. HZ:x86默认为100(10ms单位),其他体系结构为250或1000
    2. jiffies
    3. time_before宏:把unsigned long转换为long再相减!
    4. struct timespec xtime; //精确到ns?
    5. timer_list
    6. 延迟执行:e.g.重新设置网卡的以太模式需要2ms
      1. udelay ndelay mdelay BogoMIPS
      2. schedule_timeout()
  19. mm
    1. struct page: 在于描述物理内存本身,而不是包含在里面的数据
    2. struct zone:x86-32上normal区域为16~896MB
    3. kmalloc()
      1. gfp_mask
    4. vmalloc()
    5. slab层
      1. 每个高速缓存:p = kmem_cache("task_struct", sizeof(struct task_struct), ARCH_MIN_TASKALIGN, SLAB_PANIC|SLAB_NOTRACK, NULL);
    6. 内核栈:1或2页,如果1页,则使用单独的中断栈
    7. 高端内存映射:__GFP_HIGHMEM获得的页没有逻辑地址?
      1. 永久映射:kmap 有数量限制
      2. 临时映射:kmap_atomic
    8. 老式的每CPU的分配:data[NR_CPUS] --> get_cpu()禁止内核抢占
    9. 新的每CPU:DEFINE_PER_CPU(type,name); --> get_cpu_var(name)
  20. VFS
    1. 操作对象:{super, inode, dentry, file}_operations
    2. inode
      1. permission(inode,mask):允许特定的访问模式,返回0,支持访问控制链(ACLS)的文件系统需要
      2. setxattr:允许key/value与文件关联(hiden/invisible?)
    3. struct file:没有对应的磁盘数据,通过f_dentry -> 指向相关的inode -> 文件是否dirty
    4. 和文件系统相关的数据结构
      1. struct file_system_type;
      2. struct vfsmount;
    5. 和进程相关数据结构
      1. struct files_struct;
  21. 块I/O层
    1. struct buffer_head; BH_xxx标志,弊端:大块数据的IO分解为多个buffer_head,不必要的负担和空间浪费
    2. struct bio; 代表的是I/O操作,而buffer_head仅描述磁盘的一个块
      1. struct bio_vec: { page, offset, len } 三元组
    3. 请求队列(request_queue)
    4. I/O调度
      1. Linus电梯:尝试合并读请求;防止饥饿;根据扇区位置调整插入(优化物理访问性能?);默认到队列尾部
      2. 最终期限:写是异步的,而读必然是同步阻塞的!--> 减少读请求饥饿现象(降低了全局吞吐量);3个队列:读、写、派发
      3. 预测I/O(默认调度):请求提交后有意空闲片刻,如果这期间应用有相邻的其他读请求,则可提高性能(总感觉这里的设计考虑因素并不多??)
      4. CFQ:I/O请求按进程放入不同队列
      5. Noop:仅执行合并,用于无寻道开销的,如闪存卡
  22. 进程地址空间
    1. mm_struct
    2. vm_area_struct
    3. VMA标志,vm_operations_struct
    4. 可通过内存描述符的mmap和mm_rb域访问内存区域(分别使用list和rbtree)
    5. 页表:PGD、PMD、PTE
  23. 页高速缓存和回写
    1. struct address_space; //physical pages of a file ...

      1. radix_tree
    2. flusher线程、pdflush
  24. 设备与模块
    1. 字符设备(只提供流式访问)、块设备(可随机读写)、网络设备
    2. kobject ktype kset
    3. sysfs:把kobject与dentry联系起来
    4. kobject_uevent():内核空间向用户空间发送信号
  25. 调试
  26. 可移植性
    1. 字节顺序:u32 __cpu_to_be32(u32) 把cpu字节顺序转换为高位优先 

抱歉!评论已关闭.