Showing posts with label OS. Show all posts
Showing posts with label OS. Show all posts

Sunday, October 10, 2010

Interrupt Service Routines (ISRs) and its declaring in C language

About Interrupt Service Routines (ISRs) & Interrupt
對於Interrupt Service Routines(ISRs)各家有各種版本的解釋,但其實內容大同小異,例如,微軟在Windows CE 5.0的線上文件中對於ISRs有著這樣的說法,
An interrupt service routine (ISR) is a software routine that hardware invokes in response to an interrupt. ISRs examine an interrupt and determine how to handle it. ...... An ISR must perform very fast to avoid slowing down the operation of the device and the operation of all lower priority ISRs. [1]
由上面的最後一句話,我們可以知道ISRs的執行必須是快速的、有效率的,否則可能影響整個系統的運作。另外在Raj Kamal [2]的書上,對於ISR有這麼一段定義:
ISR is also called device driver in case of the devices and called exception or signal or trap handler in case of software interrupts.

Raj Kamal把ISR分成軟體及硬體的面相來說明。的確, Interrupt在我們修OS時,恐龍本OS [3]將Interrupt分成三類:
  1. External Interrupt: 由CPU外的週邊硬體所發出, 如: I/O complete...
  2. Internal Interrupt: CPU執行指令時發生, 如: Overflow, divide by zero...
  3. Software Interrupt: User Program在執行期間需要某項服務(如I/O request)而對OS發出Interrupt
當OS收到Interrupt,會保存目前process的執行狀態且暫停process,而去執行所對應的ISR。 


Declaring ISRs using C language
在C語言中,對於如何使用ISR,並沒有制定一個標準,因此不同的compiler會有不同的宣告方式,底下舉出各種compiler的宣告方式:
  • Borland C
/* Borland C */
void interrupt interrupt_handler(void)
{
    /* do something */
}
  • Watcom C/C++
/* Watcom C/C++ */
void _interrupt interrupt_handler(void)
{
    /* do something */
}
  • IAR
/* IAR declares an ISR like so: */
#pragma vector=TIMER0_OVF_vect
__interrupt void MotorPWMBottom()
{
    // code
}
  • AVR GCC
/* AVR GCC declares an ISR like so: */
ISR(PCINT1_vect)
{
  //code
}

其中, AVR GCC是以macro的方式呈現, 因此需要include底下這個header file
#include <avr/interrupt.h>

An ISR example
在筆者之前一篇文章「How to program the Pololu 3pi Robot using C language - "Motor Control"」中提到, ATmega328p有兩個8-bit timers: Timer0與Timer2, 它們被用來控制電流, 因此時間的控制是很重要的, 假如某個timer發生了overflow就應該做出一些中斷措施, 底下的例子就是每當程式執行中, timer2發生overflow時, ISR的呼叫情形

// this ISR is called every time timer2 overflows
ISR(TIMER2_OVF_vect)
{
 us_times_10 += 1024;
 if (us_times_10 >= 10000)
 {
  timer0_millis++;
  us_times_10 -= 10000;
 }
}

Conclusion
本文收集了不同書本、網站對於Interrupt Service Routines的介紹, 並複習了OS課程中, 「恐龍本」所分類的幾種Interrupt情況, 分成了軟體及硬體兩個面相來描述。另外也介紹四種不同的編譯器對於ISR的使用方式, 最後舉出一個例子, 來介紹「AVR」單晶片在這方面的應用。


Reference
  1. http://msdn.microsoft.com/en-us/library/ms892408.aspx
  2. Embedded Systems: Architecture, Programming and Design, 2/e, by Raj Kamal, Tata McGraw-Hill, 2006
  3. Silberschatz, Galvin, and Gagne, “Operating System Concept,” Sixth Edition, John Wiley & Sons, Inc., 2002.
  4. http://wiki.osdev.org/Interrupt_Service_Routines
  5. AVR-Libc user manual (v1.6.6)

Sunday, January 31, 2010

Locks for Data Synchronization

「簡介」

在OS課程中提到,Process Communication分為兩大類: 「Shared Memory」、「Message Passing」,接下來即是一大串的討論,所針對的便是Shared Memory所可能產生的問題,以及其解決方案,並提出一些有名的例子,像是「Producer/Consumer Problem」、「Dining Philosophers」等等的例子,我們可以發現重點在於怎麼讓其共享的變數或資料能夠「一致」,為了使其一致,必須規定一些存取上的機制,也就是說,當某個process在存取某個變數時,我們希望其它process可以暫緩存取該變數,這樣才能維持資料的一致性以及使其同步(synchronization),因此,我們必須設計一些鎖(Locks),這些鎖使得process可以鎖定正在使用的區段,而避免被其它process存取,這篇文章的目的就是要描述不同鎖的特性。

「Locks」
不同的系統,提供其各自不同特性的鎖,例如SQL Server,在資料庫的處理上需要透過鎖來幫忙整頓transaction,而這邊要介紹的是在Linux系統中「fcntl」 這個system call所提供的locks。

「Shared Lock」VS「Exclusive Lock」
以下這段描述來自IBM solidDB系統的文件[Ref.1],
    An exclusive lock allows only one user/connection to access (read or update) a particular piece of data. A shared lock allows multiple users to read data, but doesn't allow any of them to update the data.
   
    .........

    Shared and exclusive locks cannot be mixed. If you have an exclusive lock on a record, I cannot get a shared lock (or an exclusive lock) on that same record.
其實Linux系統中的「fcntl」所提供的「Shared Lock」及「Exclusive Lock」除了名稱跟IBM solidDB的Locks取得一樣,其功能亦相同。所以說,Shared Lock是可以由多個process所共享,即共同鎖定某個檔案的某個區塊,然而,當已經有一個process對某檔案的某區塊設定了Shared Lock,則其它任何的process就無法對該區塊設定Exclusive Lock;而關於Exclusive Lock,對於某個檔案的某個區塊只能被唯一一個process對其設定Exclusive Lock。


「fcntl系統呼叫的使用」

  • 標頭檔的引入及變數宣告
#include<fcntl.h>
struct flock region1;

  • 使用Shared Lock來鎖定區塊的第5位元組到第10位元組
region1.l_type = F_RDLCK;
region1.l_whence = SEEK_SET;
region1.l_start = 5;
region1.l_len = 5;

  • 使用Exclusive Lock來鎖定區塊的第5位元組到第10位元組      
region1.l_type = F_WRLCK;
region1.l_whence = SEEK_SET;
region1.l_start = 5;
region1.l_len = 5;


 「Examples」
舉例來說,假設有個「Process1」開啟了「fileA」並對這個檔案做一些鎖定如下:
  • 「Process1」利用「Shared Lock」來鎖定「fileA」的第5個Byte到第10個Byte

  • 「Process1」利用「Exclusive Lock」來鎖定「fileA」的第20個Byte到第30個Byte

  • 「fileA」的第20個Byte到第30個Byte只允許「Process1」讀寫 

那麼,當另外有個「Process2」要來對「fileA」做存取時,我們可以看到:
  • 「Process2」可以存取「fileA」中未被「Process1」鎖定的部份

  • 「Process2」對於「fileA」中的第5個Byte到第10個Byte,只能「read」,不能「write」

  • 「Process2」對於「fileA」中的第20個Byte到第30個Byte,不能「read」,也不能「write」

以上就是Shared Lock以及Exclusive Lock的介紹。


[Reference]
[1] http://publib.boulder.ibm.com/infocenter/soliddb/v6r3/index.jsp
[2] Beginning Linux Programming 4/e, Richard Stones and Neil Matthew