linux應(yīng)用軟件編程之多任務(wù)(進(jìn)程)詳解
一、多任務(wù)概述
1.定義:
讓系統(tǒng)具備同時(shí)處理多個(gè)任務(wù)的能力
2.實(shí)現(xiàn)過(guò)程
- 多進(jìn)程
- 多線程
- 進(jìn)程間通信
二、進(jìn)程概述
1.定義
一個(gè)正在運(yùn)行的程序稱為一個(gè)進(jìn)程,其運(yùn)行過(guò)程中需要消耗內(nèi)存和CPU。

2.程序和進(jìn)程的區(qū)別
程序 進(jìn)程
靜態(tài)的數(shù)據(jù)集合,存儲(chǔ)在硬盤空間 是一個(gè)程序動(dòng)態(tài)執(zhí)行的過(guò)程,需要消耗內(nèi)存和CPU
程序運(yùn)行起來(lái)可以產(chǎn)生進(jìn)程 進(jìn)程具備動(dòng)態(tài)生命周期,從產(chǎn)生到調(diào)度再到消亡
一個(gè)程序可以產(chǎn)生多個(gè)進(jìn)程 一個(gè)進(jìn)程中也可執(zhí)行多個(gè)程序
3.進(jìn)程的產(chǎn)生
進(jìn)程產(chǎn)生時(shí),操作系統(tǒng)都會(huì)為其分配0-4G的虛擬內(nèi)存空間。操作系統(tǒng)內(nèi)存區(qū)如下圖所示:

(1)內(nèi)核: 1 文件管理;2. 進(jìn)程管;3. 內(nèi)存管理。
(2)棧區(qū):1.保存局部變量;2.函數(shù)的形參和返回值;3.保存函數(shù)的調(diào)用關(guān)系(保護(hù)現(xiàn)場(chǎng)和恢復(fù)現(xiàn)場(chǎng))。
(3)堆區(qū):1. 由開發(fā)人員手動(dòng)分配;2. 使用完要手動(dòng)釋放。
(4)數(shù)據(jù)區(qū):
- data段:1. 已初始化的全局變量 ;2. 已初始化的靜態(tài)變量。
- bss段:1.未初始化的全局變量 ; 2. 未初始化的靜態(tài)變量(static)-->bss段初始時(shí)按位清0。
- 字符串常量區(qū):保存字符串常量 "hello world"
(5)文本區(qū):1. 存放指令代碼 ;2. 存放常量。
4.進(jìn)程的調(diào)度
- CPU:
由于CPU數(shù)據(jù)處理速度快,因此是“宏觀并行,微觀串行”。
- cpu調(diào)度算法
1、時(shí)間片輪詢算法
2、先來(lái)先服務(wù),后來(lái)后服務(wù)(任務(wù)隊(duì)列)
3、短作業(yè)優(yōu)先調(diào)度
4、高優(yōu)先級(jí)先執(zhí)行,低優(yōu)先級(jí)后執(zhí)行
5.進(jìn)程的狀態(tài)
- 操作系統(tǒng)的三態(tài)圖:

- Linux操作系統(tǒng)的進(jìn)程狀態(tài):

