操作系統(tǒng)

下文參考鏈接

進程有那些狀態(tài)?

答:

  • 創(chuàng)建狀態(tài)(new) :進程正在被創(chuàng)建,尚未到就緒狀態(tài)。
  • 就緒狀態(tài)(ready) :進程已處于準備運行狀態(tài),即進程獲得了除了處理器之外的一切所需資源,一旦得到處理器資源(處理器分配的時間片)即可運行。
  • 運行狀態(tài)(running) :進程正在處理器上上運行(單核 CPU 下任意時刻只有一個進程處于運行狀態(tài))。
  • 阻塞狀態(tài)(waiting) :又稱為等待狀態(tài),進程正在等待某一事件而暫停運行如等待某資源為可用或等待 IO 操作完成。即使處理器空閑,該進程也不能運行。
  • 結束狀態(tài)(terminated) :進程正在從系統(tǒng)中消失。可能是進程正常結束或其他原因中斷退出運行。

進程間的通信方式

1. 管道/匿名管道(Pipes) :用于具有親緣關系的父子進程間或者兄弟進程之間的通信。
2. 有名管道(Names Pipes) : 匿名管道由于沒有名字,只能用于親緣關系的進程間通信。為了克服這個缺點,提出了有名管道。有名管道嚴格遵循先進先出(first in first out)。有名管道以磁盤文件的方式存在,可以實現(xiàn)本機任意兩個進程通信。
3. 信號(Signal) :信號是一種比較復雜的通信方式,用于通知接收進程某個事件已經(jīng)發(fā)生;
4. 消息隊列(Message Queuing) :消息隊列是消息的鏈表,具有特定的格式,存放在內(nèi)存中并由消息隊列標識符標識。管道和消息隊列的通信數(shù)據(jù)都是先進先出的原則。與管道(無名管道:只存在于內(nèi)存中的文件;命名管道:存在于實際的磁盤介質(zhì)或者文件系統(tǒng))不同的是消息隊列存放在內(nèi)核中,只有在內(nèi)核重啟(即,操作系統(tǒng)重啟)或者顯示地刪除一個消息隊列時,該消息隊列才會被真正的刪除。消息隊列可以實現(xiàn)消息的隨機查詢,消息不一定要以先進先出的次序讀取,也可以按消息的類型讀取.比 FIFO 更有優(yōu)勢。消息隊列克服了信號承載信息量少,管道只能承載無格式字 節(jié)流以及緩沖區(qū)大小受限等缺。
5. 信號量(Semaphores) :信號量是一個計數(shù)器,用于多進程對共享數(shù)據(jù)的訪問,信號量的意圖在于進程間同步。這種通信方式主要用于解決與同步相關的問題并避免競爭條件。
6. 共享內(nèi)存(Shared memory) :使得多個進程可以訪問同一塊內(nèi)存空間,不同進程可以及時看到對方進程中對共享內(nèi)存中數(shù)據(jù)的更新。這種方式需要依靠某種同步操作,如互斥鎖和信號量等??梢哉f這是最有用的進程間通信方式。
7. 套接字(Sockets) :此方法主要用于在客戶端和服務器之間通過網(wǎng)絡進行通信。套接字是支持 TCP/IP 的網(wǎng)絡通信的基本操作單元,可以看做是不同主機之間的進程進行雙向通信的端點,簡單的說就是通信的兩方的一種約定,用套接字中的相關函數(shù)來完成通信過程。

線程之間的通信方式?

答:
1. 共享內(nèi)存:線程之間共享程序的公共狀態(tài),線程之間通過讀-寫內(nèi)存中的公共狀態(tài)來隱式通信。volatile共享內(nèi)存
2. 消息傳遞:線程之間沒有公共的狀態(tài),線程之間必須通過明確的發(fā)送信息來顯示的進行通信。wait/notify等待通知方式、join方式
3. 使用阻塞隊列控制線程通信:管道輸入/輸出流的形式
4.使用管道流進行線程通信(已被上面的阻塞隊列代替)
通過輸入/輸出在線程間進行通信通常很有用。Java中對應的實現(xiàn)就是PipedWriter類和PipedReader類。這種使用管道來通信的模型可以看成是"生產(chǎn)者-消費者"問題的變種,這里的管道就是一個封裝好的解決方案。管道基本上就是一個阻塞隊列,它存在于引入阻塞隊列之前的java版本中。在實際開發(fā)中,很少會使用到管道流。

