Linux核心設計與實現(原書第3版)筆記

志_祥發表於2014-10-31

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位元組順序轉換為高位優先 

相關文章