- 各進(jìn)程狀態(tài):
1.運(yùn)行態(tài)(用戶運(yùn)行態(tài)、內(nèi)核運(yùn)行態(tài)) R
正在執(zhí)行,且被CPU任務(wù)調(diào)度所執(zhí)行的進(jìn)程
2.就緒態(tài) R
正在執(zhí)行,沒(méi)有CPU任務(wù)調(diào)度執(zhí)行的進(jìn)程(只缺少cpu)
3.可喚醒等待態(tài) S
也稱為睡眠態(tài),阻塞等待資源的進(jìn)程
4.不可喚醒等待態(tài) D
不想被CPU任務(wù)調(diào)度所打斷的進(jìn)程任務(wù)可以設(shè)置為不可喚醒等待態(tài)
5.暫停態(tài) T
被暫停執(zhí)行的進(jìn)程
6.僵尸態(tài) Z
進(jìn)程執(zhí)行結(jié)束,空間沒(méi)有被回收
7.結(jié)束態(tài) X
進(jìn)程執(zhí)行結(jié)束,空間被回收
6.進(jìn)程的消亡
- 進(jìn)程執(zhí)行結(jié)束(進(jìn)程退出)
- 回收進(jìn)程資源空間
三、進(jìn)程相關(guān)的命令
- 父進(jìn)程:產(chǎn)生子進(jìn)程的進(jìn)程稱為父進(jìn)程
- 子進(jìn)程:父進(jìn)程產(chǎn)生出來(lái)的新進(jìn)程即為該父進(jìn)程的子進(jìn)程
1. ps -aux
查看進(jìn)程相關(guān)參數(shù):PID、狀態(tài)、CPU占有率、內(nèi)存占有率

- USER:創(chuàng)建者
- PID:進(jìn)程的ID號(hào)
- %CPU:CPU占有率
- %MEM:內(nèi)存占有率
- TTY:當(dāng)前進(jìn)程所關(guān)聯(lián)的終端
- STAT:當(dāng)前進(jìn)程的狀態(tài)值(帶“+”號(hào)表示前臺(tái)進(jìn)程,不帶“+”號(hào)表示后臺(tái)進(jìn)程)
- START TIME:進(jìn)程創(chuàng)建的時(shí)間
- COMMAND:進(jìn)程的名稱(init進(jìn)程是操作系統(tǒng)啟動(dòng)的第一個(gè)進(jìn)程)
ps -aux | grep ./a.out
- |:管道 :前面命令的輸出作為后面命令的輸入
- grep:字符串查找:在輸入中查找和后面字符串相關(guān)的數(shù)據(jù)

2. top
動(dòng)態(tài)查看進(jìn)程的相關(guān)參數(shù):CPU占有率、內(nèi)存占有率
——按照CPU、內(nèi)存占有率的高低進(jìn)行排列的

- PR、NI:表示進(jìn)程的優(yōu)先級(jí),值越小,優(yōu)先級(jí)越高
- TIME+:進(jìn)程運(yùn)行的時(shí)間
3. ps -ef查看該進(jìn)程的ID和父進(jìn)程ID

4. pstree查看進(jìn)程的產(chǎn)生關(guān)系
pstree -p
查看進(jìn)程的產(chǎn)生關(guān)系(有PID號(hào))

pstree -sp 進(jìn)程PID號(hào)
查看某個(gè)指定的進(jìn)程的產(chǎn)生關(guān)系

5.kill
kill -信號(hào)的編號(hào)/信號(hào)的名稱 PID
向進(jìn)程發(fā)送信號(hào),讓進(jìn)程的狀態(tài)發(fā)生變化


由第一張圖片中可以看出20429進(jìn)程一開始是在R+運(yùn)行狀態(tài),執(zhí)行kill相關(guān)命令,其進(jìn)程被殺死。
結(jié)束一個(gè)進(jìn)程的三種表示形式:
kill -9 PID kill -SIGKILL PID killall -9 進(jìn)程名稱
kill -l
查看系統(tǒng)支持的信號(hào)

- 9——SIGKILL——殺死信號(hào)
- 19——SIGSTOP——暫停態(tài)信號(hào)
- 18——SIGCONT——喚醒信號(hào)
+前臺(tái)進(jìn)程后臺(tái)進(jìn)程
6. jobs查看當(dāng)前終端的后臺(tái)進(jìn)程

7.fg
[ fg 后臺(tái)進(jìn)程編號(hào)]
讓后臺(tái)進(jìn)程切換成前臺(tái)進(jìn)程


