偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

深入分析Linux內(nèi)核源碼-進(jìn)程調(diào)度(1)

系統(tǒng) Linux
計(jì)算機(jī)最基本的時(shí)間單元是時(shí)鐘周期,例如取指令、執(zhí)行指令、存取內(nèi)存等。時(shí)間系統(tǒng)是計(jì)算機(jī)系統(tǒng)非常重要的組成部分,特別是對(duì)于Unix類(lèi)分時(shí)系統(tǒng)尤為重要。時(shí)間系統(tǒng)主要任務(wù)是維持系統(tǒng)時(shí)間并且防止某個(gè)進(jìn)程獨(dú)占CPU及其他資源,也就是驅(qū)動(dòng)進(jìn)程的調(diào)度。

1 Linux時(shí)間系統(tǒng)

計(jì)算機(jī)最基本的時(shí)間單元是時(shí)鐘周期,例如取指令、執(zhí)行指令、存取內(nèi)存等。時(shí)間系統(tǒng)是計(jì)算機(jī)系統(tǒng)非常重要的組成部分,特別是對(duì)于Unix類(lèi)分時(shí)系統(tǒng)尤為重要。時(shí)間系統(tǒng)主要任務(wù)是維持系統(tǒng)時(shí)間并且防止某個(gè)進(jìn)程獨(dú)占CPU及其他資源,也就是驅(qū)動(dòng)進(jìn)程的調(diào)度。

1.1 時(shí)鐘硬件

大部分PC機(jī)中有兩個(gè)時(shí)鐘源,他們分別叫做RTC和OS(操作系統(tǒng))時(shí)鐘。RTC(Real Time Clock,實(shí)時(shí)時(shí)鐘)也叫做CMOS時(shí)鐘,它是PC主機(jī)板上的一塊芯片,它靠電池供電,即使系統(tǒng)斷電,也可以維持日期和時(shí)間。由于它獨(dú)立于操作系統(tǒng),所以也被稱(chēng)為硬件時(shí)鐘,它為整個(gè)計(jì)算機(jī)提供一個(gè)計(jì)時(shí)標(biāo)準(zhǔn),是最原始***層的時(shí)鐘數(shù)據(jù)。

Linux只用RTC來(lái)獲得時(shí)間和日期;然而,通過(guò)作用于/dev/rtc設(shè)備文件,也允許進(jìn)程對(duì)RTC編程。通過(guò)執(zhí)行/sbin/clock系統(tǒng)程序,系統(tǒng)管理員可以配置時(shí)鐘。

OS時(shí)鐘產(chǎn)生于PC主板上的定時(shí)/計(jì)數(shù)芯片,由操作系統(tǒng)控制這個(gè)芯片的工作,OS時(shí)鐘的基本單位就是該芯片的計(jì)數(shù)周期。在開(kāi)機(jī)時(shí)操作系統(tǒng)取得RTC中的時(shí)間數(shù)據(jù)來(lái)初始化OS時(shí)鐘,然后通過(guò)計(jì)數(shù)芯片的向下計(jì)數(shù)形成了OS時(shí)鐘,它更應(yīng)該被稱(chēng)為一個(gè)計(jì)數(shù)器。OS時(shí)鐘只在開(kāi)機(jī)時(shí)才有效,而且完全由操作系統(tǒng)控制,所以也被稱(chēng)為軟時(shí)鐘或系統(tǒng)時(shí)鐘。下面我們重點(diǎn)描述OS時(shí)鐘的產(chǎn)生。

OS時(shí)鐘輸出脈沖信號(hào),接到中斷控制器上,產(chǎn)生中斷信號(hào),觸發(fā)后面要講的時(shí)鐘中斷,由時(shí)鐘中斷服務(wù)程序維持OS時(shí)鐘的正常工作。

1.2 時(shí)鐘運(yùn)作機(jī)制

RTC和OS時(shí)鐘之間的關(guān)系通常也被稱(chēng)作操作系統(tǒng)的時(shí)鐘運(yùn)作機(jī)制。一般來(lái)說(shuō),RTC是OS時(shí)鐘的時(shí)間基準(zhǔn),操作系統(tǒng)通過(guò)讀取RTC來(lái)初始化OS時(shí)鐘,此后二者保持同步運(yùn)行,共同維持著系統(tǒng)時(shí)間。保持同步運(yùn)行是什么意思呢?就是指操作系統(tǒng)運(yùn)行過(guò)程中,每隔一個(gè)固定時(shí)間會(huì)刷新或校正RTC中的信息。

