【Linux篇】進程入門指南:操作系統中的第一步

步入進程世界:初學者必懂的操作系統概念

  • 一. 馮諾依曼體系結構
    • 1.1 背景與歷史
    • 1.2 組成部分
    • 1.3 意義
  • 二. 進程
    • 2.1 進程概念
      • 2.1.1 PCB(進程控制塊)
    • 2.2 查看進程
      • 2.2.1 使用系統文件查看
      • 2.2.2 使?top和ps這些??級?具來獲取
      • 2.2.3 通過系統調用獲取進程標識符
    • 2.3 創建子進程
    • 2.4 進程狀態
      • 2.4.1 查看進程狀態
  • 三. 最后

前言

在計算機系統中,進程是執行程序的基本單位。它不僅僅是代碼的集合,更是操作系統管理和分配資源的核心對象。每當我們運行一個應用程序,操作系統就會為其創建一個進程,使得程序能夠在計算機中獨立執行并進行資源管理。理解進程的概念對于深入學習操作系統和高效利用計算機資源至關重要。 接下來的篇章將帶領大家深入探討進程管理。

💬 歡迎討論:如果你在學習過程中有任何問題或想法,歡迎在評論區留言,我們一起交流學習。你的支持是我繼續創作的動力!
👍 點贊、收藏與分享:覺得這篇文章對你有幫助嗎?別忘了點贊、收藏并分享給更多的小伙伴哦!你們的支持是我不斷進步的動力!
🚀 分享給更多人:如果你覺得這篇文章對你有幫助,歡迎分享給更多對Linux OS感興趣的朋友,讓我們一起進步!

一. 馮諾依曼體系結構

在這里插入圖片描述

1.1 背景與歷史

馮·諾依曼體系結構是現代計算機的基礎設計模型,由約翰·馮·諾依曼于1945年提出。該結構的核心思想是將程序和數據存儲在同一個內存中,計算機通過中央處理單元(CPU)按順序執行指令。再此向大佬致敬。👏

1.2 組成部分

  • CPU(中央處理器)由運算器和控制器組成。

存儲器(內存)是CPU進行讀、獲取的必要手段,CPU執行程序,必須先加載,將代碼及數據加載到內存,CPU執行代碼,訪問數據。

結構由五個基本組成部分構成:輸入設備、輸出設備、存儲器、運算器和控制單元。

1.3 意義

它的意義在于簡化了計算機設計,提高了計算機的可編程性,使得不同的程序可以通過修改存儲器中的指令和數據來實現多種功能。馮·諾依曼體系結構成為現代計算機系統的標準架構,推動了計算機技術的飛速發展。

二. 進程

2.1 進程概念

進程是程序的一次執行實例,是操作系統進行資源分配和調度的基本單位。它擁有獨立的內存空間、系統資源(如文件句柄、網絡端口)和運行狀態。

本人理解:進程 = 內核數據結構對象 + 代碼和數據 (進程 = PCB(進程控制塊) + 代碼和數據)

2.1.1 PCB(進程控制塊)

進程的所有屬性全保存在PCB中,Linux操作系統下的PCB為 task_struct, 該結構體為Linux內核中的一種數據結構,它會被加載到內存(RAM)中。

task_struct具有的部分信息,另一部分的信息將在后續的博客講解

標?符: 描述本進程的唯?標?符,?來區別其他進程。
? 狀態: 任務狀態,退出代碼,退出信號等。
? 優先級: 相對于其他進程的優先級。
? 程序計數器: 程序中即將被執?的下?條指令的地址。
? 內存指針: 包括程序代碼和進程相關數據的指針,還有和其他進程共享的內存塊的指針
? 上下?數據: 進程執?時處理器的寄存器中的數據[休學例?,要加圖CPU,寄存器]。
? I∕O狀態信息: 包括顯?的I/O請求,分配給進程的I∕O設備和被進程使?的?件列表。
? 記賬信息: 可能包括處理器時間總和,使?的時鐘數總和,時間限制,記賬號等。

OS如何對各種進程進行的管理的?先描述,在組織。
所有運行的進程都以 task_struct 鏈表的形式存在內核中。
在這里插入圖片描述

