進程概念、PCB及進程查看

文章目錄

  • 一.進程的概念
    • 進程控制塊(PCB)
  • 二.進程查看
    • 通過指令查看進程
    • 通過proc目錄查看
    • 進程的`cwd`和`exe`
    • 獲取進程pid和ppid
    • 通過fork()創建子進程

一.進程的概念

進程是一個運行起來的程序,而程序是存放在磁盤的,cpu要想執行程序的指令,需要先將程序加載到內存中。

課本概念:進程是被加載到內存運行的程序
內核觀點:擔當分配系統資源(CPU時間,內存)的實體。

操作系統中有著大量的進程,操作系統作為管理者,管理的其實是大量進程相關的數據,那么如何管理這些數據呢?

先描述,再組織

當二進制代碼直接加載到內存時,操作系統為了更好地管理加載的程序,創建了描述該進程的數據結構。這樣,操作系統只用看這個數據結構,不用管各種復雜多樣的二進制代碼,并且將它們組織起來進行管理

進程控制塊(PCB)

這個數據結構叫PCB(process control block),進程信息被放在其中,可以理解為進程屬性的集合,在linux的PCB是task_struct

struct task_struct {volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */struct thread_info *thread_info;atomic_t usage;unsigned long flags; /* per process flags, defined below */unsigned long ptrace;int lock_depth;  /* Lock depth */int prio, static_prio;struct list_head run_list;prio_array_t *array;//.....
}

當有一個程序被加載到內存時,操作系統會為該進程在內存中創建一個task_struct類型的對象,并將該進程放入雙鏈表等其他結構中。這樣,操作系統對進程的管理就變為操作系統對PCB的管理,再變為操作系統對雙鏈表等結構的增刪查改等操作

由此可以總結:進程 = 內核數據結構(PCB等)+ 可執行程序(代碼+數據)

二.進程查看

通過指令查看進程

為了讓進程能夠一直運行方便觀察,寫一個死循環程序,讓其每隔1秒鐘打印一句話。

#include <stdio.h>
#include <unistd.h>int main()
{while(1){printf("It's a process.\n");sleep(1);}return 0;
}

隨后運行它,此時該程序變成了一個進程:
在這里插入圖片描述

接著就可以用ps指令查看進程信息,同時配合grep進行抓取

ps ajx | grep myprocess

得到以下結果:
在這里插入圖片描述

可以看到系統中關于myprocess的進程一共有兩個,第一行是我們寫的運行的程序,第二行是grep命令進行抓取的進程。展示了各種信息:PPID、PID、PGID等等,這些就是PCB的一部分。
注意:task_struct是內核數據結構,查看進程信息讀取該數據,必須要通過系統調用。

通過proc目錄查看

proc是一個目錄,里面存放當前系統實時的 進程信息
ls /proc
在這里插入圖片描述

這里的數字就是進程的PID,由于此時已經將myprocess進程停止,此目錄并沒有找到名為167647的目錄。
但是,仔細看,卻有165058,這是剛才myprocess的父進程ID即PPID,通過指令可以知道,該進程其實就是bash
在這里插入圖片描述

再次運行myprocess,并且通過指令得到其PID,進入該文件夾,可以發現進程的數據顯式存在文件中。

在這里插入圖片描述

進程的cwdexe

查看該目錄詳細信息,有兩個文件很矚目
在這里插入圖片描述

cwd: Current Work Directory 指出該進程當前工作路徑
exe: 指出該進程可執行程序的磁盤文件

修改程序,添加一個fopen函數

#include <stdio.h>
#include <unistd.h>int main() 
{FILE* fp = fopen("1.txt", "w");  // 若不存在就創建while (1) {printf("It's a process.\n");sleep(1);}
}

在這里插入圖片描述

這恰好就是cwd鏈接的目錄,說明fopen使用了查看cwd的系統調用。


