中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站建設(shè)管理及維護百度中心人工電話號碼

網(wǎng)站建設(shè)管理及維護,百度中心人工電話號碼,有關(guān)網(wǎng)站開發(fā)的文獻或論文,賠率網(wǎng)站怎么做目錄 一、信號被處理的時機: 1、理解: 2、內(nèi)核態(tài)與用戶態(tài): 1、概念: 2、重談地址空間: 3、處理時機: 補充知識: 1、sigaction: 2、函數(shù)重入: 3、volatile&…

目錄

一、信號被處理的時機:

1、理解:

2、內(nèi)核態(tài)與用戶態(tài):

1、概念:

2、重談地址空間:

3、處理時機:

補充知識:

1、sigaction:

2、函數(shù)重入:

3、volatile:

4、SIGCHLD:


前言:

信號在保存后,當(dāng)OS準(zhǔn)備對信號進行處理的時候,還需要到合適的時機才能進行處理,那么什么是合適的時機?

一、信號被處理的時機:

1、理解:

信號的產(chǎn)生是異步的

首先,要將信號進行處理之前就需要讓OS知道某個進程收到了信號了,所以進程就需要在合適的時機查查其對應(yīng)的block,pending,handler表,但是這三個表都屬于內(nèi)核級別的,我們用戶級別的進程是不允許訪問的,所以這里就自然涉及了進程的用戶態(tài)和內(nèi)核態(tài)之間的轉(zhuǎn)化

合適的時機:在進程從內(nèi)核態(tài)轉(zhuǎn)化到用戶態(tài)的時候?qū)π盘栠M行檢測,如果有并未被屏蔽就進行處理

怎么進行處理:默認(rèn),忽略,用戶自定義

2、內(nèi)核態(tài)與用戶態(tài):

1、概念:

進程在執(zhí)行代碼的時候不僅僅是只執(zhí)行用戶的代碼,還有操作系統(tǒng)的代碼,想要訪問操作系統(tǒng)就需要變成內(nèi)核態(tài),執(zhí)行用戶的代碼就要變成用戶態(tài):

用戶態(tài):進程只能訪問用戶自己的代碼和數(shù)據(jù)

內(nèi)核態(tài):進程允許訪問操作系統(tǒng)的代碼和數(shù)據(jù)

用戶態(tài)-->內(nèi)核態(tài)

進程時間片到了,進行進程切換的時候
調(diào)用系統(tǒng)調(diào)用接口:open,read等等
產(chǎn)生異常,中斷的時候等等

內(nèi)核態(tài)-->用戶態(tài)

進程切換完畢
系統(tǒng)調(diào)用結(jié)束后
異常,中斷處理完后

OS是不會收到信號就立即執(zhí)行的,比如當(dāng)前我正在進行系統(tǒng)調(diào)用或者正在切換進程等等,在從內(nèi)核態(tài)轉(zhuǎn)化為用戶態(tài)的時候,就進行信號的查詢?nèi)砗吞幚硇盘?#xff0c;所以要等到OS將更重要的事情忙完后,在進程從內(nèi)核態(tài)到用戶態(tài)的時候就進行信號的檢測和處理

2、重談地址空間:

如下,我們回顧下我們地址空間的知識:

每個進程都有其獨有的虛擬地址空間,進程具有獨立性
通過頁表的映射+MMU機制進行虛擬到物理地址之間的轉(zhuǎn)化
進程都具有其對應(yīng)的虛擬地址空間,能夠讓進程以統(tǒng)一的時間看待我們的代碼和數(shù)據(jù)


?

虛擬地址空間又可分為兩個空間0~3GB的空間為用戶空間,3~4GB的空間為內(nèi)核空間

為什么要區(qū)分內(nèi)核空間和用戶空間?

因為內(nèi)核空間中存放的是OS的代碼和數(shù)據(jù),是不允許進程隨便訪問的,需要進程切換到內(nèi)核態(tài)才能進行訪問,并且規(guī)劃也能夠OS進行更好的管理

其中:用戶空間就是我們的代碼和數(shù)據(jù),當(dāng)進程在用戶態(tài)的時候就能夠訪問這段空間的代碼和數(shù)據(jù)
內(nèi)核空間中存放的就是OS的代碼和數(shù)據(jù),這里的虛擬地址通過特有的內(nèi)核級頁表從虛擬地址空間映射到物理內(nèi)存中,由于OS是最先被加載的程序,所以其映射應(yīng)該在較為底部的位置

