Linux編程:2、進程基礎知識

一、進程基本概念

1、進程與程序的區別
  • 程序:靜態的可執行文件(如電腦中的vs2022安裝程序)。
  • 進程:程序的動態執行過程(如啟動后的vs2022實例),是操作系統分配資源的單位(如 CPU 時間、內存)。
  • 特點:同一程序可啟動多個進程(如多個 vs2022?窗口),進程關閉后程序仍存在。
2、進程的組成
  • 進程控制塊(PCB):操作系統為每個進程創建的唯一標識,包含進程狀態、資源信息等。
  • 程序段(代碼):進程執行的代碼邏輯。
  • 數據集(數據):進程操作的數據。

二、進程控制塊(PCB)

1、核心字段
  • 進程號(PID):32 位無符號整數(Linux 最大為 32767),通過getpid()獲取當前進程號。
  • 進程狀態
    • R:可執行狀態。
    • S:可中斷睡眠。
    • D:不可中斷睡眠。
    • T:暫停或跟蹤狀態。
    • Z:僵尸進程(已退出但未釋放資源)。
    • X:即將銷毀的進程。
  • 查看命令ps -eo stat,pid,user,cmd(顯示狀態、PID、用戶、命令)。
2、其他字段
  • 優先級:決定 CPU 調度順序。
  • CPU 現場信息:保存進程暫停時的 CPU 狀態,以便恢復。
  • 資源清單:內存、I/O 設備等分配情況。
  • 隊列指針:鏈接同一狀態的進程(如就緒隊列、等待隊列)。

三、進程 PID 文件

1、存儲位置:
  • 位于/var/run目錄,文件名通常為進程名.pid,內容為單行的進程號。
  • 注意:需程序自行創建,系統不會自動生成。
2、作用:
  • 防止程序重復啟動(通過文件鎖機制實現)。
  • 示例代碼:通過fcntl加鎖判斷進程是否已運行。
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/file.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>// PID文件路徑,用于存儲當前運行實例的進程ID
    #define PID_FILE "/var/run/test.pid"/*** 檢查程序是否已在運行,確保只有一個實例** 返回值:*   0 - 程序未運行,當前是第一個實例*  -1 - 程序已在運行,當前實例退出*/
    int checkAlone(void)
    {int  fd;       // 文件描述符char buf[16];  // 存儲PID的緩沖區// 打開或創建PID文件,使用O_CREAT標志確保文件存在fd = open(PID_FILE, O_RDWR | O_CREAT, 0666);if (fd < 0) {perror("open pid failed");  // 打印錯誤信息exit(1);                    // 打開失敗時終止程序}// 定義文件鎖結構,準備加寫鎖struct flock fl;fl.l_type   = F_WRLCK;   // 寫鎖類型fl.l_start  = 0;         // 從文件開始位置fl.l_whence = SEEK_SET;  // 以文件起始為基準fl.l_len    = 0;         // 鎖定整個文件// 嘗試加非阻塞寫鎖// 返回值:0-成功,-1-失敗(文件已被鎖定)int ret = fcntl(fd, F_SETLK, &fl);if (ret < 0) {close(fd);             // 關閉文件描述符printf("Had run.\n");  // 提示已有實例在運行return -1;             // 返回錯誤碼}// 將當前進程ID寫入PID文件sprintf(buf, "%ld", (long)getpid());write(fd, buf, strlen(buf) + 1);printf("first running.\n");  // 提示首次運行return 0;                    // 返回成功
    }int main(void)
    {// 檢查程序是否已在運行if (checkAlone() < 0) {return -1;  // 已有實例在運行,退出當前進程}// 主程序邏輯:循環執行任務while (1) {printf("working...\n");   // 輸出工作狀態sleep(1);                // 休眠1秒}return 0;
    }
?3、開啟兩個終端:

第一次運行程序(第一個終端):

第二次運行程序(第二個終端) :


四、進程的創建

