系統調用
內核爲用戶進程提供的交互接口,可以爲用戶進程提供受限制地訪問硬件設備、申請操作系統資源以及創建進程和進程通信等能力。linux中的每個系統調用都對應一個系統調用號,調用號用于指明具體哪個系統調用。
- 系統調用既爲應用程序提供了請求接口,又保證了系統的安全和穩定。用戶空間的程序不能直接訪問內核代碼,內核代碼駐留在受保護的內存地址中,用戶進程無法訪問這塊內存。
- 系統調用在用戶進程和硬件設備之間增加一層,屏蔽了硬件的複雜操作,從而讓應用層的使用更加便捷。
應用編程接口API
實際上應用程序一般會使用用戶空間實現的應用編程接口來間接調用系統調用,API可以通過一個或若幹個系統調用來實現一個接口,而且能屏蔽不同操作系統的差異,爲應用程序提供相同的接口,比如常用的C庫。此外,POSIX標注給出了API和系統調用之間的關系,不同的操作系統提供與POSIX兼容的庫就能讓應用程序實現統一的接口。
對硬件的管理
操作系統內核的核心任務包括對計算機擴展的硬件進行管理,比如硬盤、鍵盤、鼠標及其他擴展硬件。內核必須要能夠與它們互相通信,但通信過程有個很關鍵的問題需要關注,就是速度問題。CPU的速度非常快,但向硬件發起一個請求並接到其響應的速度是相當慢的,如何有效讓它們協同工作是硬件管理的核心問題,因爲這個問題很可能會嚴重影響整體性能。
有兩種實現方:輪詢機制和中斷機制。輪詢機制是讓內核定期對硬件設備進行查詢,看是否需要處理,如果需要則處理,這種情況可能會讓內核做很多無用功。中斷機制則反過來,讓硬件主動來發送信號,當硬件有事件發生時則向內核發出信號,然後內核再介入處理。內核一般也是使用中斷機制來管理硬件。
關于中斷
中斷機制讓硬件能發通知給CPU,中斷本質是一個特殊的電信號,處理器接收到中斷後會馬上告知內核。比如點擊下鼠標時鼠標控制器就會發送一個中斷通知,處理器一旦檢測到中斷信號便中斷自己當前的工作轉而處理中斷,然後通知操作系統鼠標産生了中斷,內核得知鼠標被按下了,然後內核負責處理事件。
不同設備的中斷不同,通過一個唯一的數字作爲標識,也就是鼠標、鍵盤、硬盤的中斷值都不同,操作系統對不同的中斷進行處理。中斷值也稱中斷請求線(IRQ),每個IRQ都對應一個數值,比如PC上0位時鍾中斷、1位鍵盤中斷。當然,也可能是動態分配中斷值。
中斷由硬件打斷操作系統,爲硬件與操作系統提供了通信機制。
中斷處理程序
內核在響應每個特定的中斷時都會執行指定的一個函數,該函數爲中斷處理程序。每個硬件有一個相應的中斷處理程序,他屬于設備驅動的一部分。在linux中,中斷處理程序是一個C函數,這些C函數按照一定的類型聲明,然後內核就可以以標准的方式調用。中斷處理程序被內核調用來響應中斷,它們運行在中斷上下文中,在該上下文中執行的代碼不能夠阻塞。
中斷信號隨時可能發生,所以中斷處理程序隨時可能被運行,必須保證它快速被執行,才能快速恢複中斷代碼的執行。理想狀態是中斷能快速被響應,而且中斷處理程序能快速被執行完。但中斷程序要處理的工作往往有很多,比如對于網絡而言,中斷處理程序要將網卡的數據包拷貝得到內存中,而且還要對其進行處理後才交給合適的協議棧,最終再告知硬件已處理中斷信號。
中斷的上半部和下半部
我們想要快速的中斷響應,同時又想要在中斷處理程序中完成更多的工作,這是一個矛盾體。爲了解決這個問題,中斷處理被分爲上半部和下半部。上半部用于執行有嚴格時限的工作,比如應答硬件。而下半部用于處理能夠延後處理的工作。上半部和下半部其實就是一種異步化處理思想,這樣既能夠保證響應速度,又能夠完成大工作量的處理。
對于網卡來說,它的緩存大小是固定的,一旦網卡接收到數據後內核必須馬上將它們拷貝到內存中,不然將可能導致網卡的緩存爆滿而數據包被丟失。鑒于這種情況,對于網卡的中斷信號處理應該快速將網卡數據包拷貝到內存中,這就是上半部的工作,快速執行完後馬上結束中斷處理,將處理器交還給中斷前的程序。而耗時的數據包處理操作則放到下半部中,這部分可以稍後一點再處理,沒有很強的時效性。
每個設備都有自己的驅動程序,驅動程序可以通過request_irq()函數來注冊中斷處理程序。
中斷上下文
中斷上下文是指內核在執行一個中斷處理程序時所處的上下文,在該上下文中不能睡眠,也不能調用某些函數。中斷處理程序時打斷了其它正在執行的代碼,所以它必須要快速簡潔地執行完畢,中斷處理程序有自己的棧。
linux中斷過程
硬件産生了一個中斷信號,它通過總線將電信號發送給中斷控制器,中斷控制器會將中斷信號發往處理器。處理器會立即停止正在做的事情,然後關閉中斷系統並跳到預定義的位置開始執行代碼,這個預定義的代碼就是由內核設置的中斷處理程序入口。對于每個中斷線,處理器都會跳轉到對應一個唯一的入口位置。內核執行do_IRQ()函數對所接收到的中斷進行響應。
系統定時器
內核大量函數都是基于時間驅動的,比如有些函數周期性地執行,這些就需要定時器來支持。系統定時器是一種可編程硬件芯片,它以固定頻率産生中斷,即定時器中斷,它對應的中斷處理程序負責更新系統時間,同時也負責執行周期性任務。定時器和時鍾中斷處理程序是linux內核管理機制的中樞。
定時器是管理內核流逝時間的基礎,使用定時器時設置一個超時時間,並且指定超時發生時執行的函數。當定時器到時時會自動執行該函數,該函數只運行一次。
內核的時間
內核需要在硬件的幫助下才能計算和管理時間,硬件提供了系統定時器給內核來計算流逝的時間,當時鍾中斷發生時內核的特定中斷處理程序會對其進行處理。定時器以某種頻率自行觸發時間中斷,這個頻率成爲節拍率,連續兩次時間中斷的間隔時間爲節拍。內核通過已知的節拍來計算牆上時間和系統運行時間,牆上時間即是實際時間,系統運行時間爲自系統啓動後開始的時間。內核也爲用戶空間提供了一組獲取實際時間和日期的系統調用。
實時時鍾
實時時鍾(RTC)是用來持久存放系統時間的設備,它可以靠主板上的微型電池保持系統的計時,所以即使系統關閉了也能保持系統時間的計時。實時時鍾和CMOS集成在一起,實時時鍾與BIOS的保存設置都是通過同一個電池供電。系統啓動時內核讀取實時時鍾來初始化牆上時間,該時間對應的變量爲xtime。
基于時間的內核管理
內核很多工作都依賴于時鍾中斷,比如:
- 系統運行時間的更新工作。
- 實際時間的更新工作。
- 在SMP結構中,均衡調度程序中運行隊列的均衡工作。
- 判斷當前進程是否使用完了自己的時間片,調度工作。
- 執行動態定時器。
- 處理器時間的統計工作。
關于節拍率
系統定時器的節拍率提供給靜態預處理定義,單位爲HZ,內核再asm/param.h文件中定義。x86體系中系統定時器頻率默認值爲100,所以時鍾中斷評論爲100HZ,每秒進行時鍾中斷100次,每10ms産生一次。不同的體系結構節拍率可能不同。
更高的節拍率能提供時間驅動時間的解析度,同時也提高時間驅動事件的准確度。對于linux來說能提供更高的精度來執行poll()、select()等系統調用,也能提高進程搶占的准確度。但高節拍率會增加系統負擔,因爲會更加頻繁地執行時鍾中斷處理程序,增加了電源的消耗。
jiffies
jiffies是一個全局變量,它用來記錄自系統啓動以來産生的節拍總數。啓動時爲0,然後每次時鍾中斷都會增加改變了的值,每秒增量爲節拍率,即n赫茲。時鍾中斷處理程序工作大致包括:
- 獲得xtime_lock鎖,對jiffies_64和牆上時間xtime進行保護。
- 應答系統時鍾。
- 使用牆上時間更新實時時鍾。
- 累加jiffies_64。
- 更新當前進程消耗的系統時間和用戶時間。
- 執行已到期的定時器。
- 計算平均負載。