再看exe,此時進程運行中,直接刪除其鏈接在磁盤中的文件,發現進程沒有終止,停止進程再運行顯然就會失敗了。
在這里插入圖片描述

運行程序,本質就是將其從磁盤拷貝至內存中,進程與其磁盤上對應程序沒有直接關系。

獲取進程pid和ppid

可以直接通過系統調用getpid()getppid()得到當前進程的pid和ppid(父進程的pid),返回值為pid_t類型,底層就是整數。

運行以下代碼

#include <stdio.h>
#include <unistd.h>int main()
{while (1){printf("It's a process.\t");printf("pid:%d, ppid:%d\n",getpid(), getppid());sleep(1);}return 0;
}

可以看到打印出當前進程的pidppid
在這里插入圖片描述

通過ps axj | head -1; ps axj | grep 184670進行驗證,當前進程是./myprocess且其父進程是bash

在這里插入圖片描述

通過fork()創建子進程

通過man指令查看fork()函數細節
在這里插入圖片描述

fork()函數可以創建子進程,創建成功后父子進程代碼共享。
若成功創建,子進程的pid返回給父進程,0返回給子進程;
若失敗,-1返回給父進程,沒有子進程。

代碼共享可以通過以下代碼得到驗證

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() 
{printf("before\n");fork();printf("Hello, pid:%d\n", getpid());
}

fork()之前的代碼只執行了一次,之后的代碼執行了兩次,這兩次分別是兩個進程執行的。
在這里插入圖片描述


創建父子進程是為了做不同的事情,一般是通過if/else來進行分流達到的,這恰恰用到了fork()有兩個返回值的特點,下面的代碼若是初見一定會迷惑。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() 
{pid_t id = fork();// id: 0-子進程 >0-父進程if (id == 0){while(1){printf("child process, pid: %d, ppid: %d", getpid(), getppid());sleep(1);}}else{while(1){printf("father process, pid: %d, ppid: %d", getpid(), getppid());sleep(1);}}
}

利用父子進程fork()返回值不同,達到兩個死循環都在不斷執行的效果:
在這里插入圖片描述

通過指令查看,確實兩個進程是父子進程關系:

在這里插入圖片描述


下面來簡要分析上面的情況,具體細節會在之后進程地址空間部分詳談。

  1. 為什么兩個死循環會同時執行?

上節講過,進程 = 內核數據結構(PCB等)+ 可執行程序(代碼+數據)。通過fork()創建子進程,肯定也要給子進程創建一個獨立的task_struct,而其代碼和數據指向了父進程接下來的代碼和數據。子進程的大部分屬性值也是由父進程拷貝而來,修改前地址不會改變。
在CPU角度,它不會管誰是父進程,誰是子進程,會在操作系統的管理下并發執行。在我們的視角下,兩個死循環同時執行了。

  1. 為什么fork()返回值如此設計?

父與子的關系是一對一或者一對多的。這樣的關系導致父找子并不容易,所以創建子進程成功后需要把子進程的pid返回給父進程,方便父進程控制子進程。
而子找父是很容易的,通過系統調用getppid()即可。

  1. 為什么fork()會返回兩次值?

fork()之前只有父進程,即只有父進程才能調用fork()fork()內部在return之前肯定已經將子進程創建成功,又子進程和父進程在創建成功后代碼共享,那么子進程和父進程都會執行return這條語句,這也就是為什么fork()會返回兩次值。

  1. 同一個變量id怎么會既大于0,又等于0?

進程之間具有獨立性,一個進程崩潰了,不會影響另一個進程。這里的id是父子進程的共享數據,若父子進程對共享數據有寫操作,這時操作系統會將該數據拷貝兩份,這就是寫時拷貝。那么此時,雖然這是同一個變量名,但實際上表示的是不同的值,那么id出現兩種情況也就不足為奇了,實際在底層的空間根本就不是一個。

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

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

相關文章

OA辦公系統自動滲透測試過程