我們知道每一個進程都有其對應(yīng)的進程地址空間, 那么是不是每一個進程都有其獨特的內(nèi)核空間和內(nèi)核級頁表呢?

答案是只有一份

對應(yīng)用戶空間和用戶級頁表有很多份的,因為進程具有獨立性
但是內(nèi)核級頁表只有一份,內(nèi)核空間比較特殊,所有進程最終映射到物理內(nèi)存都是同一塊區(qū)域,進程只是將操作系統(tǒng)代碼和數(shù)據(jù)映射入自己的進程地址空間而已,其中內(nèi)核級頁表只需將虛擬地址空間映射到物理內(nèi)存,所有進程都是如此

所以,每一個進程看到的內(nèi)核空間中的內(nèi)容,看到的內(nèi)核級頁表資源,最后映射到的物理內(nèi)存中的代碼和數(shù)據(jù)都是一樣的

所以在用戶空間的代碼區(qū)中執(zhí)行對應(yīng)的系統(tǒng)調(diào)用,
首先將進程從用戶態(tài)轉(zhuǎn)化到內(nèi)核態(tài),
然后在自己的內(nèi)核空間中找到對應(yīng)的系統(tǒng)調(diào)用方法,
然后通過內(nèi)核級頁表映射到物理內(nèi)存找到對應(yīng)的代碼和數(shù)據(jù),
然后在返回(在返回的時候進程從內(nèi)核態(tài)轉(zhuǎn)化為用戶態(tài)),
這樣就相當(dāng)與在進程自己的進程地址空間中進行系統(tǒng)調(diào)用

那么上述的切換是如何進行切換的呢?

首先,我們知道,CR3 寄存器存儲當(dāng)前進程的頁目錄表物理地址,用于分頁機制下的內(nèi)存管理,

在CPU中同樣還有一個叫做ESC寄存器的東西,這個寄存器的作用就是用來表示當(dāng)前進程的狀態(tài):是用戶態(tài)還是內(nèi)核態(tài)

那么這個寄存器是怎樣實現(xiàn)的呢?

在這個寄存器中,有著最后兩個比特位,兩個比特位有4種表示方式:00 01 10 11,其中只使用兩種方式,00和11也就是對應(yīng)十進制的0和3,

當(dāng)這個寄存器最后兩個比特位為0的時候,表示當(dāng)前進程處于內(nèi)核態(tài)
當(dāng)這個寄存器最后兩個比特位為1的時候,表示當(dāng)前進程處于用戶態(tài)

所以切換進程的狀態(tài)就需要將ESC寄存器中的最后兩個比特位修改為對應(yīng)的值,CPU為我們提供了一種方法來修改自己的工作狀態(tài):int 0x80指令

小總結(jié):

1、每一個進程中的0~3GB中的內(nèi)容是不一樣的,因為進程具有獨立性

2、每一個進程中的3~4GB中的內(nèi)容是一樣的,在整個系統(tǒng)中,無論進程再怎么切換,? ? ? ? ? ? ? ? 3~4GB中的內(nèi)核空間內(nèi)容是不變的

3、在進程視角:我們進行系統(tǒng)調(diào)用,就是在我自己的地址空間中進行執(zhí)行的

4、操作系統(tǒng)視角:任何一個時刻,都有進程執(zhí)行,想執(zhí)行OS的代碼可以隨時執(zhí)行

5、操作系統(tǒng)本質(zhì)是一個基于時鐘中斷的一個死循環(huán)

怎么理解操作系統(tǒng)的執(zhí)行邏輯呢或者說操作系統(tǒng)的本質(zhì)是什么?

其可以理解為一種基于中斷驅(qū)動的“死循環(huán)”模型,核心在于通過時鐘中斷等機制實現(xiàn)任務(wù)調(diào)度,資源管理和實時響應(yīng)

主框架循環(huán):

操作系統(tǒng)的核心代碼是一個死循環(huán)(for(; ;) pause();?),這個循環(huán)并非是空轉(zhuǎn)的,而是通過中斷機制被動喚醒的,當(dāng)沒有外部事件(用戶輸入,I/O完成)或內(nèi)部事件(如時間片耗盡)時,操作系統(tǒng)會進入低功耗狀態(tài)或執(zhí)行空閑任務(wù)

