前沿拓展:
切換用戶
1、第一進(jìn)入系統(tǒng)設(shè)置,第二在“ 用戶賬戶 ”中點擊“ 登錄本地賬戶 ”;2、接著為顯示你的賬戶信息,不需要管,點右
第一是藍(lán)色的部分,線程1在運行過程中,通過系統(tǒng)調(diào)用進(jìn)程到內(nèi)核狀態(tài),此時發(fā)生系統(tǒng)阻塞,需要調(diào)度,內(nèi)核態(tài)此時保持用戶態(tài)的現(xiàn)場到內(nèi)核棧中,第二通過調(diào)度子系統(tǒng)調(diào)度到線程2中運行,此時發(fā)生線程控制塊的切換,從TCB1切換到TCB2切換到線程2的TCB時候,TCB中存放了內(nèi)核棧的指針,此時運行在內(nèi)核態(tài),此時內(nèi)核態(tài)運行一段收尾代碼后,一般會通過iret指令,切換線程2的用戶空間,執(zhí)行用戶空間的代碼,就完成的用戶棧的切換過程
所以對于內(nèi)核級線程,分為用戶態(tài)和內(nèi)核態(tài),例如process 1,用戶進(jìn)程中有線程A和線程B,它們共享進(jìn)程的內(nèi)存空間,分別有自己的用戶棧,用于存放自己的調(diào)用過程,同時在內(nèi)核空間,有屬于自己的PCB,但是對于每一個進(jìn)程有一個內(nèi)核棧
進(jìn)程切換的時機(jī)
對于一個進(jìn)程由哪些部分組成呢?主要包括用戶空間和內(nèi)核空間,如下圖所示:
用戶空間的進(jìn)程地址空間一般由代碼段、數(shù)據(jù)段、堆、棧組成,由task_struct的VMA維護(hù),同時所有的內(nèi)存空間都是存放在該進(jìn)程的頁表中,CPU中的reg也是由頁表機(jī)制來管理內(nèi)核空間進(jìn)程地址空間維護(hù)了一個進(jìn)程的控制塊PCB task_struct,主要是內(nèi)核棧和用戶棧信息thread_info,這兩個用戶維護(hù)進(jìn)程的上下文切換中有大用途
這個在linux進(jìn)程管理章節(jié)中已經(jīng)有詳細(xì)介紹,要想進(jìn)行進(jìn)程的切換,那么OS必須第一獲得控制權(quán),其主要在以下情況下得到控制權(quán)
trap: 進(jìn)程主動的切換,主要是通過執(zhí)行一個system callException: 被動的切換,執(zhí)行了一個意外的**作,例如常見的page faultInterrupt: 硬件設(shè)備請求OS服務(wù) ,比如time中斷,IO中斷進(jìn)程切換
基于內(nèi)核棧實現(xiàn)進(jìn)程切換的基本思路:
1, 當(dāng)進(jìn)程由用戶態(tài)進(jìn)入內(nèi)核態(tài)時,主要是通過系統(tǒng)調(diào)用或者中斷,會引起堆棧切換,用戶信息會被壓入到內(nèi)核棧中,包括此時的用戶的棧指針,PC和程序狀態(tài)保存在內(nèi)核棧中
2, 當(dāng)進(jìn)入到內(nèi)核后,此時由于某些原因,由于該進(jìn)程需要讀取磁盤或者網(wǎng)絡(luò)等信息,變成阻塞狀態(tài),或者時間片用完,此時需要讓出CPU,重新引起調(diào)度時,**作系統(tǒng)會找到一個新的進(jìn)程的PCB,并完成新進(jìn)程PCB的切換
3, 當(dāng)完成新進(jìn)程的切換時,內(nèi)核也完成了內(nèi)核棧的切換,那么當(dāng)中斷返回時,執(zhí)行IRET,彈出的就是新進(jìn)程的EIP,從而跳轉(zhuǎn)到新進(jìn)程的用戶指令進(jìn)行執(zhí)行。
這個切換的核心就是構(gòu)建出內(nèi)核棧的樣子,要在適當(dāng)?shù)牡胤綁喝霔?,適當(dāng)?shù)牡胤椒祷氐刂罚⒏鶕?jù)內(nèi)核棧的樣子,編寫相應(yīng)的匯編代碼,完成內(nèi)核堆棧的入棧和出站**作,以便保證順利完成進(jìn)程切換。
4.1 中斷入口
**作系統(tǒng)負(fù)責(zé)進(jìn)程的調(diào)度和切換,所以進(jìn)程的切換一定是內(nèi)核中發(fā)生,而用戶程序是運行在內(nèi)核態(tài),所以就需要使用系統(tǒng)調(diào)用進(jìn)入到內(nèi)核態(tài)。主要的偽代碼如下:
push ds;
mov ds, 內(nèi)核段號
system_call 4.2 中斷處理
用戶態(tài)進(jìn)入內(nèi)核態(tài),要發(fā)生堆棧的切換,系統(tǒng)調(diào)用的核心指令對于X86來說是指令int 0x80,這個系統(tǒng)調(diào)用中斷。 當(dāng)執(zhí)行int 0x80 這條語句時由用戶態(tài)進(jìn)入內(nèi)核態(tài)時,CPU會自動按照***SS、ESP、EFLAGS、CS、EIP***的順序,將這幾個寄存器的值壓入到內(nèi)核棧中,由于執(zhí)行int 0x80時還未進(jìn)入內(nèi)核,所以壓入內(nèi)核棧的這五個寄存器的值是用戶態(tài)時的值,其中***EIP*為int 0x80的下一條語句 "=a" (__res),這條語句的含義是將eax所代表的寄存器的值放入到_res變量中。所以當(dāng)應(yīng)用程序在內(nèi)核中返回時,會繼續(xù)執(zhí)行 “=a” (__res) 這條語句。**這個過程完成了進(jìn)程切換中的第一步,通過在內(nèi)核棧中壓入用戶棧的ss、esp建立了用戶棧和內(nèi)核棧的聯(lián)系,形象點說,即在用戶棧和內(nèi)核棧之間拉了一條線,形成了一套棧。
在system_call中執(zhí)行完相應(yīng)的系統(tǒng)調(diào)用sys_call_xx后,又將函數(shù)的返回值eax壓棧。若引起調(diào)度,則跳轉(zhuǎn)執(zhí)行reschedule。否則則執(zhí)行ret_from_sys_call。
在執(zhí)行schedule前將ret_from_sys_call壓棧,因為schedule是c函數(shù),所以在c函數(shù)末尾的},相當(dāng)于ret指令,將會彈出ret_from_sys_call作為返回地址,跳轉(zhuǎn)到ret_from_sys_call執(zhí)行。 小編綜合來說,在系統(tǒng)調(diào)用結(jié)束后,將要中斷返回前,內(nèi)核棧主要是SS:SP指向用戶棧,EFLAGS標(biāo)志寄存器,返回地址EIP,還有一些其他的other Registers:EAX,EBX等,如下圖所示
4.3 找到當(dāng)前進(jìn)程的PCB和新進(jìn)程的PCB
當(dāng)前進(jìn)程的PCB 當(dāng)前進(jìn)程的PCB是用一個全局變量current指向的*(在sched.c中定義)* ,所以current即指向當(dāng)前進(jìn)程的PCB,pnext就指向下個進(jìn)程的PCB。 在schedule()*函數(shù)中,當(dāng)調(diào)用函數(shù)*switch_to(pent, _LDT(next))*時,會依次將返回地址**}***、參數(shù)2 ***_LDT(next)***、參數(shù)1 *pnext**壓棧。當(dāng)執(zhí)行*switch_to*的返回指令ret時,就回彈出schedule()函數(shù)的}執(zhí)行*schedule()*函數(shù)的返回指令
4.4 switch_to
對于schedule中switch_to,表示要取出表示下一個進(jìn)程的PCB參數(shù),并與當(dāng)前的current做一個比較,如果是當(dāng)前的current,則什么也不做;如果不等于當(dāng)前的curret,則開始進(jìn)程切換,以次完成PCB的切換,內(nèi)核棧的切換等
在schedule.c中定義struct tss_struct *tss=&(init_task.task.tss)這樣一個全局變量,即0號進(jìn)程的tss,所有進(jìn)程都共用這個tss,任務(wù)切換時不再發(fā)生變化。 雖然所有進(jìn)程共用一個tss,但不同進(jìn)程的內(nèi)核棧是不同的,所以在每次進(jìn)程切換時,需要更新tss中esp0的值,讓它指向新的進(jìn)程的內(nèi)核棧,并且要指向新的進(jìn)程的內(nèi)核棧的棧底,即要保證此時的內(nèi)核棧是個空棧,幀指針和棧指針都指向內(nèi)核棧的棧底。
4.5 中斷出口
PC的切換對于被切換出去的進(jìn)程,當(dāng)再次被調(diào)度的時,根據(jù)切換出去的進(jìn)程的內(nèi)核棧的樣子,switch_to的最后一句指令ret會彈出switch_to后面的指令,作為返回地址繼續(xù)執(zhí)行,將彈出ret_from_sys_call作為返回地址,在ret_from_sys_call中繼續(xù)進(jìn)行一些處理,最后執(zhí)行iret指令,進(jìn)行終端返回,將彈出原來用戶進(jìn)程被中斷的地方作為返回地址,繼續(xù)被中斷處執(zhí)行。
5. 小編綜合來說
對于進(jìn)程切換不同于我們熟知的“模式切換”,模式切換,CPU還是在同一進(jìn)程中運行systemcall或者中斷上下文;而進(jìn)程切換是CPU轉(zhuǎn)向另外一個進(jìn)程執(zhí)行,進(jìn)程切換改變當(dāng)前的進(jìn)程空間,其主要的工作如下:
保持當(dāng)前進(jìn)程的硬件上下文(PC/SP和通用寄存器等),對于linux系統(tǒng)而言,其硬件上下文大部分都保存在struct thread_struct thread中,但通用寄存器等都保存在內(nèi)核棧中
修改當(dāng)前進(jìn)程的PCB,比如將其狀態(tài)由運行態(tài)修改為就緒或者等待態(tài),并將該進(jìn)程PCB加入到相關(guān)隊列中
調(diào)度另外一個進(jìn)程,修改被調(diào)度進(jìn)程的PCB,并將其狀態(tài)修改為運行
將“當(dāng)前進(jìn)程"的管理數(shù)據(jù)改為調(diào)度進(jìn)程的存儲數(shù)據(jù),如頁表,TLB,同時恢復(fù)新進(jìn)程的硬件上下文,讓PC執(zhí)行新進(jìn)程的代碼
拓展知識:
切換用戶
桌面狀態(tài)快捷鍵Alt+F4 選擇切換用戶
臺式機(jī)(AMD平臺)性能如何優(yōu)化
¥2.99
電腦調(diào)修-專家1對1遠(yuǎn)程在線服務(wù)
¥38
路由器的選購、設(shè)置與進(jìn)階玩法
¥39
一看就會的RAID實用教程
¥29.9
小白必看的硬盤知識
¥9.9
查
看
更
多
官方服務(wù)
官方網(wǎng)站
切換用戶
啟動Windows 10時第一看到的是登錄屏幕,此外,如果你已經(jīng)登錄,則可以按鍵盤上的Windows + L鎖定Windows 10。
第二單擊“鎖定屏幕”以顯示登錄屏幕。默認(rèn)情況下,Windows 10會加載用于登錄的最新用戶帳戶,可用用戶帳戶列表顯示在屏幕的左下角。
如果要切換用戶,請在此列表中單擊要使用的帳戶,第二輸入登錄詳細(xì)信息。默認(rèn)情況下,Windows 10會要求輸入該用戶登錄時使用的最新信息:密碼、PIN或圖片密碼。
如果需要更改登錄方法,請單擊“登錄選項”,第二按要使用的方法,之后,輸入必要的信息以登錄。
原創(chuàng)文章,作者:九賢生活小編,如若轉(zhuǎn)載,請注明出處:http:///60578.html