Linux系列
文章目錄
- Linux系列
- 前言
- 一、進程終止的概念
- 二、進程終止的場景
- 三、進程終止的實現
- 3.1 程序退出碼
- 3.2 運行完畢結果正常
- 3.3 運行完畢結果異常
- 3.4 程序異常退出
- 總結
前言
進程終止是操作系統中,進程的一個重要階段,他標志著進程生命周期的結束。在Linux下進程終止的方式有很多,接下來我會一一介紹。
一、進程終止的概念
進程終止是操作系統將正在運行的程序結束掉的過程。當進程終止時,操作系統會回收該進程所占用的系統資源,如內存空間、文件描述符、CPU資源等,確保系統資源高效的利用。
二、進程終止的場景
這里我們僅介紹常見的進程終止場景
場景 | 原因 |
---|---|
任務完成 | 進程順利執行完所有預設的任務,達到結束點,自動請求操作系統終止 |
運行錯誤 | 進程執行過程中遇到除零錯誤、越界訪問等 |
資源不足 | 進程向操作系統申請的內存資源無法得到滿足 |
用戶手動終止 | 用戶通過命令行(kill命令)強制終止進程 |
總的來說會有下面三種退出場景:
1.代碼運行完畢,結果正確
2.代碼運行完畢,結果不正確
3.代碼異常終止
三、進程終止的實現
我們結合相關代碼,對上面的場景逐幀分析
3.1 程序退出碼
在我們平時寫的代碼中,main
函數內都會有依據return 0
這表示著程序結束時返回0
(不同的退出碼代表不同的涵義),這個零就是我們所寫程序的退出碼,但是當我們所寫的程序運行出錯時,它往往會給我們返回一個非零值,這時什么意思呢?首先我們要知道程序退出碼是干什么的:
程序退出碼是程序終止時返回給操作系統的一個整數值,用于指示程序的執行結果。它的核心是為調用者提供清晰的狀態反饋,以便后續處理。
更詳細的內容我會在下文穿插介紹
3.2 運行完畢結果正常
return 終止進程
這是我們接觸最多的一種方式:
1 #include<stdio.h>2 int main()3 {4 printf("I am process...\n"); 5 return 0; 6 }
當我們執行這個程序后,我們只能看到程序運行的結果,程序退出碼呢?其實程序退出碼,返回是為了給他的父進程(這里的父進程就是bash
命令行)查看的,父進程創建出子進程來執行程序時,它需要知道子進程執行的結果(如成功、錯誤等)程序退出碼的作用就是反饋執行狀態,通常退出碼為零表示成功執行,而非零值,表示不同類型的錯誤。我們可以通過這個命令查看程序退出碼:
echo $?
$?:保存的是最近一次進程退出時的退出碼
exit終止進程
想了解更多可以通過man手冊查看
exit(n)
直接終止進程并返回一個指定的退出碼,適用于需要立刻終止進程的場景:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 void test() 5 { 6 printf("I am process...\n"); 7 //int *ptr=(int*)malloc(1000*1000*4); 8 exit(11);9 printf("I am process...\n"); 10 } 11 int main() 12 { 13 test(); 14 return 0; 15 }
可以看到當程序執行過,exit(11)
后程序直接退出,并返回指定退出碼,不再繼續向下執行。
exit
和return
的區別
在主函數中兩者是等價的,但是在多層函數調用中,return
只表示當前所處函數調用完成,而exit
則會直接終止進程并返回程序退出碼,當我們的程序在被調用的函數中出錯時,我們就可以使用exit
直接終止程序而不是使用return
返回主函數再終止,在后面我會給出示例。
_exit終止進程
這個系統調用接口和exit
用法一樣,但是不同的是:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 void test()5 {6 printf("I am process..."); 7 //int *ptr=(int*)malloc(1000*1000*4);8 _exit(11);9 printf("I am process...\n");10 }11 int main()12 {13 test();14 return 0;15 }
_exit
在終止進程時,不會刷新緩沖區,而exit
會幫助進程刷新緩沖區的資源
注:在測試這一點時打印函數不可以加\n
,\n
會幫助我們刷新緩沖區資源。
3.3 運行完畢結果異常
strerror 函數
在介紹程序退出碼時我們說,不同的退出碼對應著不同錯誤信息,那么我們該如何知道退出碼對應的錯誤信息呢?在庫函數中存在strerror
函數可以幫助我們:
下面代碼打印出0~5
程序退出碼,所對應的信息。
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 #include<string.h>5 int main()6 {7 int i=0;8 for(;i<=5;i++)9 {10 printf("%d->%s\n",i,strerror(i)); 11 }12 return 0;13 }
errno 全局變量
在C/C++中給我們提供了一個全局,當程序執行錯誤時,系統會將變量值修改為對應的錯誤碼,并返回(程序退出碼),我們可以配合strerror
函數之間打印出對應的錯誤信息:
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 #include<string.h>5 #include<errno.h>6 int main()7 {8 int *ptr=(int*)malloc(1000*1000*1000*4);9 if(ptr==NULL)10 {11 printf("malloc error,%d->%s\n",errno,strerror(errno)); 12 }13 return 0;14 }
perror 函數
它就像一個簡化版的strerror
信息,可以直接輸出錯誤描述,格式為:
用戶自定義消息:錯誤描述
1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 #include<string.h>5 #include<errno.h>6 int main()7 {8 int *ptr=(int*)malloc(1000*1000*1000*4);9 if(ptr==NULL)10 {11 perror("malloc error:"); 12 } 13 return 0; 14 }
3.4 程序異常退出
這里的原因還是比較多的,今天我們先介紹kill
,我們可以使用kill
系統調用或命令強制終止進程:
kill命令
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 #include<string.h> 5 #include<errno.h> 6 int main() 7 { 8 printf("I am prcsess......\n"); 9 sleep(100); 10 return 0; 11 }
這個好像不太好演示......
kill系統調用
第二個參數對應的信號可以通過kill -l查看
1 #include<stdio.h>2 #include<stdlib.h> 3 #include<signal.h>4 #include<unistd.h>5 int main()6 {7 pid_t id=fork();8 if(id==0)9 {10 while(1)11 {12 13 printf("I am child,pid:%d,ppid%d\n",getpid(),getppid());14 sleep(1);15 }16 }17 else if(id>0)18 {19 sleep(5);20 kill(id,SIGKILL);21 }22 else exit(1);23 return 0;24 }
總結
進程終止是我們在學習Linux系統部分比較重要的一節,本篇我們主要介紹了進程退出碼的作用以及如何來獲取使用它,這對我們高效的編程有很大的幫助。