本篇內(nèi)容主要講解“Java進程的執(zhí)行和掛起是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java進程的執(zhí)行和掛起是什么”吧!
站在用戶的角度思考問題,與客戶深入溝通,找到皮山網(wǎng)站設(shè)計與皮山網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名申請、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋皮山地區(qū)。
進程是對邏輯的抽象,我們從操作系統(tǒng)的書籍中對進程有了很多的認識,但是對進程的實現(xiàn)可能不太了解,這篇文章嘗試解釋一下關(guān)于進程實現(xiàn)的大致原理。
進程的實現(xiàn),其實和我們平時寫代碼的時候一樣,比如我們要表示一個東西,我們會定義一個數(shù)據(jù)結(jié)構(gòu)。進程也不例外。所以進程的本質(zhì)就是一個數(shù)據(jù)結(jié)構(gòu),他保存了一系列的數(shù)據(jù)。操作系統(tǒng)以數(shù)組或者鏈表的形式和全部的進程管理起來。進程可以說分為兩種
1 系統(tǒng)初始化時第一個進程,
2 除了第一個進程外的其他進程,他們都是由fork或者fork+execute系統(tǒng)調(diào)用創(chuàng)建出來的。
我們首先看一下進程的結(jié)構(gòu)體都有什么信息。
當系統(tǒng)創(chuàng)建一個進程之后,會設(shè)置cs:ip寄存器的值,如果是fork,則ip就是fork函數(shù)后面的語句的ip地址。如果是execute則ip地址由編譯器指定。不管怎樣,當進程開始執(zhí)行的時候,cpu就會解析cs:ip拿到一條指令去執(zhí)行。那么cs:ip是如何被解析的呢?
執(zhí)行進程的時候,tss選擇子(GDT索引)被加載到tss寄存器,然后把tss里的上下文也加載到對應(yīng)的寄存器,比如cr3,ldt選擇子。根據(jù)tss信息中的ldt索引首先從GDT找到進程ldt結(jié)構(gòu)體數(shù)據(jù)的首地址,然后根據(jù)當前段的屬性,比如代碼段,則從cs中取得選擇子,系統(tǒng)從ldt表中取得進程線性空間的首地址、限長、權(quán)限等信息。用線性地址的首地址加上ip中的偏移,得到線性地址,然后再通過頁目錄和頁表得到物理地址,物理地址還沒有分配則進行缺頁異常等處理。
進程的掛起、阻塞、多進程。這些概念我們平時聽得比較多,現(xiàn)在我們來看看他是實現(xiàn)是怎樣的。進程的掛起,或者說阻塞分為兩種。
1 主動掛起。通過sleep讓進程間歇性掛起。sleep的原理之前有分析過,就不再分析。大概的原理
就是設(shè)置一個定時器,到期后喚醒進程。
修改進程為掛起狀態(tài),等待喚醒。
2 被動掛起。
被動掛起的場景比較多,主要是進程申請一個資源,但是資源沒有滿足條件,則進程被操作系統(tǒng)掛起。比如我們讀一個管道的時候。管道沒有數(shù)據(jù)可讀,則進程被掛起。插入到管道的等待隊列。
// 當前進程掛載到睡眠隊列p中,p指向隊列頭指針的地址
void sleep_on(struct task_struct **p)
{
struct task_struct *tmp;
if (!p)
return;
if (current == &(init_task.task))
panic("task[0] trying to sleep");
/*
*p為第一個睡眠節(jié)點的地址,即tmp指向第一個睡眠節(jié)點
頭指針指向當前進程,這個版本的實現(xiàn)沒有采用真正鏈表的形式,
他通過每個進程在棧中的臨時變量形成一個鏈表,每個睡眠的進程,
在棧里有一個變量指向后面一個睡眠節(jié)點,然后把鏈表的頭指針指向當前進程,
然后切換到其他進程執(zhí)行,當被wake_up喚醒的時候,wake_up會喚醒鏈表的第一個
睡眠節(jié)點,因為第一個節(jié)點里保存了后面一個節(jié)點的地址,所以他喚醒后面一個節(jié)點,
后面一個節(jié)點以此類推,從而把整個鏈表的節(jié)點喚醒,這里的實現(xiàn)類似nginx的filter,
即每個模塊保存后面一個節(jié)點的地址,然后把全局指針指向自己。
*/
tmp = *p;
*p = current;
// 不可中斷睡眠只能通過wake_up喚醒,即使有信號也無法喚醒
current->state = TASK_UNINTERRUPTIBLE;
// 進程調(diào)度
schedule();
// 喚醒后面一個節(jié)點
if (tmp)
tmp->state=0;
}
// 喚醒隊列中的第一個節(jié)點,并清空鏈表,因為第一個節(jié)點會向后喚醒其他節(jié)點
void wake_up(struct task_struct **p)
{
if (p && *p) {
(**p).state=0;
*p=NULL;
}
}
我們發(fā)現(xiàn),進程的實現(xiàn),和我們平時寫代碼差不多,就是定義數(shù)據(jù)結(jié)構(gòu),然后實現(xiàn)操作數(shù)據(jù)結(jié)構(gòu)的算法。當然,因為涉及到硬件底層,操作系統(tǒng)的實現(xiàn)比我們的代碼復(fù)雜得多。
到此,相信大家對“Java進程的執(zhí)行和掛起是什么”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!