四、進(jìn)程相關(guān)的編程
1.實(shí)現(xiàn)進(jìn)程的步驟
進(jìn)程創(chuàng)建 : fork()
- getpid():獲取當(dāng)前進(jìn)程自己的PID號(hào)
- getppid():獲取當(dāng)前進(jìn)程父進(jìn)程的PID號(hào)
進(jìn)程調(diào)度:操作系統(tǒng)完成
進(jìn)程消亡:
- 1.進(jìn)程退出:return、exit()相關(guān)函數(shù)
- 2.回收資源空間:wait()、waitpid()
2.進(jìn)程創(chuàng)建函數(shù)
pid_t fork(void);
功能:通過(guò)拷貝父進(jìn)程產(chǎn)生一個(gè)新的子進(jìn)程
- 子進(jìn)程完全拷貝父進(jìn)程0-3G的虛擬內(nèi)存空間
- 子進(jìn)程拷貝父進(jìn)程PCB(進(jìn)程控制塊)塊中的部分內(nèi)容:PID不拷貝
返回值:
- >0:父進(jìn)程 ,是子進(jìn)程的PID號(hào)
- ==0:子進(jìn)程
- -1 :出錯(cuò)

3.示例程序
使用fork函數(shù)創(chuàng)建新進(jìn)程,
- 父進(jìn)程打印自己的PID和自己子進(jìn)程的pid
- 子進(jìn)程中打印自己的PID和父進(jìn)程的PID
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc , const char *argv[])
{
pid_t pid = fork();
if(pid > 0)
{
while(1)
{
printf("I am father pid = %d sonpid = %d \n",getpid(),pid);
sleep(1);
}
}
else if(0 == pid)
{
while(1)
{
printf("I am son pid = %d ppid = %d \n",getpid(),getppid());
sleep(1);
}
}
else
{
perror("fork error");
}
return 0;
}注意:
1. 子進(jìn)程完完整整拷貝父進(jìn)程0-3G虛擬內(nèi)存空間。
2. 父子進(jìn)程棧區(qū)、數(shù)據(jù)區(qū)、文本區(qū)、堆區(qū)完全獨(dú)立,數(shù)據(jù)不共享
3. 要想共享數(shù)據(jù),需要使用進(jìn)程間通信方式實(shí)現(xiàn)

例如以下程序:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc , const char *argv[])
{
pid_t pid = fork();
int num = 0;
if(pid > 0)
{
num = 100;
while(1)
{
printf("I am father pid = %d sonpid = %d num = %d\n",getpid(),pid,num);
sleep(1);
}
}
else if(0 == pid)
{
num = 1000;
while(1)
{
printf("I am son pid = %d ppid = %d num = %d\n",getpid(),getppid(),num);
sleep(1);
}
}
else
{
perror("fork error");
}
return 0;
}運(yùn)行結(jié)果如下:

3.進(jìn)程退出函數(shù)
(1)main中return
#include <stdio.h>
#include <stdlib.h>
int fun()
{
return 0;
}
int main(int argc, const char *argv[])
{
int i = 15;
while (i--)
{
printf("PID = %d\n", getpid());
sleep(1);
}
return 0;
}(2) exit ()、_exit() :結(jié)束一個(gè)進(jìn)程
- exit (0) : 正常退出
- exit (非0) :由于進(jìn)程產(chǎn)生了某種問(wèn)題,需要主動(dòng)退出進(jìn)程
#include <stdio.h>
#include <stdlib.h>
int fun()
{
exit(0);
return 0;
}
int main(int argc, const char *argv[])
{
fun();
printf("hello world\n");
return 0;
}4.回收資源空間:
wait()、waitpid()
僵尸進(jìn)程:進(jìn)程退出后,但其資源空間未被父進(jìn)程回收
如何避免僵尸進(jìn)程產(chǎn)生:
1. 子進(jìn)程退出后,父進(jìn)程及時(shí)為其回收資源空間
2. 讓該進(jìn)程成為一個(gè)孤兒進(jìn)程,結(jié)束時(shí)被操作系統(tǒng)中的系統(tǒng)進(jìn)程回收
孤兒進(jìn)程:父進(jìn)程先消亡,其對(duì)應(yīng)的子進(jìn)程成為一個(gè)孤兒進(jìn)程,會(huì)被系統(tǒng)進(jìn)程所收養(yǎng)
(守護(hù)類的進(jìn)程)
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if (pid > 0)
{
while (1)
{
printf("I am father : pid = %d, sonpid = %d\n", getpid(), pid);
sleep(1);
}
}
else if (0 == pid)
{
int i = 15;
while (i--)
{
printf("I am son : pid = %d, ppid = %d\n", getpid(), getppid());
sleep(1);
}
}
else
{
perror("fork error");
}
return 0;
}
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, const char *argv[])
{
pid_t pid = fork();
if (pid > 0)
{
int i = 10;
while (i--)
{
printf("I am father : pid = %d, sonpid = %d\n", getpid(), pid);
sleep(1);
}
}
else if (0 == pid)
{
int i = 20;
while (i--)
{
printf("I am son : pid = %d, ppid = %d\n", getpid(), getppid());
sleep(1);
}
}
else
{
perror("fork error");
}
return 0;
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Linux下SFTP用戶權(quán)限設(shè)置條件及實(shí)現(xiàn)命令
SFTP賬號(hào)是基于SSH賬號(hào)的,其擁有的權(quán)限是比較大的,今天主要教大家如何進(jìn)行SFTP用戶權(quán)限設(shè)置,感興趣的你可不要錯(cuò)過(guò)了哈,希望本文知識(shí)可以幫助到你2013-02-02
Linux安裝yum時(shí)出現(xiàn)apt-get?install?E:?無(wú)法定位軟件包問(wèn)題解決
這篇文章主要介紹了Linux安裝yum時(shí)出現(xiàn)apt-get?install?E:?無(wú)法定位軟件包問(wèn)題解決的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-12-12
Linux系統(tǒng)實(shí)現(xiàn)關(guān)機(jī)的常用命令
在Linux系統(tǒng)中,關(guān)機(jī)可以通過(guò)多種命令實(shí)現(xiàn),具體取決于你的需求(如立即關(guān)機(jī)、定時(shí)關(guān)機(jī)、安全關(guān)機(jī)等)以及使用的系統(tǒng)管理工具(如systemd或SysVinit),以下是常用的關(guān)機(jī)方法,需要的朋友可以參考下2026-02-02
CentOS設(shè)置上網(wǎng)代理全過(guò)程
該文章詳細(xì)介紹了在CentOS 7.0系統(tǒng)上設(shè)置代理服務(wù)器的過(guò)程,包括設(shè)置全局代理、yum代理、wget代理以及配置Docker HTTP代理的步驟2025-12-12
Win8.1 + CentOS7 雙系統(tǒng) U盤安裝(超詳細(xì)教程)
這篇文章主要介紹了Win8.1 + CentOS7 雙系統(tǒng) U盤安裝(超詳細(xì)教程),非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2017-01-01
ubuntu24.04設(shè)置靜態(tài)IP地址的方法教學(xué)
這篇文章主要為大家詳細(xì)介紹了使用ubuntu24.04設(shè)置靜態(tài)IP地址的相關(guān)方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-05-05
一文詳解Linux下如何在vim里使用異步編譯和運(yùn)行
這篇文章主要介紹了如何在Linux的vim編輯器中使用異步編譯和運(yùn)行C++程序,具體功能包括在vim中直接構(gòu)建和運(yùn)行單個(gè)文件或整個(gè)項(xiàng)目,使用快捷鍵如F9、F10、F7、F8和F6進(jìn)行操作,此外,提到了使用兩個(gè)vim插件來(lái)實(shí)現(xiàn)這些功能,并提供了必要的配置文件和命令信息2025-10-10