用戶級線程和內(nèi)核級線程?

答:
用戶級線程和內(nèi)核級線程
用戶級線程和內(nèi)核級線程

線程的同步方式?

1. 互斥量(Mutex):采用互斥對象機制,只有擁有互斥對象的線程才有訪問公共資源的權限。因為互斥對象只有一個,所以可以保證公共資源不會被多個線程同時訪問。比如 Java 中的 synchronized 關鍵詞和各種 Lock 都是這種機制。
2. 信號量(Semphares) :它允許同一時刻多個線程訪問同一資源,但是需要控制同一時刻訪問此資源的最大線程數(shù)量
3. 事件(Event) :Wait/Notify:通過通知操作的方式來保持多線程同步,還可以方便的實現(xiàn)多線程優(yōu)先級的比較操

操作系統(tǒng)中進程的調(diào)度算法有哪些嗎?

  • 先到先服務(FCFS)調(diào)度算法 : 從就緒隊列中選擇一個最先進入該隊列的進程為之分配資源,使它立即執(zhí)行并一直執(zhí)行到完成或發(fā)生某事件而被阻塞放棄占用 CPU 時再重新調(diào)度。
  • 短作業(yè)優(yōu)先(SJF)的調(diào)度算法 : 從就緒隊列中選出一個估計運行時間最短的進程為之分配資源,使它立即執(zhí)行并一直執(zhí)行到完成或發(fā)生某事件而被阻塞放棄占用 CPU 時再重新調(diào)度。
  • 時間片輪轉調(diào)度算法 :時間片輪轉調(diào)度是一種最古老,最簡單,最公平且使用最廣的算法,又稱 RR(Round robin)調(diào)度。每個進程被分配一個時間段,稱作它的時間片,即該進程允許運行的時間。
  • 優(yōu)先級調(diào)度 : 為每個流程分配優(yōu)先級,首先執(zhí)行具有最高優(yōu)先級的進程,依此類推。具有相同優(yōu)先級的進程以 FCFS 方式執(zhí)行??梢愿鶕?jù)內(nèi)存要求,時間要求或任何其他資源要求來確定優(yōu)先級。
  • 多級反饋隊列調(diào)度算法 :前面介紹的幾種進程調(diào)度的算法都有一定的局限性。如短進程優(yōu)先的調(diào)度算法,僅照顧了短進程而忽略了長進程 。多級反饋隊列調(diào)度算法既能使高優(yōu)先級的作業(yè)得到響應又能使短作業(yè)(進程)迅速完成。,因而它是目前被公認的一種較好的進程調(diào)度算法,UNIX 操作系統(tǒng)采取的便是這種調(diào)度算法。

過程:
1、按照先來先服務原則排序,設置N個就緒隊列為Q1,Q2...QN,每個隊列中都可以放很多作業(yè);
2、為這N個就緒隊列賦予不同的優(yōu)先級,第一個隊列的優(yōu)先級最高,第二個隊列次之,其余各隊列的優(yōu)先權逐個降低;
3、設置每個就緒隊列的時間片,優(yōu)先權越高,算法賦予隊列的時間片越小。時間片大小的設定按照實際作業(yè)(進程)的需要調(diào)整;
4、進程在進入待調(diào)度的隊列等待時,首先進入優(yōu)先級最高的Q1等待。
5、首先調(diào)度優(yōu)先級高的隊列中的進程。若高優(yōu)先級中隊列中已沒有調(diào)度的進程,則調(diào)度次優(yōu)先級隊列中的進程。例如:Q1,Q2,Q3三個隊列,只有在Q1中沒有進程等待時才去調(diào)度Q2,同理,只有Q1,Q2都為空時才會去調(diào)度Q3。
6、對于同一個隊列中的各個進程,按照時間片輪轉法調(diào)度。比如Q1隊列的時間片為N,那么Q1中的作業(yè)在經(jīng)歷了時間片為N的時間后,若還沒有完成,則進入Q2隊列等待,若Q2的時間片用完后作業(yè)還不能完成,一直進入下一級隊列,直至完成。
7、在低優(yōu)先級的隊列中的進程在運行時,又有新到達的作業(yè),那么在運行完這個時間片后,CPU馬上分配給新到達的作業(yè)即搶占式調(diào)度CPU。