目錄 一、下載環境源碼 二、部署環境 三、測試 XSS漏洞 SQL注入 文件上傳漏洞 一、下載環境源碼 OA源碼打包地址: https://download.csdn.net/download/weixin_43650289/90434502?spm=1001.2014.3001.5503 二、部署環境

怎么修改node_modules里的文件,怎么使用patch-package修改node_modules的文件,怎么修改第三方庫原文件。

在開發中會遇到需要node_modules里第三方庫有bug&#xff0c;然后需要修改node_modules文件的情況 使用patch-package包可以修改node_modules里的文件 patch-package npm 官網&#xff1a;patch-package - npm 安裝 npm i patch-package 修改文件后 npx patch-package s…

Python在實際工作中的運用-通用格式CSV文件自動轉換XLSX

繼續上篇《Python在實際工作中的運用-CSV無損轉XLSX的幾個方法》我們雖然對特定格式的CSV實現了快速轉換XLSX的目標,但是在運行Py腳本前,還是需要編輯表格創建腳本和數據插入腳本,自動化程度很低,實用性不強,為減少人工提高效率,實現輸入CSV文件路徑即可自動適配完成轉換…

seacmsv9報錯注入

1、seacms的介紹 ? seacms中文名&#xff1a;海洋影視管理系統。是一個采用了php5mysql架構的影視網站框架&#xff0c;因此&#xff0c;如果該框架有漏洞&#xff0c;那使用了該框架的各個網站都會有相同問題。 2、源碼的分析 漏洞的部分源碼如下&#xff1a; <?php …

Hbase客戶端API——語句大全

目錄 創建表&#xff1a; 插入數據&#xff1a; 刪除數據&#xff1a; 修改數據&#xff1a; 查詢數據&#xff1a;Get 查詢數據&#xff1a;Scan 查詢數據&#xff1a;過濾查詢 創建表&#xff1a; 檢驗&#xff1a; 插入數據&#xff1a; 驗證 一次多條數據插入 驗證&…

vscode 版本

vscode官網 Visual Studio Code - Code Editing. Redefined 但是官網只提供最新 在之前的版本就要去github找了 https://github.com/microsoft/vscode/releases 獲取舊版本vscode安裝包的方法_vscode 老版本-CSDN博客

IP------PPP協議

這只是IP的其中一塊內容PPP&#xff0c;IP還有更多內容可以查看IP專欄&#xff0c;前一章內容為網絡類型&#xff0c;可通過以下路徑查看IP---網絡類型-CSDN博客&#xff0c;歡迎指正 3.PPP協議 1.PPP優點 網絡類型&#xff1a;p2p PPP---點到點協議 兼容性會更強凡是接口或…

Springboot基礎篇(3):Bean管理

前言&#xff1a;Spring 通過掃描類路徑&#xff08;Classpath&#xff09;來查找帶有特定注解&#xff08;如 Component、Service、Repository 等&#xff09;的類&#xff0c;并將它們注冊為 Spring 容器中的 Bean。 1 Bean掃描 Bean 掃描是 Spring 框架的核心功能之一&…

Metal 學習筆記二:3D模型

是什么讓一個好游戲更好玩&#xff1f;漂亮的圖像&#xff01;就像《神界&#xff1a;原罪2》&#xff0c;《暗黑破壞神3》以及《巫師3》等大作一樣&#xff0c;需要一個強大的程序團隊以及3D美術團隊強強合作。你在屏幕中看到正是3D模型使用自定義渲染繪制的結果。就像上一章你…

【算法】797. 差分

題目 797. 差分 思路 差分的實質是通過構造數組b減少時間復雜度&#xff0c;數組a為初始數據&#xff0c;構造數組b&#xff0c;數組a是b的前綴和&#xff0c;通過對數組b操作就可以實現數組a每個數加上c&#xff0c;而對數組b的操作在單位時間內即可完成&#xff0c;對數組…

解鎖狀態模式:Java 編程中的行為魔法

