進程概述
進程的定義
程序:
程序是存放在存儲介質上的一個可執行文件
進程:
進程是程序的執行實例, 包括程序計數器、 寄存器和變量的當前值
程序是靜態的, 進程是動態的
程序是一些指令的有序集合, 而進程是程序執行的過程
進程的狀態是變化的, 其包括進程的創建、 調度和消亡
在 linux 系統中, 進程是管理事務的基本單元
進程擁有自己獨立的處理環境和系統資源(處理器、 存儲器、I/O 設備、 數據、 程序)
可用 exec 函數由內核將程序讀入內存, 使其執行起來成爲一個進程
進程的狀態及轉換
進程整個生命週期 可簡單劃分爲三種狀態:
就緒態:
進程已具備執行的一切條件, 正在等待分配 CPU 的處理時間
執行態:
該進程正在佔用 CPU 運行
等待態:
進程因不具備某些執行條件,而暫時無法繼續執行的狀態
進程三種狀態的轉換關係:
進程控制塊
OS 是根據 PCB ,對併發執行的進程進行 控制和管理
系統在創建一個進程的時,會開闢一段內存空間存放與此進程相關 的 PCB 數據結構
PCB 是操作系統中最重要的記錄型數據結構
PCB 中記錄用於 描述進程進展情況及 控制進程運行所需的全部信息
PCB 是進程存在的唯一標誌, 在 Linux 中 PCB 存放在 task_struct 結構體中
調度數據:
進程的狀態、 標誌、 優先級、 調度策略等
時間數據:
創建該進程的時間、 在用戶態的運行時間、 在內核態的運行時間等
文件系統數據:
umask 掩碼、 文件描述符表等
內存數據、 進程上下文、 進程標識(進程號)
進程控制
進程號
每個進程都由一個進程號來標識, 其類型爲 pid_t, 進程號的範圍: 0~32767( 2^15 )
進程號總是唯一的, 但進程號可以重用
當一個進程終止後, 其進程號就可以再次使用了
在 linux 系統中進程號由 0 開始
進程號爲 0 及 1 的進程由內核創建
進程號爲 0 的進程通常是調度進程, 常被稱爲交換進程(swapper)
進程號爲 1 的進程通常是 init 進程
除調度進程外, 在 linux 下面所有的進程都由 進程 init 進程直接或者間接創建
進程號(PID):
標識進程的一個非負整型數
父進程號(PPID):
任何進程(除 init 進程)都是由另一個進程創建, 該進程稱爲 被創建進程的父進程, 對應的進程號稱爲父進
程號(PPID)
進程組號(PGID):
進程組是一個或多個進程的集合
他們之間相互關聯, 進程組可以接收同一終端的各種信號,關聯的進程有一個進程組號(PGID)
Linux 操作系統提供了三個獲得進程號的函數 getpid()、 getppid()、 getpgid()
例子:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
pid_t pid;
pid_t ppid;
pid_t pgid;
// 獲取本進程號
pid = getpid();
// 獲取調用此函數的進程的父進程號
ppid = getppid();
// 獲取進程組號,參數爲 0 時返回當前 PGID, 否則返回參數指定的進程的 PGID
pgid = getpgid(pid);
printf("pid = %d\n",pid);
printf("ppid = %d\n",ppid);
printf("pgid = %d\n",pgid);
return 0;
}
進程的創建 fork 函數
#include <sys/types.h>
#include <unistd.h>
/*
* 從一個已存在的進程中創建一個新進程, 新進程稱爲子進程, 原進程稱爲父進程
*return:
* 成功:子進程返回0 父進程返回子進程ID
* 錯誤:-1
*/
pid_t fork(void);
pid_t vfork(void);
地址空間:
進程上下文、 進程堆棧、 打開的文件描述符、 信號控制設定、 進程優先級、 進程組號
子進程所獨有的只有它的進程號, 計時器
創建一個子進程實現多任務:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
pit_t pid;
pid = frok();
if(pid < 0)
{
perror("fork");
}
if(0 == pid)
{
while(1)
{
printf("this is son process\n");
sleep(1);
}
}
else
{
while(1)
{
printf("this is father process\n");
sleep(1);
}
}
return 0;
}
驗證父子進程分別有各自獨立的地址空間
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int var = 10;
int main(int argc, char *argv[])
{
pid_t pid;
int num = 9;
pid = fork();
if(pid < 0)
{
perror("fork");
}
if(0 == pid)
{
var++;
num++;
printf("in son process var = %d, num = %d\n",var, num);
}
else
{
sleep(1);
printf("in father process var= %d, num = %d\n",var, num);
}
printf("common code area\n");
return 0;
}
進程的掛起
進程的等待
進程的終止
進程退出
清理進程的創建 vfork 函數
進程的替換
system 函數
練習