其中操作系統(tǒng)本會一直卡在pause()這個行代碼暫停,等到發(fā)生中斷機制,被進程“推著走”才能夠讓代碼得以運行

那有什么中斷機制呢?

時鐘中斷:每過一定很短的時間產(chǎn)生一次,用于更新系統(tǒng)時間、檢查進程時間片、觸發(fā)調(diào)度?

硬件中斷:如鍵盤輸入,由外設(shè)通過中斷控制器通知CPU?

軟件中斷:如系統(tǒng)調(diào)用,允許用戶程序訪問內(nèi)核空間

進程是如何被操作系統(tǒng)調(diào)用的呢?

進程被調(diào)度,就意味著它的時間片到了,操作系統(tǒng)會通過時鐘中斷,檢測到是哪一個進程的時間片到了,然后通過系統(tǒng)調(diào)用函數(shù)schedule()保存進程的上下文數(shù)據(jù),然后選擇合適的進程去運行

3、處理時機:

有了上述鋪墊的知識,接下來可以理解:

我們前面了解到,在進程從內(nèi)核態(tài)轉(zhuǎn)化到用戶態(tài)的時候?qū)π盘栠M行檢測,處理方式如下圖:

對于上述的執(zhí)行用戶自定義有兩個問題:

為什么要切回用戶態(tài)再執(zhí)行對應(yīng)的方法:
因為如果在內(nèi)核態(tài)中執(zhí)行用戶自定義的方法,可能自定義方法中存在危害操作系統(tǒng)的代碼,這是不安全的

為什么在用戶態(tài)執(zhí)行完畢后還要返回內(nèi)核態(tài)再到用戶態(tài)
需要回到內(nèi)核態(tài)找到進程的上下文,將上下文帶出到用戶態(tài)才行,并且自定義的動作和待返回的進程是屬于不同的堆棧,不能夠直接返回

對于信號捕捉的理解可以看看下面這張圖

如上,這是一個橫著的8,然后用一橫貫穿,上面是用戶態(tài),下面是內(nèi)核態(tài),注意有4個交點,并且8的交點是在橫線下方的也就是在內(nèi)核態(tài)中

接下來解釋上圖:

四個綠色的圈圈就表示兩態(tài)之間的切換了四次,當(dāng)進程時間片到了,進行進程切換,產(chǎn)生異常,中斷的時候等等就進行用戶態(tài)到內(nèi)核態(tài)之間的轉(zhuǎn)化

進程切換完畢,系統(tǒng)調(diào)用結(jié)束后,異常,中斷處理完后進行內(nèi)核態(tài)到用戶態(tài)之間的轉(zhuǎn)化

此時就進行信號的檢測:首先看pending表,如果其為1并且該信號沒有被阻塞就執(zhí)行對應(yīng)動作,如果被屏蔽或者為0就繼續(xù)從pending表向下找下一個,以此類推

二、補充知識:

1、sigaction:

其中有個新的結(jié)構(gòu)體:sigaction,其內(nèi)部成員如下

我們只關(guān)心第一個和第三個成員:

成功返回0,失敗返回-1,錯誤碼被設(shè)置

第一個參數(shù)signum:信號編號

第二個參數(shù)act: 傳入該類結(jié)構(gòu)體,設(shè)置屏蔽信號什么的在之前就要設(shè)置好

第三個參數(shù)oldact:保存修改前的結(jié)構(gòu)體

其中sigaction中的第一個成員變量:就是signal的第二個參數(shù),需要自己設(shè)置自定義

第三個成員變量就是屏蔽的信號集,怎么理解呢?

首先我們知道,比如當(dāng)在處理2號信號的時候,如果sa_mask默認(rèn),那么OS就只會屏蔽2號信號,如果還想要屏蔽更多信號,就需要sigaddset(&act.sa_mask,1);這樣在待傳入結(jié)構(gòu)體中的sa_mask進行更多的設(shè)置來屏蔽