圖2 時(shí)鐘運(yùn)作機(jī)制

我們可以看到,RTC處于***層,提供最原始的時(shí)鐘數(shù)據(jù)。OS時(shí)鐘建立在RTC之上,初始化完成后將完全由操作系統(tǒng)控制,和RTC脫離關(guān)系。操作系統(tǒng)通過(guò)OS時(shí)鐘提供給應(yīng)用程序所有和時(shí)間有關(guān)的服務(wù)。

1.3 Linux時(shí)間基準(zhǔn)

以上我們了解了RTC(實(shí)時(shí)時(shí)鐘、硬件時(shí)鐘)和OS時(shí)鐘(系統(tǒng)時(shí)鐘、軟時(shí)鐘)。下面我們具體描述OS時(shí)鐘。OS時(shí)鐘是由可編程定時(shí)/計(jì)數(shù)器產(chǎn)生的輸出脈沖觸發(fā)中斷而產(chǎn)生的。輸出脈沖的周期叫做一個(gè)“時(shí)鐘滴答”。計(jì)算機(jī)中的時(shí)間是以時(shí)鐘滴答為單位的,每一次時(shí)鐘滴答,系統(tǒng)時(shí)間就會(huì)加1。操作系統(tǒng)根據(jù)當(dāng)前時(shí)鐘滴答的數(shù)目就可以得到以秒或毫秒等為單位的其他時(shí)間格式。

定義“時(shí)間基準(zhǔn)”的目的是為了簡(jiǎn)化計(jì)算,這樣計(jì)算機(jī)中的時(shí)間只要表示為從這個(gè)時(shí)間基準(zhǔn)開(kāi)始的時(shí)鐘滴答數(shù)就可以了?!皶r(shí)間基準(zhǔn)是由操作系統(tǒng)的設(shè)計(jì)者規(guī)定的。例如DOS的時(shí)間基準(zhǔn)是1980年1月1日,Unix的時(shí)間基準(zhǔn)是1970年1月1日上午12點(diǎn),Linux的時(shí)間基準(zhǔn)是1970年1月1日凌晨0點(diǎn)。

1.4 Linux的時(shí)間系統(tǒng)

OS時(shí)鐘記錄的時(shí)間也就是通常所說(shuō)的系統(tǒng)時(shí)間。系統(tǒng)時(shí)間是以“時(shí)鐘滴答”為單位的,而時(shí)鐘中斷的頻率決定了一個(gè)時(shí)鐘滴答的長(zhǎng)短,例如每秒有100次時(shí)鐘中斷,那么一個(gè)時(shí)鐘滴答的就是10毫秒(記為10ms),相應(yīng)地,系統(tǒng)時(shí)間就會(huì)每10ms增1。

Linux中用全局變量jiffies表示系統(tǒng)自啟動(dòng)以來(lái)的時(shí)鐘滴答數(shù)目。在/kernel/time.c中定義如下:

unsigned long volatile jiffies

在jiffies基礎(chǔ)上,Linux提供了如下適合人們習(xí)慣的時(shí)間格式,在/include/linux/time.h中定義如下:

struct timespec {/* 這是精度很高的表示*/

long tv_sec; /* 秒 (second) */

long tv_nsec;  /* 納秒:十億分之一秒( nanosecond)*/

};

struct timeval {/* 普通精度*/

int tv_sec; /* 秒*/

int tv_usec;  /* 微秒:百萬(wàn)分之一秒(microsecond)*/

};

struct timezone {/* 時(shí)區(qū) */

int tz_minuteswest;/* 格林尼治時(shí)間往西方的時(shí)差 */

int tz_dsttime;/* 時(shí)間修正方式 */

};

tv_sec表示秒(second),tv_usec表示微秒(microsecond),tv_nsec表示納秒(nanosecond)。定義tb_usec和tv_nsec的目的是為了適用不同的使用要求,不同的場(chǎng)合根據(jù)對(duì)時(shí)間精度的要求選用這兩種表示。另外,Linux還定義了用于表示更加符合大眾習(xí)慣的時(shí)間表示:年、月、日。但是萬(wàn)變不離其宗,所有的時(shí)間應(yīng)用都是建立在jiffies基礎(chǔ)之上的。簡(jiǎn)而言之,jiffies產(chǎn)生于時(shí)鐘中斷!

