引用書中原話:
close和release
並不是每一個close系統調用都會引起對release方法的調用。只有那些真正釋放設備數據結構的close調用纔會調用這個方法。內核對每個file結構維護其被使用多少次的計數器。無論是fork還是dup,都不會創建新的數據結構(僅有open創建),它們只是增加已有結構中的計數。只有在file結構的計數歸0時,close系統調用纔會執行release方法,這隻在刪除這個結構時纔會發生。release和close系統調用間的關係保證了每次open驅動程序只會看到對應的一次release調用。
信號量和自旋鎖
簡單的說,自旋鎖在內核中主要用來防止多處理器中併發訪問臨界區,防止內核搶佔造成的競爭。另外自旋鎖不允許任務睡眠(持有自旋鎖的任務睡眠會造成自死鎖——因爲睡眠有可能造成持有鎖的內核任務被重新調度,而再次申請自己已持有的鎖),它能夠在中斷上下文中使用。
信號量和自旋鎖區別
從嚴格意義上講,信號量和自旋鎖屬於不同層次的互斥手段,前者的實現有賴於後者。
注意以下原則:
如果代碼需要睡眠——這往往是發生在和用戶空間同步時——使用信號量是唯一的選擇。由於不受睡眠的限制,使用信號量通常來說更加簡單一些。如果需要在自旋鎖和信號量中作選擇,應該取決於鎖被持有的時間長短。理想情況是所有的鎖都應該儘可能短的被持有,但是如果鎖的持有時間較長的話,使用信號量是更好的選擇。另外,信號量不同於自旋鎖,它不會關閉內核搶佔,所以持有信號量的代碼可以被搶佔。這意味者信號量不會對影響調度反應時間帶來負面影響。
自旋鎖對信號量
需求 建議的加鎖方法
低開銷加鎖 優先使用自旋鎖
短期鎖定 優先使用自旋鎖
長期加鎖 優先使用信號量
中斷上下文中加鎖 使用自旋鎖
持有鎖是需要睡眠、調度 使用信號量
除了鎖之外的方法
免鎖算法————循環緩衝區
原子變量
位操作
seqlock
RCU(read-copy-update)
內存屏障
爲了防止編譯器和硬件的不正確優化,使得對存儲器的訪問順序(其實就是變量)和書寫程序時的訪問順序不一致而提出的一種解決辦法。
#define barrier() __asm__ __volatile__("": : :"memory")
1. 保證編譯器不會對代碼做優化,打亂指令的執行順序。
2. 向CPU發一條指令,保證硬件不會打亂在barrier兩邊的內存訪問指令不會被打亂。
3.memory 強制 gcc 編譯器假設 RAM 所有內存單元均被彙編指令修改,這樣 cpu 中的 registers 和 cache 中已緩存的內存單元中的數據將作廢。cpu 將不得不在需要
的時候重新讀取內存中的數據。這就阻止了 cpu 又將 registers,cache 中的數據用於去優化指令,而避免去訪問內存。