多線程和多進程區(qū)別?

答:
線程(CPU調(diào)度和分派的基本單位)進程(操作系統(tǒng)進行資源分配和調(diào)度的基本單位)劃分成的更小的運行單位,一個進程在其執(zhí)行的過程中可以產(chǎn)生多個線程。線程和進程最大的不同在于基本上各進程是獨立的,而各線程則不一定,因為同一進程中的線程極有可能會相互影響。線程執(zhí)行開銷小,但不利于資源的管理和保護;而進程正相反,并且線程中內(nèi)存地址空間是相互共享的,而進程中不是。因此,進程和線程其實都是內(nèi)核調(diào)度實體(KSE),只是對?些系統(tǒng)資源,例如虛擬內(nèi)存、打開?件描述符、對信號的處置、進程 ID 等資源的共享程度不同?已。所以我們可以推斷出以下結論:

  1. 線程間的通信更容易,因為擁有著同?塊數(shù)據(jù)段,因?可以使?全局變量進?通信,相當于繼承,大家公用一部分資源。
  2. 線程的創(chuàng)建速度要高于進程,因為“數(shù)據(jù)重合度”更?,?線程只需要擁有??的程序計數(shù)器,一組寄存器和棧即可(1、程序計數(shù)器為什么是私有的?程序計數(shù)器私有主要是為了線程切換后能恢復到正確的執(zhí)行位置。2、棧為什么是私有的?保證線程中的局部變量不被別的線程訪問到,虛擬機棧和本地方法棧是線程私有的。)
  3. 線程之間的上下?切換也要?進程間的上下?切換更快,因為線程更加輕量,自然在切換的過程中消耗的資源也更少(什么是上下文切換?線程切換意味著需要保存當前線程的上下文,留待線程下次占用 CPU 的時候恢復現(xiàn)場。并加載下一個將要占用 CPU 的線程上下文。這就是所謂的 上下文切換。)。
  4. 線程同步的時候需要同步機制來支持,因為資源共享,我們在共享資源操作的時候,需要加額外的操作,但是進程不用,進程的資源是獨立的,同步的時候更加容易

協(xié)程和線程區(qū)別?

答:

  • 概念:協(xié)程是一種比線程更加輕量級的存在,一個線程可以擁有多個協(xié)程。協(xié)程不是被操作系統(tǒng)內(nèi)核所管理,而是完全由程序所控制(也就是在用戶態(tài)執(zhí)行),好處是性能得到了很大提升,不會像線程切換那樣消耗資源。協(xié)程擁有自己的寄存器上下文和棧。協(xié)程調(diào)度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。因此:協(xié)程能保留上一次調(diào)用時的狀態(tài)(即所有局部狀態(tài)的一個特定組合),每次過程重入時,就相當于進入上一次調(diào)用的狀態(tài),換種說法:進入上一次離開時所處邏輯流的位置。
  • 協(xié)程的好處:
    無需線程上下文切換的開銷(無需切換內(nèi)核態(tài)與用戶態(tài))
    無需原子操作鎖定及同步的開銷
    方便切換控制流,簡化編程模型
    線程進程都是同步機制,而協(xié)程則是異步。
  • 應用場景:可以在線程IO阻塞的時候,去運行協(xié)程,提高CPU利用率
    什么是協(xié)程?(參考鏈接)