2 時(shí)鐘中斷

#p#

2.1 時(shí)鐘中斷的產(chǎn)生

“時(shí)鐘中斷”是特別重要的一個(gè)中斷,因?yàn)檎麄€(gè)操作系統(tǒng)的活動(dòng)都受到它的激勵(lì)。系統(tǒng)利用時(shí)鐘中斷維持系統(tǒng)時(shí)間、促使環(huán)境的切換,以保證所有進(jìn)程共享CPU;利用時(shí)鐘中斷進(jìn)行記帳、監(jiān)督系統(tǒng)工作以及確定未來(lái)的調(diào)度優(yōu)先級(jí)等工作。可以說(shuō),“時(shí)鐘中斷”是整個(gè)操作系統(tǒng)的脈搏。

時(shí)鐘中斷的物理產(chǎn)生如圖3所示:

圖3 8253和8259A的物理連接方式

脈沖信號(hào)接到中斷控制器8259A_1的0號(hào)管腳,觸發(fā)一個(gè)周期性的中斷,我們就把這個(gè)中斷叫做時(shí)鐘中斷,時(shí)鐘中斷的周期,也就是脈沖信號(hào)的周期,我們叫做“滴答”或“時(shí)標(biāo)”(tick)。從本質(zhì)上說(shuō),時(shí)鐘中斷只是一個(gè)周期性的信號(hào),完全是硬件行為,該信號(hào)觸發(fā)CPU去執(zhí)行一個(gè)中斷服務(wù)程序,我們就把這個(gè)服務(wù)程序叫做時(shí)鐘中斷。

2.2.Linux實(shí)現(xiàn)時(shí)鐘中斷的全過(guò)程

1. 和時(shí)鐘中斷相關(guān)的函數(shù)

下面我們看時(shí)鐘中斷觸發(fā)的服務(wù)程序,該程序代碼比較復(fù)雜,分布在不同的源文件中,主要包括如下函數(shù):

時(shí)鐘中斷程序:timer_interrupt( );

中斷服務(wù)通用例程do_timer_interrupt();

時(shí)鐘函數(shù):do_timer( );

中斷安裝程序:setup_irq( );

中斷返回函數(shù):ret_from_intr( );

前三個(gè)函數(shù)的調(diào)用關(guān)系如下:

timer_interrupt( )

do_timer_interrupt()

do_timer( )

(1) timer_interrupt( )

這個(gè)函數(shù)大約每10ms被調(diào)用一次,實(shí)際上, timer_interrupt( )函數(shù)是一個(gè)封裝例程,它真正做的事情并不多,該函數(shù)主要語(yǔ)句就是調(diào)用do_timer_interrupt()函數(shù)。

(2) do_timer_interrupt()

do_timer_interrupt()函數(shù)有兩個(gè)主要任務(wù),一個(gè)是調(diào)用do_timer( ),另一個(gè)是維持實(shí)時(shí)時(shí)鐘(RTC,每隔一定時(shí)間段要回寫(xiě)),其實(shí)現(xiàn)代碼在/arch/i386/kernel/time.c中, 為了突出主題,筆者對(duì)以下函數(shù)作了改寫(xiě),以便于讀者理解:

static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)

{

do_timer(regs); /* 調(diào)用時(shí)鐘函數(shù),將時(shí)鐘函數(shù)等同于時(shí)鐘中斷未嘗不可*/

if(xtime.tv_sec > last_rtc_update + 660)

update_RTC();

/*每隔11分鐘就更新RTC中的時(shí)間信息,以使OS時(shí)鐘和RTC時(shí)鐘保持同步,11分鐘即660秒,xtime.tv_sec的單位是秒,last_rtc_update記錄的是上次RTC更新時(shí)的值 */

}

其中,xtime是前面所提到的timeval類(lèi)型,這是一個(gè)全局變量。

(3) 時(shí)鐘函數(shù)do_timer() (在/kernel/sched.c中)

void do_timer(struct pt_regs * regs)

