廣義上,所有的進程信息被放在一個叫做進程控制塊的數據結構中,可以理解爲進程屬性的集合。
進程控制塊
每個進程在內核中都有一個進程控制塊(PCB)來維護進程相關的信息,Linux內核的進程控制塊是tack_struct.結構體。下面我們將全面瞭解一下其中都有那些信息。
在Linux中,這個結構叫做task_struct.
task_struct是Linux內核的一種數據結構,他會被裝載到PAM力氣並且包含着進程信息。每個進程都把它的信息放在task_struct這個數據結構裏,task_struct包含了這些內容:
標識符:描述本進程的唯一標識符,來區別其他進程。
狀態:任務狀態、退出代碼,退出信號等。
優先級:相對於其他進程的優先級。
程序計數器:程序中即將被執行的下一條指令的地址。
內存指針:包括程序代碼和進程相關數據的指針,還有其他進程共享的內存塊的指針。
上下文數據:進程指行時處理器的寄存器中的數據。
I/O狀態信息:包括顯示的I/O請求,分配給進程的I/O設備和被進程使用的文件列表。
記賬信息:可包括處理時間總和,使用的時鐘數總和,時間限制,記賬號等。
保存進程的數據結構叫做task_struct,並且在include/linux/sched.h裏找到它。所有運行在系統裏的進程都以task_struct鏈表的形式在內核裏。
進程的信息可以通過/proc文件夾查看。要獲取PID爲400的進程信息,你需要查看/proc/400這個文件夾。大多數進程信息同樣可以使用top和ps這些用戶級工具來獲取。
進程標識符
進程id(pid)
父進程iD(ppid)
進程位置:
1.進程內存映像
Linux下C程序生成主要由四個步驟組成:預編譯、編譯、彙編、鏈接。編譯器gcc經過預編譯、編譯、彙編3個步驟將源程序轉換成目標文件。如果程序有多個目標文件或程序中使用了庫函數,則編譯器還需要將所有目標文件及所需的庫文件鏈接起來,最後生成可執行程序。當程序執行時,操作系統將可執行程序複製到內存中,程序轉爲進程通常需要以下步驟:
(1)內核將進程讀入內存,爲內存分配內存空間;
(2)內核爲該進程保存PID及相關的狀態信息,把進程放到運行隊列中等待執行。程序轉化爲進程後就可被操作系統得到調度程序執行了。
進程的內存映像是指內核在內存中如何存放可執行程序文件。再將程序轉化爲進程的過程中,操作系統可將執行程序從硬盤複製到內存中,其佈局如下:
C地址空間測試代碼:
#include<stdio.h>
#include<stdlib.h>
int g_val=100;
void test()
{
int a=10;
int b=10;
printf("test stack1 address:0x%x\n",&a);
printf("test stack2 address:0x%x\n",&b);
}
void(*fp)();
int main()
{
int a=10;
int *heap=malloc(sizeof(int));
fp=test;
printf("code address:0x%x\n",fp);
printf("data address:0x%x\n",&g_val);
printf("heap address:0x%x\n",heap);
printf("main stack0 address:0x%x\n",&a);
fp();
return 0;
}
運行結果如下:
2.進程映像的位置依賴使用的內存管理方案。
3.可執行程序與進程內存映像的不同之處在於:
a.可執行程序位於磁盤中而內存映像位於內存;
b.可執行程序沒有堆棧,因爲程序被加載到內存中才會分配堆棧;
c.可執行程序雖然也有未出始化數據段但它並不被存儲在位於硬盤中的可執行文件中;
d.可執行程序是靜態的、不變的,而內存在映像隨着程序的執行是在動態變化的,比如數據段隨着程序的執行要存儲新的數據值,棧在函數調用時也是在不斷變化。