void Printpending()
{sigset_t set;sigpending(&set);for(int signo = 31; signo>=1; signo--){if(sigismember(&set,signo)) cout <<"1";else cout<<"0";}cout << endl;
}void myhandler(int signo)
{cout << "get a signo : " << signo << endl;while(1){Printpending();sleep(1);}
}int main()
{struct sigaction act,oact;memset(&act,0,sizeof(act));memset(&oact,0,sizeof(oact));//清空信號集sigemptyset(&act.sa_mask);//添加屏蔽信號sigaddset(&act.sa_mask,1);sigaddset(&act.sa_mask,3);sigaddset(&act.sa_mask,4);sigaddset(&act.sa_mask,9);//設(shè)置自定義方法act.sa_handler = myhandler;sigaction(2,&act,&oact);    while(1){cout << "i am a process mypid : " << getpid() << endl;sleep(1);}return 0;
}

如上,這樣就將1?3 4號都屏蔽了,9號和19號信號可以經(jīng)過試驗發(fā)現(xiàn)不可屏蔽,

2、函數(shù)重入:

可以被重復(fù)進入的函數(shù)稱為可重入函數(shù)

如下是一個場景:

如上,當(dāng)在insert函數(shù)中捕捉到了信號,并且在信號的自定義動作中又調(diào)用了insert,這樣函數(shù)就會重入,這樣就會導(dǎo)致函數(shù)節(jié)點丟失,在釋放的時候無法釋放node2,就會導(dǎo)致內(nèi)存泄漏

這就是函數(shù)重入導(dǎo)致的內(nèi)存泄漏問題

我們把這種函數(shù)稱為可重入函數(shù)(注意:這個是特性,不具有褒貶含義)

3、volatile:

int flag;void myhandler(int signo)
{cout << "get a signo : " << signo << endl;flag = 1;
}int main()
{signal(2,myhandler);while(!flag); //flag = 0 為假 !flag 為真cout << "a process quit ! " << endl;return 0;
}

如上,上述本來是一個死循環(huán),但是當(dāng)給當(dāng)前進程發(fā)送2號信號的時候就會進入我們的自定義函數(shù)調(diào)用,這個時候在里面將flag修改為1,這樣就能夠退出while死循環(huán)了,并且我們的代碼運行起來也是達到預(yù)期了

但是在編譯中,有個-O1/O2/O3這種的優(yōu)化,如下,我們把這種優(yōu)化帶著,在運行代碼試試

如上,此時發(fā)現(xiàn)盡管我們給當(dāng)前進程發(fā)送2號信號,并且也看到了自定義代碼中打印的字符串,但是進程卻沒有退出while這個死循環(huán)

這是為什么呢?

這是因為在編譯的時候進行了O1的優(yōu)化

如上,正常情況下,CPU在每次進行邏輯檢測的時候,每次都從內(nèi)存中進行讀入,這種IO比較費事,當(dāng)進行O1的優(yōu)化之后,就會對整個代碼進行檢測,此時沒有信號就檢查不到flag被修改了,此時就會將flag放入邏輯檢測的寄存器中,這樣,當(dāng)在自定義中修改了flag,這只是把內(nèi)存中的flag修改了,但是CPU寄存器中的flag并沒有被修改,所以就會一直繼續(xù)死循環(huán)

為了防止這種過度優(yōu)化,保存內(nèi)存的可見性,可以在全局變量前面加上volatile關(guān)鍵字修飾,這樣就無法將flag放入到寄存器中,老老實實地每次都從內(nèi)存中進行讀入

4、SIGCHLD:

在前面實現(xiàn)進程等待的時候,每次當(dāng)子進程退出的時候,父進程都需要等待,回收子進程,防止其成為僵尸進程造成內(nèi)存泄漏問題

父進程有兩種方式等待子進程:設(shè)置0為阻塞等待或者設(shè)置WNOHANG為非阻塞輪詢

但是上述兩種方式都有缺陷,要么父進程阻塞,不能做其自己的事情,要么每次工作的時候都還要關(guān)心關(guān)心子進程的狀態(tài)

那么有沒有一種方式能夠讓父進程不在關(guān)心子進程,當(dāng)子進程退出的時候自動回收呢?

有的有的:

首先要了解:子進程在退出的時候會向父進程發(fā)送17號信號,所以我們可以在父進程中將17好信號捕捉,然后在自定義函數(shù)中等待,這里設(shè)置第一個參數(shù)為-1為等待任意進程