2.2 查看進程

2.2.1 使用系統文件查看

命令格式:

ls /proc/ [pid]

  • 功能

查看指定進程的進程信息。不加pid則查看所有進程的信息

2.2.2 使?top和ps這些??級?具來獲取

命令格式:

  • ps ajx | grep myprocess | grep -v grep

2.2.3 通過系統調用獲取進程標識符

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
return 0;
}
  • getpid()系統調用,用于獲取當前進程的 PID(Process ID),在子進程中調用 getpid(),返回的是子進程自身的 PID。
  • getppid()系統調用,用于獲取當前進程的父進程PID。

2.3 創建子進程

示例代碼:

#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>int gval = 100;int main()
{printf("父進程開始運行 ,pid: %d\n",getpid());pid_t id = fork();if(id < 0){perror("id");return 1;}else if(id == 0){printf("我是一個子進程 !, 我的pid:%d, 我的父進程id:%d, gval: %d\n",getpid(),getppid(),gval);sleep(5);//childwhile(1){sleep(1);printf("子進程修改變量 : %d -> %d", gval,  gval+10);gval+=10;printf("我是一個子進程 !, 我的pid:%d, 我的父進程id:%d\n",getpid(),getppid());}}else{//fatherwhile(1){sleep(1);printf("我是一個父進程 !, 我的pid:%d, 我的父進程id:%d, gval: %d\n",getpid(),getppid(),gval);}}printf("進程開始運行 ,pid: %d\n",getpid());return 0;
}

子進程會共享父進程的代碼和數據,如果父子任何一方對數據進行修改,OS系統會在底層第數據進行拷貝,讓目標進程修改這個拷貝。

問題1:為什么fork給父子返回各自不同的返回值?

  • 父進程中的返回值:

fork() 在父進程中返回 子進程的 PID(進程 ID)。這個 PID 是一個正整數,唯一標識子進程。父進程可以使用該 PID 來跟蹤子進程,執行如等待子進程結束、獲取子進程的狀態等操作。

  • 子進程中的返回值:

在子進程中,fork() 返回 0。子進程通過這個返回值可以判斷自己是否是子進程,父進程通過返回值判斷是否是父進程。

問題2:為什么一個函數會返回兩次?

  • 父進程的情況:

返回值是子進程的 PID(進程ID),是一個正整數。

父進程用這個 PID 來識別和管理子進程。父進程可以使用這個 PID 來執行如 wait()、waitpid() 等系統調用,等待子進程終止或獲取子進程的退出狀態。

  • 子進程的情況:

返回值是 0。

子進程用返回值 0 來判斷自己是子進程,以便執行不同于父進程的代碼。子進程可能會通過這個返回值執行某些特定的初始化工作或處理。

結論:fork() 會返回兩次是因為它在父進程和子進程中分別執行,父進程獲得的是子進程的 PID,子進程獲得的是 0。通過這個返回值,父進程和子進程可以執行不同的代碼,保證了進程的正確管理和并行執行。

問題3:fork兩個返回值各種給??如何返回?

  • 父進程:父進程使用返回子進程的PID,來管理或等待子進程。
  • 子進程:子進程返回0,子進程用這個值來判斷自己是子進程,以執行不同于父進程代碼邏輯(比如初始化、執行任務等)。
  • fork返回負值,表示fork調用失敗(資源不足等)它會返回 -1,并且沒有子進程創建。操作系統會設置 errno 來表示具體的錯誤原因。

2.4 進程狀態

請看Linux內核關于進程狀態的描述:

static const char *const task_state_array[] = {
“R (running)”, /*0 */
“S (sleeping)”, /*1 */
“D (disk sleep)”, /*2 */
“T (stopped)”, /*4 */
“t (tracing stop)”, /*8 */
“X (dead)”, /*16 */
“Z (zombie)”, /*32 */
};

  1. R(running): 運行狀態,表示某進程正在運行或準備運行。
  2. S(sleep): 睡眠狀態,進程在等待某些事件完成(也稱為淺度睡眠,可中斷睡眠)。
  3. D(disk sleep): 磁盤休眠狀態,進程通常在等待I/O操作完成(也稱為深度睡眠,不可中斷睡眠)。
  4. T(stopped): 停止狀態,可以通過發送信號讓該進程繼續進行。
  5. t(Tracing stop): 通常是在進行調試或進程跟蹤時出現的狀態。
  6. X(dead): 死亡狀態,不會出現在進程列表中。
  7. Z(Zombie): 僵尸狀態,子進程已結束,父進程為獲取子進程的退出信息。

2.4.1 查看進程狀態

使用ps aux 或 ps ajx 命令可以查看進程的詳細狀態。
命令選項含義:

  • a:顯??個終端所有的進程,包括其他??的進程。
  • x:顯?沒有控制終端的進程,例如后臺運?的守護進程。
  • j:顯?進程歸屬的進程組ID、會話ID、?進程ID,以及與作業控制相關的信息。
  • u:以??為中?的格式顯?進程信息,提供進程的詳細信息,如??、CPU和內存使?情況等。

僵尸進程危害
進程的退出狀態必須被維持下去,因為他要告訴關?它的進程(?進程),你交給我的任務,我辦的怎么樣了。可?進程如果?直不讀取,那?進程就?直處于Z狀態。
? 維護退出狀態本?就是要?數據維護,也屬于進程基本信息,所以保存在task_struct(PCB)中,
換句話說,Z狀態?直不退出,PCB?直都要維護?是的!
? 那?個?進程創建了很多?進程,就是不回收,是不是就會造成內存資源的浪費。因為數據結構對象本?就要占?內存,想想C中定義?個結構體變量(對象),是要在內存的某個位置進?開辟空間!
? 內存泄漏

孤兒進程

?進程如果提前退出,那么?進程后退出,進?Z之后,那該如何處理呢?
? ?進程先退出,?進程就稱之為“孤?進程”
? 孤?進程被1號init進程領養,當然要有init進程回收

如何避免孤兒進程

  1. 父進程等待子進程退出(避免子進程成為孤兒進程)

父進程可以通過適當的進程管理確保它會在子進程結束時正確地回收子進程的資源,避免進程成為孤兒進程。常用的技術包括:

wait() 或 waitpid():父進程可以使用 wait() 或 waitpid() 來等待子進程結束,并獲取子進程的退出狀態,從而清理和回收子進程的資源。這樣,即使父進程在結束之前退出,它也能確保子進程的資源得到回收。

  1. 使用 signal() 或 sigaction() 捕獲終止信號

如果父進程結束時沒有來得及清理子進程的資源,可以通過捕獲特定信號(如 SIGCHLD)來及時回收子進程的資源。通過設置 SIGCHLD 信號處理函數,父進程可以在子進程結束時自動清理。

  1. 避免父進程直接退出

父進程應該在子進程完成后再退出,例如通過使用 wait() 等系統調用等待子進程完成后再退出。如果父進程在子進程結束前退出,可能導致子進程變成孤兒進程。

定期檢查子進程狀態,使用 waitpid() 等方法主動回收子進程的資源。

三. 最后

本文主要介紹了操作系統中的進程管理,包括馮諾依曼體系結構、進程概念、進程控制塊(PCB)、進程狀態及如何查看和管理進程。
馮諾依曼體系結構是現代計算機設計的基礎,它將程序和數據存儲在同一內存中,提升了計算機的可編程性。進程則是程序的執行實例,操作系統通過進程控制塊(PCB)來管理進程的資源和狀態。進程通過 fork() 創建子進程,父子進程通過返回值區分身份。進程有不同的狀態,如運行、睡眠、停止等,父進程可以通過 wait() 等系統調用回收子進程資源,避免孤兒進程的產生。如果父進程提前退出,子進程可能成為孤兒進程,操作系統會由 init 進程接管。為了避免孤兒進程,父進程應在子進程結束后再退出,并通過信號捕獲機制及時清理資源。

路雖遠,行則將至;事雖難,做則必成

親愛的讀者們,下一篇文章再會!! \color{Red}親 愛 的 讀 者 們 , 下 一 篇 文 章 再 會 ! ! 親愛的讀者們,下一篇文章再會!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/73847.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73847.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73847.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

銷售易vs紛享銷客:制造行業CRM選型深度解析

“以客戶為中心”&#xff0c;顧名思義就是指讓客戶貫穿企業市場、研發、生產、銷售、服務全流程&#xff0c;以客戶需求為導向進行經營。CRM作為企業數字化建設基礎設施&#xff0c;在企業高質量發展進程中扮演著重要角色。在眾多CRM解決方案中&#xff0c;騰訊旗下CRM銷售易憑…

【JavaScript】九、JS基礎練習

文章目錄 1、練習&#xff1a;對象數組的遍歷2、練習&#xff1a;猜數字3、練習&#xff1a;生成隨機顏色 1、練習&#xff1a;對象數組的遍歷 需求&#xff1a;定義多個對象&#xff0c;存數組&#xff0c;遍歷數據渲染生成表格 let students [{ name: 小明, age: 18, gend…

代碼隨想錄day31 貪心part05

56.合并區間 以數組 intervals 表示若干個區間的集合&#xff0c;其中單個區間為 intervals[i] [starti, endi] 。請你合并所有重疊的區間&#xff0c;并返回 一個不重疊的區間數組&#xff0c;該數組需恰好覆蓋輸入中的所有區間 。 示例 1&#xff1a; 輸入&#xff1a;in…

《C++11:通過thread類編寫C++多線程程序》

關于多線程的概念與理解&#xff0c;可以先了解Linux下的底層線程。當對底層線程有了一定程度理解以后&#xff0c;再學習語言級別的多線程編程就輕而易舉了。 【Linux】多線程 -&#xff1e; 從線程概念到線程控制 【Linux】多線程 -&#xff1e; 線程互斥與死鎖 語言級別的…

c++位運算總結

在C中&#xff0c;位運算是對二進制位進行操作的運算&#xff0c;主要有以下幾種&#xff1a; 1. 按位與&#xff08; & &#xff09;&#xff1a;兩個操作數對應位都為1時&#xff0c;結果位才為1&#xff0c;否則為0。例如 3 & 5 &#xff0c; 3 二進制是 0000 0011…

1.1 計算機網絡的概念

首先來看什么是計算機網絡&#xff0c;關于計算機網絡的定義并沒有一個統一的標準&#xff0c;不同的教材有 不同的說法&#xff08;這是王道書對于計算機網絡的定義&#xff09;&#xff0c;我們可以結合自己的生活經驗去體會這個 定義。 可以用不同類型的設備去連接計算機網絡…

用LLama factory時報類似Process 2504721 got signal: 1的解決方法

之前用nohup來遠程跑LLama factory微調腳本&#xff0c;是沒有問題的&#xff0c;但今天發現運行類似下面這個命令時&#xff0c; nohup llamafactory-cli train examples/train_qlora/qwen_lora.yaml 只要一關閉ssh session&#xff0c;就會終止訓練&#xff0c;報類似&…

python常用內置時間函數+藍橋杯時間真題

1.time 1.1 time.time() 時間戳指&#xff1a;1970年1月1日開始到現在所經過的秒數 import time print(time.time()) # 輸出可得1970年1月1日開始到執行此代碼所經過的秒數 1.2 time.localtime() 返回一個當前時間的時間對象&#xff0c;具體信息&#xff0c;并且可以單獨…

一個用 C 語言打印出所有三位數水仙花數的程序

水仙花數&#xff08;Narcissistic number&#xff09;是指一個三位數&#xff0c;其各位數字的立方和等于該數本身。例如&#xff1a;153 是一個水仙花數&#xff0c;因為 (1^3 5^3 3^3 153)。 以下是一個用 C 語言打印出所有三位數水仙花數的程序&#xff1a; 代碼實現 …

利用 VSCode 配置提升 vibe coding 開發效率

利用 VSCode 配置提升 vibe coding 開發效率 Vibe Coding&#xff08;氛圍編程&#xff09;是一種基于AI的編程方法&#xff0c;其核心在于通過自然語言描述軟件需求&#xff0c;再由大規模語言模型&#xff08;LLM&#xff09;自動生成代碼&#xff0c;從而實現對傳統手寫編程…

練習題:110

目錄 Python題目 題目 題目分析 需求理解 關鍵知識點 實現思路分析 代碼實現 代碼解釋 函數定義&#xff1a; 計算值的總和&#xff1a; 測試函數&#xff1a; 運行思路 結束語 Python題目 題目 定義一個函數&#xff0c;接受一個字典作為參數&#xff0c;返回字…

處理 Linux 信號:進程控制與異常管理的核心

個人主頁&#xff1a;chian-ocean 文章專欄-Linux 前言&#xff1a; 在 Linux 操作系統中&#xff0c;信號是用于進程間通信的一種機制&#xff0c;能夠向進程發送通知&#xff0c;指示某些事件的發生。信號通常由操作系統內核、硬件中斷或其他進程發送。接收和處理信號是 Li…

通信協議之串口

文章目錄 簡介電平標準串口參數及時序USART與UART過程引腳配置 簡介 點對點&#xff0c;只能兩設備通信只需單向的數據傳輸時&#xff0c;可以只接一根通信線當電平標準不一致時&#xff0c;需要加電平轉換芯片&#xff08;一般從控制器出來的是信號是TTL電平&#xff09;地位…

Unity編輯器功能及拓展(1) —特殊的Editor文件夾

Unity中的Editor文件夾是一個具有特殊用途的目錄&#xff0c;主要用于存放與編輯器擴展功能相關的腳本和資源。 一.糾纏不清的UnityEditor 我們Unity中進行游戲構建時&#xff0c;我們經常遇到關于UnityEditor相關命名空間丟失的報錯&#xff0c;這時候&#xff0c;只得將報錯…

工具類-csv文件導入數據庫思路

首先&#xff0c;讓我們來看下數據庫建表語句&#xff1a; CREATE TABLE behavior_reports (id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 報告ID,report_type VARCHAR(50) NOT NULL COMMENT 報告類型(daily, weekly, monthly),start_date DATE NOT NULL COMMENT 開始日期,e…

軟件工程之軟件開發模型(瀑布、迭代、敏捷、DevOps)

1. 瀑布模型&#xff08;Waterfall Model&#xff09; 定義與流程 瀑布模型是線性順序的開發流程&#xff0c;包含需求分析、設計、編碼、測試、維護等階段&#xff0c;每個階段完成后才能進入下一階段&#xff0c;類似“瀑布流水”逐級推進。 核心特點 嚴格階段劃分&#…

FreeRTOS與RT-Thread內存分配對比分析

一、動態內存分配策略 ?FreeRTOS ?分配算法多樣性&#xff1a;提供5種動態內存管理算法&#xff08;heap_1至heap_5&#xff09;&#xff0c;覆蓋從簡單到復雜的場景。例如&#xff1a; heap_1&#xff1a;僅支持分配不支持釋放&#xff0c;適用于固定任務棧分配。heap_4&…

202519 | Mybatis-Plus

快速入門 MyBatis-Plus&#xff08;簡稱 MP&#xff09;是 MyBatis 的增強工具&#xff0c;它在 MyBatis 的基礎上只做增強不做改變&#xff0c;簡化了開發&#xff0c;提高了效率。以下是 MyBatis-Plus 的快速入門指南&#xff0c;幫助您快速上手使用。 1. 環境準備 JDK&…

Linux C語言調用第三方庫,第三方庫如何編譯安裝

在 Linux 環境下使用 C 語言調用第三方庫時&#xff0c;通常需要先對第三方庫進行編譯和安裝。以下為你詳細介紹一般的編譯安裝步驟&#xff0c;并給出不同類型第三方庫&#xff08;如使用 Makefile、CMake 構建系統&#xff09;的具體示例。 一般步驟 1. 獲取第三方庫源碼 …

linux基本命令(1)--linux下的打包命令 -- tar 和gzip

tar 解壓 &#xff0c;打包 語法&#xff1a;tar [主選項輔選項] 文件或者目錄 使用該命令時&#xff0c;主選項是必須要有的&#xff0c;它告訴tar要做什么事情&#xff0c;輔選項是輔助使用的&#xff0c;可以選用。 主選項&#xff1a; c 創建新的檔案文件。如果用戶想備…