并發(fā)和并行的區(qū)別

  • 并發(fā):
    并發(fā)(Concurrent),在操作系統(tǒng)中,是指一個時間段中有幾個程序都處于已啟動運行到運行完畢之間,且這幾個程序都是在同一個處理機上運行。

就想前面提到的操作系統(tǒng)的時間片分時調(diào)度。打游戲和聽音樂兩件事情在同一個時間段內(nèi)都是在同一臺電腦上完成了從開始到結束的動作。那么,就可以說聽音樂和打游戲是并發(fā)的。

  • 并行:
    并行(Parallel),當系統(tǒng)有一個以上CPU時,當一個CPU執(zhí)行一個進程時,另一個CPU可以執(zhí)行另一個進程,兩個進程互不搶占CPU資源,可以同時進行,這種方式我們稱之為并行(Parallel)。

這里面有一個很重要的點,那就是系統(tǒng)要有多個CPU才會出現(xiàn)并行。在有多個CPU的情況下,才會出現(xiàn)真正意義上的『同時進行』。

什么是僵尸進程?

答:僵尸進程是當子進程比父進程先結束,而父進程又沒有回收子進程,釋放子進程占用的資源,此時子進程將成為一個僵尸進程。如果父進程先退出,子進程被init接管,子進程推出后init會回收其占用的相關資源。如果太多僵尸進程的話,會導致系統(tǒng)的進程號不夠用,不再產(chǎn)生進程。解決方法: (1) 讓僵尸進程成為孤兒進程,由init進程回收;(手動殺死父進程)。(2) 父進程用wait或waitpid去回收資源(方案不好)父進程通過wait或waitpid等函數(shù)去等待子進程結束,但是不好,會導致父進程一直等待被掛起,相當于一個進程在干活,沒有起到多進程的作用。

線程死鎖是如何產(chǎn)生的,如何避免 ?

答:

  • 線程死鎖的條件:
  1. 互斥條件:一個資源在同一時刻只由一個線程占用。
  2. 請求與保持條件:一個線程在請求被占資源時發(fā)生阻塞,并對已獲得的資源保持不放。
  3. 循環(huán)等待條件:發(fā)生死鎖時,所有的線程會形成一個死循環(huán),一直阻塞。
  4. 不剝奪條件:線程已獲得的資源在未使用完不能被其他線程剝奪,只能由自己使用完釋放資源。
  • 避免死鎖的方法:只有上面四個條件達成才能形成死鎖,所以我們只需要破壞上面任意一個條件即可
  1. 破壞互斥條件:使資源同時訪問而非互斥使用,就沒有進程會阻塞在資源上,從而不發(fā)生死鎖。但是這種場景很少,因為你資源共享的話,如果是只讀就可以,但是設計到修改很可能會導致異常。而且我們加鎖就是為了互斥。
  2. 破壞占有和等待條件:采用靜態(tài)分配的方式,靜態(tài)分配的方式是指進程必須在執(zhí)行之前就申請需要的全部資源,且直至所要的資源全部得到滿足后才開始執(zhí)行。
  3. 占有部分資源的線程進一步申請其他資源時,如果申請不到,主動釋放它占有的資源,破壞 "不可搶占" 條件
  4. 按序申請資源,破壞 "循環(huán)等待" 條件

io多路復用,介紹select,poll,epoll原理,他們的優(yōu)缺點及不同?