1、fork () 函數
  • 功能:創建子進程,返回兩次(父進程返回子進程 PID,子進程返回 0)。
  • 特點:子進程復制父進程的內存空間(不共享內存),繼承打開的文件描述符等資源。
  • 示例1
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>int main()
    {int count = 0;  // 用于父子進程各自計數的變量printf("準備創建子進程...\n");// 創建子進程:fork調用會返回兩次// 父進程返回子進程的PID(正值)// 子進程返回0// 返回負值表示創建失敗pid_t pid = fork();// 錯誤處理:創建子進程失敗if (pid < 0) {printf("創建子進程失敗");exit(1);  // 終止程序并返回錯誤碼1}// 子進程執行分支else if (pid == 0) {// 子進程中fork返回0// getpid()返回子進程自身的PIDprintf("我是子進程,pid=%d, 進程號=%d\n", pid, getpid());count++;  // 子進程的count加1}// 父進程執行分支else {// 父進程中fork返回子進程的PID// getpid()返回父進程自身的PIDprintf("我是父進程, pid=%d, 進程號=%d\n", pid, getpid());count++;  // 父進程的count加1}// 父子進程都會執行此語句// 通過判斷pid值區分當前是哪個進程printf("我是%s, count=%d\n", pid == 0 ? "子進程" : "父進程", count);return 0;
    }

    說明1:
    由 fork 創建的新進程被稱為子進程,原來的進程,稱為“父進程”

    該函數被調用一次,但返回兩次(在父進程中返回 1 次,子進程中返回 1 次)
    1)子進程的返回值是 0
    2)而父進程的返回值是子進程的 PID


    fork 執行完之后,子進程和父進程繼續執行 fork 之后的指令。
    父進程和子進程幾乎是等同的,它們具有相同的變量值(但變量內存并不共享),
    打開的文件也都相同,還有其他一些相同屬性。
    如果父進程改變了變量的值,子進程將不會看到這個變化。
    實際上, 子進程是父進程的一個復制(拷貝),但它們并不共享內存。
    父進程改變了變量的值,子進程中對應的變量不會有任何影響。

  • 示例2:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>int main()
    {int count = 0;  // 父子進程各自的計數器printf("準備創建子進程...\n");pid_t pid;// 循環兩次創建子進程,每次fork會產生父子兩個分支for (int i = 0; i < 2; i++) {pid = fork();  // 關鍵系統調用:創建新進程if (pid < 0) {perror("fork失敗");  // 輸出系統錯誤信息exit(1);             // 異常退出}else if (pid == 0) {// 子進程分支:pid為0,getpid()返回子進程IDprintf("[新的子進程]我是子進程,pid=%d, 進程號=%d\n", pid,getpid());count++;  // 子進程計數器加1}else {// 父進程分支:pid為子進程ID,getpid()返回父進程IDprintf("我是父進程, pid=%d, 進程號=%d\n", pid, getpid());count++;  // 父進程計數器加1}}// 父子進程最終都會執行此語句// 通過最后一次fork的返回值判斷當前是父進程還是子進程printf("我是%s, count=%d\n", pid == 0 ? "子進程" : "父進程", count);return 0;
    }



    for 循環了 2 次,實際上創建了 3 個子進程,而不是兩個。

2、exec 系列函數
  • 功能:用指定程序替換當前進程(成功后原進程代碼不再執行)。
  • 接口差異
    • l:參數以列表形式傳遞(如execl)。
    • p:從 PATH 環境變量查找程序(如execlp)。
    • v:參數通過指針數組傳遞(如execv)。
    • e:傳遞自定義環境變量(如execle)。
  • 示例
    無參的:
    ?
    #include <cstdio>
    #include <unistd.h>int main(int argc, char* argv[])
    {// 使用execl函數執行外部程序,替換當前進程映像// 參數1: 要執行的程序路徑// 參數2開始: 傳遞給程序的命令行參數,必須以NULL結尾execl("/bin/pwd",         // 指定要執行的程序路徑(絕對路徑)"pwd",              // 命令行參數列表的第一個參數,通常是程序名(可自定義)NULL);              // 參數列表結束標記,必須為NULL// 如果execl調用成功,當前進程會被完全替換,不會執行到這里// 如果執行到這里,說明execl調用失敗perror("execl failed");  // 打印系統錯誤信息return 1;                // 返回錯誤退出碼
    }



    帶參的:

    #include <unistd.h>
    int main(int argc, char* argv[])
    {// 相當于執行: ls -l /tmpexecl("/bin/ls", "ls", "-l", "/tmp", NULL);return 0;
    }

3、fork 與 exec 結合

  • 場景:父進程創建子進程后,子進程執行新程序(如 Shell 命令解析)。
  • 示例邏輯
    pid_t pid = fork();
    if (pid == 0) { execv("/path/to/program", argv); } // 子進程執行新程序

?

五、進程的分類

1、前臺進程
  • 定義:需與用戶交互的進程(如終端運行的程序),默認啟動即為前臺。
  • 查看命令ps -e | grep 進程名
2、后臺進程
  • 定義:無需交互,在后臺運行(如服務器程序)。
  • 啟動方式:命令后加&(如./a.out &)。
  • 終止命令killall 進程名