void myhandler(int signo)
{pid_t rid = waitpid(-1,nullptr,0);cout << "a signo get : " << signo << " mypid " << getpid() << " rid : " << rid << endl;
}int main()
{signal(17,myhandler);pid_t id = fork();if(id == 0){//childcout << "child process " << getpid() << " myppid : " << getppid() << endl;sleep(5);exit(0);}//fatherwhile(1){cout << "father process " << getpid() << endl;sleep(1);}return 0;
}

如上,這樣父進程就可以不用管子進程了,能夠完成子進程的自動回收

但是這樣還不夠,如果有多個子進程呢?能夠全部回收嗎

這顯然是不會的,SIGCHLD這是一個信號,當(dāng)父進程收到了第一個信號的時候,會將block表中的17號信號置為1使其屏蔽,這樣,其他子進程的信號就丟失了,就會導(dǎo)致僵尸進程

那么如何解決呢?

我們在自定義中采取while循環(huán)的方式回收即可

當(dāng)然,還有一種更方便的,但是只能在Linux中有效:

將SIGCHLD這個信號的默認(rèn)動作設(shè)置為忽略,這樣父進程不會對其處理,但是當(dāng)子進程退出之后,OS會對其負(fù)責(zé),這樣的話就會自動清理資源并回收,不會產(chǎn)生僵尸進程引起內(nèi)存泄漏

http://www.risenshineclean.com/news/9411.html

相關(guān)文章:

  • 電子產(chǎn)品網(wǎng)站建設(shè)策劃方案百度app安裝下載
  • 網(wǎng)站建設(shè)html5作品sem搜索引擎營銷
  • 附近裝修公司超級優(yōu)化大師
  • 機關(guān)門戶網(wǎng)站建設(shè)要求免費營銷軟件網(wǎng)站
  • 淘寶網(wǎng)站制作ue5培訓(xùn)機構(gòu)哪家強
  • 網(wǎng)站是用什么做的嗎百度一下就知道手機版
  • 做神馬網(wǎng)站優(yōu)化排名西安網(wǎng)絡(luò)推廣seo0515
  • wordpress添加形式鄭州seo線上推廣技術(shù)
  • 有關(guān)于網(wǎng)站開發(fā)的參考文獻免費個人網(wǎng)站怎么建立
  • 有沒有兼職做設(shè)計的網(wǎng)站抖音關(guān)鍵詞推廣
  • 自己可做以做網(wǎng)站嗎事件營銷的概念
  • 網(wǎng)站設(shè)計 做鼠標(biāo)效果優(yōu)化公司
  • 9e做網(wǎng)站推廣優(yōu)化排名
  • 高端手機網(wǎng)站建設(shè)網(wǎng)絡(luò)營銷的五個發(fā)展階段
  • 做視頻賺錢的國外網(wǎng)站各大網(wǎng)站提交入口網(wǎng)址
  • 上海優(yōu)化排名藍天seo谷歌優(yōu)化排名怎么做
  • 建設(shè)網(wǎng)站考慮因素寧波seo網(wǎng)絡(luò)推廣定制多少錢
  • 邯鄲市住房和城鄉(xiāng)建設(shè)網(wǎng)站百度拍照搜題
  • 新浪云服務(wù)器做網(wǎng)站瀏覽器廣告投放
  • 做網(wǎng)站_你的出路在哪里創(chuàng)建自己的網(wǎng)站
  • 中國產(chǎn)品網(wǎng)注冊網(wǎng)站站長seo推廣
  • jsp網(wǎng)站空間網(wǎng)絡(luò)銷售渠道有哪些
  • 做網(wǎng)站如何排版曹操seo博客
  • 旅游網(wǎng)站首頁設(shè)計圖片seo自然排名
  • 免費做網(wǎng)站的網(wǎng)頁如何給自己的公司建網(wǎng)站
  • 怎么將網(wǎng)站做成小程序seo是做什么工作內(nèi)容
  • 做app 的模板下載網(wǎng)站營銷推廣方案怎么寫
  • 怎樣做動態(tài)網(wǎng)站網(wǎng)上銷售
  • 怎么把統(tǒng)計代碼加到網(wǎng)站網(wǎng)上銷售推廣方案
  • 校園安全網(wǎng)站建設(shè)windows優(yōu)化大師有用嗎