手寫死鎖?

    Lock lock1 = new ReentrantLock();
    Lock lock2 = new ReentrantLock();
    static Runnable a = () -> {
        try {
            while (true) {
                HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
//                    lock1.lock();
                synchronized (test.obj1) {
                    System.out.println("Thread 1 lock 1");
                    Thread.sleep(5000);
//                        lock2.lock();
                    synchronized (test.obj2) {
                        System.out.println("Thread 1 lock 2");
                        Thread.sleep(5000);
                    }
//                        lock2.unlock();
                    System.out.println("Thread 1 unlock 2");
//                        lock1.unlock();
                }
                System.out.println("Thread 1 unlock 1");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    };



    static Thread thread1 = new Thread(a);
    static Thread thread2 = new Thread(() -> {
        try {
            while (true) {
//                    lock2.lock();
                synchronized (test.obj2) {
                    System.out.println("Thread 2 lock 2");
                    Thread.sleep(5000);
//                    lock1.lock();
                    synchronized (test.obj1) {
                        System.out.println("Thread 2 lock 1");
                        Thread.sleep(5000);
                    }
//                    lock1.unlock();
                    System.out.println("Thread 2 unlock 1");
//                    lock2.unlock();
                }
                System.out.println("Thread 2 unlock 2");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    

    public static String obj1 = "obj1";
    public static String obj2 = "obj2";

    public static void main(String[] args) {
        thread1.start();
        thread2.start();
    }

簡述操作系統(tǒng)如何進行內(nèi)存管理?

答:

  • 為什么要內(nèi)存管理?
    答:早期,程序直接運行在物理內(nèi)存上,直接操作物理內(nèi)存,這種方式存在幾個問題:
    1、地址空間不隔離:程序操作相同地址空間會造成互相影響甚至崩潰,而且安全性也得不到保證;2、使用效率低:沒有特別好的策略保證多個進程對超過物理內(nèi)存大小的內(nèi)存需求的滿足;3、程序運行地址不確定:程序運行時,都需要分配空閑區(qū)域,而空閑位置不確定,會帶來一些重定位問題;
  • 虛擬內(nèi)存
    計算機系統(tǒng)里任何問題都可以靠引入一個中間層來解決,內(nèi)存管理就在程序和物理內(nèi)存之間引入了虛擬內(nèi)存的概念;對進程地址和物理地址進行隔離;

參考鏈接

簡述操作系統(tǒng)中的缺頁中斷?

答:

  • 概念: malloc()和mmap()等內(nèi)存分配函數(shù),在分配時只是建立了進程虛擬地址空間,并沒有分配虛擬內(nèi)存對應的物理內(nèi)存。當進程訪問這些沒有建立映射關系的虛擬內(nèi)存時,處理器自動觸發(fā)一個缺頁異常。
  • 缺頁中斷:在請求分頁系統(tǒng)中,可以通過查詢頁表中的狀態(tài)位來確定所要訪問的頁面是否存在于內(nèi)存中。每當所要訪問的頁面不在內(nèi)存是,會產(chǎn)生一次缺頁中斷,此時操作系統(tǒng)會根據(jù)頁表中的外存地址在外存中找到所缺的一頁,將其調(diào)入內(nèi)存。

什么時候會由用戶態(tài)陷入內(nèi)核態(tài)?

答:

  • 為何要區(qū)分用戶態(tài)和內(nèi)核態(tài)?
    最簡單的運行程序的方式是“直接執(zhí)行”,即直接在 CPU 上執(zhí)行任意程序。直接執(zhí)行的問題是:1、如何限制代碼行為?比如禁止:設置特殊寄存器的值、訪問存儲器的任意位置、I/O 請求、申請更多系統(tǒng)資源等。2、在運行這個程序的時候,如何切換到另一個程序?進程調(diào)度應該是 OS 才有的權限。因此引入用戶態(tài)和內(nèi)核態(tài)和兩種模式。用戶態(tài)無法執(zhí)行受限操作,如 I/O 請求,執(zhí)行這些操作會引發(fā)異常。核心態(tài)只能由操作系統(tǒng)運行,可以執(zhí)行特權操作。用戶程序通過系統(tǒng)調(diào)用 system call 執(zhí)行這些特權操作。OS 執(zhí)行前會判斷進程是否有權限執(zhí)行相應的指令。區(qū)分用戶態(tài)和核心態(tài)的執(zhí)行機制稱為“受限直接執(zhí)行”(Limited Direct Execution)。
  • 什么時候會陷入內(nèi)核態(tài)?

系統(tǒng)調(diào)用(trap)、中斷(interrupt)和異常(exception)。

系統(tǒng)調(diào)用是用戶進程主動發(fā)起的操作。發(fā)起系統(tǒng)調(diào)用,陷入內(nèi)核,由操作系統(tǒng)執(zhí)行系統(tǒng)調(diào)用,然后再返回到進程。

中斷和異常是被動的,無法預測發(fā)生時機。中斷包括 I/O 中斷、外部信號中斷、各種定時器引起的時鐘中斷等。異常包括程序運算引起的各種錯誤如除 0、緩沖區(qū)溢出、缺頁等。

在系統(tǒng)的處理上,中斷和異常類似,都是通過中斷向量表來找到相應的處理程序進行處理。區(qū)別在于,中斷來自處理器外部,不是由任何一條專門的指令造成,而異常是執(zhí)行當前指令的結果。

操作系統(tǒng)中,虛擬地址與物理地址之間如何映射?

Linux 下如何查看端口被哪個進程占用?

答:lsof -i:端口號

進程通信中的管道實現(xiàn)原理是什么?

答:

  • 管道是如何通信的:
    管道是由內(nèi)核管理的一個緩沖區(qū),相當于我們放入內(nèi)存中的一個紙條。管道的一端連接一個進程的輸出。這個進程會向管道中放入信息。管道的另一端連接一個進程的輸入,這個進程取出被放入管道的信息。一個緩沖區(qū)不需要很大,它被設計成為環(huán)形的數(shù)據(jù)結構,以便管道可以被循環(huán)利用。當管道中沒有信息的話,從管道中讀取的進程會等待,直到另一端的進程放入信息。當管道被放滿信息的時候,嘗試放入信息的進程會等待,直到另一端的進程取出信息。當兩個進程都終結的時候,管道也自動消失。

  • 管道是如何創(chuàng)建的:
    從原理上,管道利用fork機制建立,從而讓兩個進程可以連接到同一個PIPE上。最開始的時候,上面的兩個箭頭都連接在同一個進程Process 1上(連接在Process 1上的兩個箭頭)。當fork復制進程的時候,會將這兩個連接也復制到新的進程(Process 2)。隨后,每個進程關閉自己不需要的一個連接 (兩個黑色的箭頭被關閉; Process 1關閉從PIPE來的輸入連接,Process 2關閉輸出到PIPE的連接),這樣,剩下的紅色連接就構成了如上圖的PIPE。

  • 管道通信的實現(xiàn)細節(jié):
    在 Linux 中,管道的實現(xiàn)并沒有使用專門的數(shù)據(jù)結構,而是借助了文件系統(tǒng)的file結構和VFS的索引節(jié)點inode。通過將兩個 file 結構指向同一個臨時的 VFS 索引節(jié)點,而這個 VFS 索引節(jié)點又指向一個物理頁面而實現(xiàn)的。如下圖

    例子

    有兩個 file 數(shù)據(jù)結構,但它們定義文件操作例程地址是不同的,其中一個是向管道中寫入數(shù)據(jù)的例程地址,而另一個是從管道中讀出數(shù)據(jù)的例程地址。這樣,用戶程序的系統(tǒng)調(diào)用仍然是通常的文件操作,而內(nèi)核卻利用這種抽象機制實現(xiàn)了管道這一特殊操作。

Linux 下如何排查 CPU 以及 內(nèi)存占用過多?

答:CPU的話使用TOP命令去查一下哪些線程

簡述 Linux 虛擬內(nèi)存的頁面置換算法?

簡述 Linux 零拷貝的原理?

答:
參考文章

Linux 中虛擬內(nèi)存和物理內(nèi)存有什么區(qū)別?有什么優(yōu)點?

BIO、NIO 有什么區(qū)別?怎么判斷寫文件時 Buffer 已經(jīng)寫滿?簡述 Linux 的 IO模型

簡述 mmap 的使用場景以及原理?

簡述操作系統(tǒng)中 malloc 的實現(xiàn)原理?

LVS 的 NAT、TUN、DR 原理及區(qū)別?

共享內(nèi)存是如何實現(xiàn)的
image.png

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容