3、守護進程
  • 定義:特殊后臺進程,獨立于終端(如sshdhttpd),用于長期運行任務。
  • 特點
    • 不依附終端,終端關閉后仍運行。
    • 父進程通常為systemd(PID 1)。
  • 創建步驟
    1. fork后退出父進程,子進程成為孤兒進程。
    2. setsid創建新會話,脫離原終端。
    3. chdir("/")切換工作目錄至根目錄。
    4. umask(0)清除文件權限掩碼。
    5. 關閉默認文件描述符(0、1、2)。
  • 示例代碼:通過信號處理實現日志寫入的守護進程。
  • 查看命令ps axj(顯示 PPID、會話信息等)。

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

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

相關文章

React Router 中 navigate 后瀏覽器返回按鈕不起作用的問題記錄

React Router 中 navigate 后瀏覽器返回按鈕不起作用的問題記錄 在使用 React Router&#xff08;v6&#xff09;開發項目時&#xff0c;我遇到了一個讓人困惑的問題&#xff1a; 當我從 /article 頁面使用 navigate("/article/next") 進行跳轉后&#xff0c;點擊瀏…

[面試精選] 0094. 二叉樹的中序遍歷

文章目錄 1. 題目鏈接2. 題目描述3. 題目示例4. 解題思路5. 題解代碼6. 復雜度分析 1. 題目鏈接 94. 二叉樹的中序遍歷 - 力扣&#xff08;LeetCode&#xff09; 2. 題目描述 給定一個二叉樹的根節點 root &#xff0c;返回 它的 中序 遍歷 。 3. 題目示例 示例 1 : 輸入&…

Addressable-配置相關

1、Profile 概述窗口配置 主要用于配置Addressable打包&#xff08;構建&#xff09;加載AB包時使用的一些變量,這些變量定義了 在哪里保存打包&#xff08;構建&#xff09;的AB包運行時在哪里加載AB包 可以添加自定義變量&#xff0c;以便在打包加載時使用,之后在設置 組中…

aws(學習筆記第四十三課) s3_sns_sqs_lambda_chain

文章目錄 aws(學習筆記第四十三課) s3_sns_sqs_lambda_chain學習內容&#xff1a;1. 整體架構1.1 代碼鏈接1.2 整體架構1.3 測試代碼需要的修改1.3.1 unit test代碼中引入stack的修改1.3.2 test_outputs_created代碼中把錯誤的去掉 2. 代碼解析2.1 生成dead_letter_queue死信隊…

Python訓練營打卡Day43

kaggle找到一個圖像數據集&#xff0c;用cnn網絡進行訓練并且用grad-cam做可視化 進階&#xff1a;并拆分成多個文件 config.py import os# 基礎配置類 class Config:def __init__(self):# Kaggle配置self.kaggle_username "" # Kaggle用戶名self.kaggle_key &quo…

hive 3集成Iceberg 1.7中的Java版本問題

hive 3.1.3 集成iceberg 1.7.2創建Iceberg表報錯如下&#xff1a; Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/iceberg/mr/hive/HiveIcebergStorageHandler has been compiled by a more recent version of the Java Runtime …

文本切塊技術(Splitter)

為什么要分塊&#xff1f; 將長文本分解成適當大小的片段&#xff0c;以便于嵌入、索引和存儲&#xff0c;并提高檢索的精確度。 用ChunkViz工具可視化分塊 在線使用 ChunkViz github https://github.com/gkamradt/ChunkViz 如何確定大模型所能接受的最長上下文 可以從…

C++:用 libcurl 發送一封帶有附件的郵件

編寫mingw C 程序&#xff0c;用 libcurl 發送一封帶有附件的郵件 下面是一個使用 MinGW 編譯的 C 程序&#xff0c;使用 libcurl 發送帶附件的郵件。這個程序完全通過代碼實現 SMTP 郵件發送&#xff0c;不依賴外部郵件客戶端&#xff1a; // send_email.cpp #include <i…

tensorflow image_dataset_from_directory 訓練數據集構建

以數據集 https://www.kaggle.com/datasets/vipoooool/new-plant-diseases-dataset 為例 目錄結構 訓練圖像數據集要求&#xff1a; 主目錄下包含多個子目錄&#xff0c;每個子目錄代表一個類別。每個子目錄中存儲屬于該類別的圖像文件。 例如 main_directory/ ...cat/ ...…

遨游Spring AI:第一盤菜Hello World

Spring AI的正式版已經發布了&#xff0c;很顯然&#xff0c;接下來我們要做的事情就是寫一個Hello World。 總體思路就是在本地搭建一個簡單的大模型&#xff0c;然后編寫Spring AI代碼與模型進行交互。 分五步&#xff1a; 1. 安裝Ollama&#xff1b; 2. 安裝DeepSeek&…