系列文章目錄 后續補充~~~ 文章目錄 一、狀態模式&#xff1a;概念與原理二、狀態模式的深度剖析&#xff08;一&#xff09;模式定義與核心思想&#xff08;二&#xff09;模式結構與角色 三、狀態模式的實際應用場景&#xff08;一&#xff09;電商系統中的訂單狀態管理&…

php 獲取head參數

php 獲取head參數 在PHP中&#xff0c;獲取HTTP頭部&#xff08;head&#xff09;參數可以通過不同的方式實現&#xff0c;下面為你詳細介紹幾種常見的方法。 1. 使用$_SERVER超全局變量 $_SERVER 是PHP中的一個超全局變量&#xff0c;它包含了諸如頭信息、路徑、腳本位置等…

數據結構與算法-圖論-最短路-拓展運用

選擇最佳路線 分析&#xff1a; 這是一道圖論中的最短路徑問題&#xff0c;目標是在給定的公交網絡中&#xff0c;找到從琪琪家附近的車站出發&#xff0c;到她朋友家附近車站&#xff08;編號為 s &#xff09;的最短時間。以下是對該問題的詳細分析&#xff1a; 問題關鍵信息…

AI知識架構之神經網絡

神經網絡:這是整個內容的主題,是一種模擬人類大腦神經元結構和功能的計算模型,在人工智能領域廣泛應用。基本概念:介紹神經網絡相關的基礎概念,為后續深入理解神經網絡做鋪墊。定義與起源: 神經網絡是模擬人類大腦神經元結構和功能的計算模型,其起源于對生物神經系統的研…

【江科協-STM32】5. 輸出比較

1. 輸出比較簡介 OC(Output Compare)輸出比較。 輸出比較可以通過CNT&#xff08;CNT計數器&#xff09;與CCR寄存器值的關系&#xff0c;來對輸出電平進行置1、置0或翻轉的操作&#xff0c;用于輸出一定頻率和占空比的PWM波形。 :::tip CNT計數器是正向計數器。它只能正向累…

C++ Primer 再探迭代器

歡迎閱讀我的 【CPrimer】專欄 專欄簡介&#xff1a;本專欄主要面向C初學者&#xff0c;解釋C的一些基本概念和基礎語言特性&#xff0c;涉及C標準庫的用法&#xff0c;面向對象特性&#xff0c;泛型特性高級用法。通過使用標準庫中定義的抽象設施&#xff0c;使你更加適應高級…

排查和解決線程池瓶頸問題案例

在分布式系統中&#xff0c;線程池的使用非常普遍&#xff0c;尤其是在處理異步任務時。然而&#xff0c;線程池的配置不當可能會導致性能瓶頸&#xff0c;進而影響系統的整體性能。本文將分享一個實際案例&#xff0c;介紹如何通過日志分析和線程池優化來解決系統中的性能瓶頸…

影響板材的熱導率有哪些因素?

板材熱導率受多種因素左右&#xff0c;可劃分為內部材料特性與外部環境條件兩大方面 內部材料特性 化學構成&#xff1a;不同化學元素及化合物組合形成的板材&#xff0c;熱導率表現大相徑庭&#xff1b;金屬板材&#xff0c;像銅與鋁&#xff0c;熱導率優異&#xff0c;這是…

給字符串加密解密

加密規則&#xff1a;輸入1a2b3c 輸出 abbccc 解密&#xff1a;輸入abbccc 輸出 1a2b3c 代碼&#xff1a; using System;namespace 加密解密 {class Program{static void Main(string[] args){Encryption("4b2a8p");Decryption("ppppppoovvv");Console.…

人工智能中的特征是什么?

什么是人工智能中的特征&#xff1f; 在人工智能中&#xff0c;特征&#xff08;feature&#xff09;是指從原始數據中提取出的、能夠代表數據關鍵信息并用于模型訓練的屬性或變量。特征通常是對原始數據的抽象或轉換&#xff0c;目的是捕捉數據中的模式、結構或相關性&#x…