{

(*(unsigned long *)&jiffies)++; /*更新系統(tǒng)時(shí)間,這種寫(xiě)法保證對(duì)jiffies操作的原子性*/

update_process_times();

++lost_ticks;

if( ! user_mode ( regs ) )

++lost_ticks_system;

mark_bh(TIMER_BH);

if (tq_timer)

mark_bh(TQUEUE_BH);

}

其中,update_process_times()函數(shù)與進(jìn)程調(diào)度有關(guān),從函數(shù)的名子可以看出,它處理的是與當(dāng)前進(jìn)程與時(shí)間有關(guān)的變量,例如,要更新當(dāng)前進(jìn)程的時(shí)間片計(jì)數(shù)器counter,如果counter<=0,則要調(diào)用調(diào)度程序。

與時(shí)間有關(guān)的事情很多,不能全都讓這個(gè)函數(shù)去完成,這是因?yàn)檫@個(gè)函數(shù)是在關(guān)中斷的情況下執(zhí)行,必須處理完最重要的時(shí)間信息后退出,以處理其他事情。那么,與時(shí)間相關(guān)的其他信息誰(shuí)去處理,何時(shí)處理?這就是由第三章討論的后半部分去去處理。上面timer_interrupt()所做的事情就是上半部分。

(4)中斷安裝程序

從上面的介紹可以看出,時(shí)鐘中斷與進(jìn)程調(diào)度密不可分,因此,一旦開(kāi)始有時(shí)鐘中斷就可能要進(jìn)行調(diào)度,在系統(tǒng)進(jìn)行初始化時(shí),所做的大量工作之一就是對(duì)時(shí)鐘進(jìn)行初始化,其函數(shù)time_init ()的代碼在/arch/i386/kernel/time.c中,對(duì)其簡(jiǎn)寫(xiě)如下:

void __init time_init(void)

{

xtime.tv_sec=get_cmos_time();

xtime.tv_usec=0;

setup_irq(0,&irq0);

}

其中的get_cmos_time()函數(shù)就是把當(dāng)時(shí)的實(shí)際時(shí)間從CMOS時(shí)鐘芯片讀入變量xtime中,時(shí)間精度為秒。而setup_irq(0,&irq0)就是時(shí)鐘中斷安裝函數(shù),那么irq0指的是什么呢,它是一個(gè)結(jié)構(gòu)類(lèi)型irqaction,其定義及初值如下:

static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};

setup_irq(0, &irq0)的代碼在/arch/i386/kernel/irq.c中,其主要功能就是將中斷程序連入相應(yīng)的中斷請(qǐng)求隊(duì)列,以等待中斷到來(lái)時(shí)相應(yīng)的中斷程序被執(zhí)行。

我們將有關(guān)函數(shù)改寫(xiě)如下,體現(xiàn)時(shí)鐘中斷的大意:

do_timer_interrupt( ) /*這是一個(gè)偽函數(shù) */

{

SAVE_ALL  /*保存處理機(jī)現(xiàn)場(chǎng) */

intr_count += 1;  /* 這段操作不允許被中斷 */

timer_interrupt() /* 調(diào)用時(shí)鐘中斷程序 */

intr_count -= 1;

jmp ret_from_intr /* 中斷返回函數(shù) */

}

#p#

其中,jmp ret_from_intr 是一段匯編代碼,也是一個(gè)較為復(fù)雜的過(guò)程,它最終要調(diào)用jmp ret_from_sys_call,即系統(tǒng)調(diào)用返回函數(shù),而這個(gè)函數(shù)與進(jìn)程的調(diào)度又密切相關(guān),,因此,我們重點(diǎn)分析jmp ret_from_sys_call。

2.系統(tǒng)調(diào)用返回函數(shù):

系統(tǒng)調(diào)用返回函數(shù)的源代碼在/arch/i386/kernel/entry.S中

ENTRY(ret_from_sys_call)

cli  # need_resched and signals atomic test

cmpl $0,need_resched(%ebx)

jne reschedule

cmpl $0,sigpending(%ebx)

jne signal_return

restore_all:

RESTORE_ALL

ALIGN

signal_return:

sti  # we can get here from an interrupt handler

testl $(VM_MASK),EFLAGS(%esp)

movl %esp,%eax

jne v86_signal_return

xorl %edx,%edx

call SYMBOL_NAME(do_signal)

jmp restore_all

ALIGN

v86_signal_return:

call SYMBOL_NAME(save_v86_state)

movl %eax,%esp

xorl %edx,%edx

call SYMBOL_NAME(do_signal)

jmp restore_all

….

reschedule:

call SYMBOL_NAME(schedule) # test

jmp ret_from_sys_call

這一段匯編代碼就是前面我們所說(shuō)的“從系統(tǒng)調(diào)用返回函數(shù)”ret_from_sys_call,它是從中斷、異常及系統(tǒng)調(diào)用返回時(shí)的通用接口。這段代碼主體就是ret_from_sys_call函數(shù),在此我們列出相關(guān)的幾個(gè)函數(shù):

(1)ret_from_sys_call:主體

(2)reschedule:檢測(cè)是否需要重新調(diào)度

(3)signal_return:處理當(dāng)前進(jìn)程接收到的信號(hào)

(4)v86_signal_return:處理虛擬86模式下當(dāng)前進(jìn)程接收到的信號(hào)

(5)RESTORE_ALL:我們把這個(gè)函數(shù)叫做徹底返回函數(shù),因?yàn)閳?zhí)行該函數(shù)之后,就返回到當(dāng)前進(jìn)程的地址空間中去了。

可以看到ret_from_sys_call的主要作用有:

檢測(cè)調(diào)度標(biāo)志need_resched,決定是否要執(zhí)行調(diào)度程序;處理當(dāng)前進(jìn)程的信號(hào);恢復(fù)當(dāng)前進(jìn)程的環(huán)境使之繼續(xù)執(zhí)行。

最后我們?cè)俅螐目傮w上瀏覽一下時(shí)鐘中斷:

每個(gè)時(shí)鐘滴答,時(shí)鐘中斷得到執(zhí)行。時(shí)鐘中斷執(zhí)行的頻率很高:100次/秒,時(shí)鐘中斷的主要工作是處理和時(shí)間有關(guān)的所有信息、決定是否執(zhí)行調(diào)度程序以及處理下半部分。和時(shí)間有關(guān)的所有信息包括系統(tǒng)時(shí)間、進(jìn)程的時(shí)間片、延時(shí)、使用CPU的時(shí)間、各種定時(shí)器,進(jìn)程更新后的時(shí)間片為進(jìn)程調(diào)度提供依據(jù),然后在時(shí)鐘中斷返回時(shí)決定是否要執(zhí)行調(diào)度程序。下半部分處理程序是Linux提供的一種機(jī)制,它使一部分工作推遲執(zhí)行。
 

【編輯推薦】

  1. 探索Linux內(nèi)核虛擬機(jī)——學(xué)習(xí)KVM架構(gòu)及其優(yōu)點(diǎn)
  2. Linux下用gdb檢測(cè)內(nèi)核rootkit的方法
  3. Linux內(nèi)核中的DeviceMapper機(jī)制
責(zé)任編輯:趙寧寧 來(lái)源: chinaitlab
相關(guān)推薦

2009-12-11 09:47:23

Linux內(nèi)核源碼進(jìn)程調(diào)度

2021-12-15 15:03:51

Linux內(nèi)核調(diào)度

2010-03-08 14:53:48

Linux分區(qū)

2025-06-16 05:10:00

2009-07-03 11:14:57

2023-05-08 12:03:14

Linux內(nèi)核進(jìn)程

2011-03-23 11:01:55

LAMP 架構(gòu)

2017-01-15 22:51:16

2010-09-07 14:21:22

PPPoE協(xié)議

2022-04-12 08:30:45

TomcatWeb 應(yīng)用Servlet

2012-05-14 14:09:53

Linux內(nèi)核調(diào)度系統(tǒng)

2020-11-12 18:08:05

JavaLinux多線(xiàn)程

2009-12-16 16:39:01

Visual Stud

2009-06-10 18:12:38

Equinox動(dòng)態(tài)化OSGi動(dòng)態(tài)化

2022-08-30 07:00:18

執(zhí)行引擎Hotspot虛擬機(jī)

2009-12-14 14:50:46

Ruby傳參數(shù)

2021-10-29 16:36:53

AMSAndroidActivityMan

2023-02-01 08:13:30

Redis內(nèi)存碎片

2011-09-01 13:51:52

JavaScript

2023-11-26 18:54:29

Linux調(diào)度器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)