華為云Flexus+DeepSeek征文|基于華為云Flexus X和DeepSeek-R1打造個人知識庫問答系統

目錄 前言 1 快速部署&#xff1a;一鍵搭建Dify平臺 1.1 部署流程詳解 1.2 初始配置與登錄 2 構建專屬知識庫 2.1 進入知識庫模塊并創建新庫 2.2 選擇數據源導入內容 2.3 上傳并識別多種文檔格式 2.4 文本處理與索引構建 2.5 保存并完成知識庫創建 3接入ModelArts S…

Java優化:雙重for循環

在工作中&#xff0c;經常性的會出現在兩張表中查找相同ID的數據&#xff0c;許多開發者會使用兩層for循環嵌套&#xff0c;雖然實現功能沒有問題&#xff0c;但是效率極低&#xff0c;一下是一個簡單的優化過程&#xff0c;代碼耗時湊從26856ms優化到了748ms。 功能場景 有兩…

Prompt Tuning:生成的模型文件有什么構成

一、為什么Prompt Tuning會生成模型文件? 1. Prompt Tuning的本質:優化可訓練的「提示參數」 核心邏輯:Prompt Tuning(提示調優)是一種輕量級的微調技術,僅優化模型輸入層的提示向量(Prompt Embedding)或少量額外參數,而非更新整個預訓練模型的權重。生成模型文件的原…

ARM SMMUv3簡介(一)

1.概述 SMMU&#xff08;System Memory Management Unit&#xff0c;系統內存管理單元&#xff09;是ARM架構中用于管理設備訪問系統內存的硬件模塊。SMMU和MMU的功能類似&#xff0c;都是將虛擬地址轉換成物理地址&#xff0c;不同的是MMU轉換的虛擬地址來自CPU&#xff0c;S…

在 Windows 系統上運行 Docker 容器中的 Ubuntu 鏡像并顯示 GUI

在 Windows 上安裝一個 X Server&#xff08;如 VcXsrv 或 X410&#xff09;&#xff0c;Ubuntu 容器通過網絡將圖形界面轉發到 Windows。 步驟&#xff1a; 安裝 X Server&#xff1a; 推薦使用VcXsrv&#xff0c;免費開源。 安裝后運行 XLaunch&#xff0c;選擇&#xff1…

Vue3學習(4)- computed的使用

1. 簡述與使用 作用&#xff1a;computed 用于基于響應式數據派生出新值&#xff0c;其值會自動緩存并在依賴變化時更新。 ?緩存機制?&#xff1a;依賴未變化時直接返回緩存值&#xff0c;避免重復計算&#xff08;通過 _dirty 標志位實現&#xff09;。?響應式更新?&…

【HarmonyOS 5】出行導航開發實踐介紹以及詳細案例

以下是 ?HarmonyOS 5? 出行導航的核心能力詳解&#xff08;無代碼版&#xff09;&#xff0c;聚焦智能交互、多端協同與場景化創新&#xff1a; 一、交互革新&#xff1a;從被動響應到主動服務 ?意圖驅動導航? ?自然語義理解?&#xff1a;用戶通過語音指令&#xff08;如…

csrf攻擊學習

原理 csrf又稱跨站偽造請求攻擊&#xff0c;現代網站利用Cookie、Session 或 Token 等機制識別用戶身份&#xff0c;一旦用戶訪問某個網站&#xff0c;瀏覽器在之后請求會自動帶上這些信息來識別用戶身份。用戶在網站進行請求或者操作時服務器會給出對應的內容&#xff0c;比如…

深入剖析MySQL鎖機制,多事務并發場景鎖競爭

一、隱藏字段對 InnoDB 的行鎖&#xff08;Record Lock&#xff09;與間隙鎖&#xff08;Gap Lock&#xff09;的影響 1. 隱藏字段與鎖的三大核心影響 類型影響維度描述DB_TRX_IDMVCC 可見性控制決定是否讀取當前版本&#xff0c;或在加鎖時避開不可見版本&#xff08;影響加鎖…

以SMMUv2為例,使用Trace32可視化操作SMMU的常用命令詳解

Trace32支持一系列的SMMU命令&#xff0c;可以幫助用戶更好地配置、查看和分析SMMU。換句話說&#xff0c;就是讓SMMU的配置變得可視化。 在添加SMMU實例之前&#xff0c;需要選擇一個CPU來激活該SMMU實例的相關命令。Trace32讓SMMU的配置可視化的本質是&#xff0c;操縱CPU讀取…