顯示具有 企鵝心臟解剖學 標籤的文章。 顯示所有文章
顯示具有 企鵝心臟解剖學 標籤的文章。 顯示所有文章

2013年9月10日 星期二

Linux中斷處理

由於IO設備的速度遠慢於CPU,如果CPU要等待IO動作完成並處理的話,效率是非常差的。透過interrupt機制可解決這問題,當IO動作完成後會發出一個asynchronous interrupt,CPU偵測後會暫停手邊的工作,然後喚醒ISR(interrupt service routine)執行,並處理I/O的請求。
  • interrupt的精神:
    1. interrupt handlers不能進入sleep,所以要避免呼叫叫到一些functions,內部潛在包含了進入sleep的function calls。
    2. 當interrupt handlers部分code要進入critical section,請用spinlocks上鎖,而不是mutexs。
    3. interrupt handlers不能與user space進行資料交換。
    4. interrupt handlers必須要儘速執行完畢。為了確保這一點,最好將執行工作切成兩部分,分別是top half與bottom half。handler的top half部分會儘速完成工作,然後可以晚點執行的工作放在bottom half,可以透softirqs與tasklets達到此目的。
    5. interrupt handlers不能重複被呼叫。當一個handler已經在執行,它的對應IRQ必須要被disable,直到handler執行完畢。
    6. interrupt handlers能被更高權限的handlers中斷。如果要避免被高權限的handlers中斷,你可以將interrupt handler標示為fast handler。但如果太多被標示為fast handlers被導致系統performance下降,因為interrupt latency時間會變長。
  • synchronous interrupt(軟體產生):
    1. 當runtime錯誤發生,會發出此interrupt。
    2. software interrupts,例如system calls。

2013年8月31日 星期六

Linux Linked Lists

Linux本身已經實作了doubly linked lists的資料結構,我們可透過linked lists實現一些功能,底下是一個範例:

定義list節點的資料結構
struct _job_list {
 struct list_head all_jobs; /* 工作清單 */
 void (*worker_handle)(char *); /* 執行工作的function */
 void *worker_data; /* 執行工作所需資料 */
 wait_queue_head_t todo; /* 用於同步boss與worker */
 spinlock_t lock; /* 用於保護工作清單的鎖 */
};

2013年8月24日 星期六

Linux Kernel Threads

很多的drivers會透過Kernel threads(簡稱,kthread)的協助,讓kthread在背景執行扮演服務的角色,然後等待events發生。在等待的過程中,kthread會進入sleep狀態,當事件發生的時候,kthread會被喚醒執行一些time-consuming的工作,如此一來,可防止main thread被blocking住。可透過下面的指令來查看系統上有哪些kthreads:
$ ps -ef
透過上面的指令,可以看到下圖PPID為2的都屬於kthread: 底下是一個kthread的範例,透過insmod載入模組後,會啟動mykthread,然後等待events發生:

2013年8月11日 星期日

Linux Kernel Timers

Kernel依據硬體所提供的不同timer來提供時間相關的服務,例如busy-waiting與sleep-waiting。如果process使用busy-waiting延時等待會浪費掉CPU的時間,反之sleep-waiting可以讓process在等待的這段時間進入睡眠,並交出CPU讓其他的process使用,等時間到了,這process會被叫醒繼續執行。首先,先瞭解一些重要的Kernel Timers變數含義,如jiffies, HZ與xtime。

HZ:
每隔固定週期Linux Kernel會發出timer interrupt,HZ定義每一秒有幾次timer interrupts,而HZ變數是儲存在Kernel變數中,在編譯Kernel之前,可以透過make menuconfig設定此值,設定路徑Processor type and features → Timer frequency (250 HZ):

2013年7月30日 星期二

Linux BogoMIPS

在Linux開機的過程中,通常可以看到這個訊息:Calibrating Delay... xxxx BogoMIPS (lpj=xxxxxxx),表示Kernel在開機過程會計算CPU在一個jiffy時間內能執行多少次的延時迴圈,這個計算過程是依據CPU的處理速度進行校正,校正結果值會儲存在Kernel變數中,此變數稱為loops_per_jiffy,而loops_per_jiffy值經過處理後可得到BogoMIPS值。Bogo是Bogus(偽)意思,而MIPS(Million Instructions Per Secon)是每秒百萬指令,所以BogoMIPS就是假的MIPS。透過此網頁http://www.clifton.nl/bogo-list.html可知道不同處理器所對應的BogoMIPS。

那為什麼需要loops_per_jiffy這個值?因為Kernel Driver有時需要很短且精準的delay (millisecond, microsecond, and nanosecond delays),此時透過jiffies實現delay是不適用,由於單位不夠小,假設Timer Frequency是250HZ,則一個tick相當於4ms,表示最小delay時間只能到4ms。所以Kernel提供 mdelay(), udelay(), 和 ndelay() 這三個函式來達到極短且精準的delay,而這三個函式是透過loops_per_jiffy實現,去計算需要多少個loop operation來得到精確的delay。