34.Linux應用層開發--進程

引入:

今天開始學習linux應用層開發的必備知識,進程。我們之前的實時系統中,都是任務的概念,linux中也有任務概念,同時還有進程和線程,他們之間是什麼關係呢?

 

其實在我們的windows中也有進程的概念,通過任務管理器就能查看到當前運行的進程。

開始學習之前先看下思維導圖,把握這節的知識點,然後在進行詳細的解讀。

 

我們將上面的內容進行詳細學習。

一.進程的基本知識

1.進程的概念

1>當我們打開windows時,說讓你殺死一個進程,那什麼是進程?

理解上,進行中的程序就是進程唄,程序的一次執行過程,是動態的(佔用CPU和內存),包括創建,調度,執行和消亡。

2>那麼和程序有啥區別?

很明顯,程序是靜態的,是存放在磁盤上的指令和數據的有序集合。

3>一個進程又包含哪些內容呢?

從我們的框圖中也能清晰的看到,它包括進程控制塊,也就是我們知道的PCB控制塊,還要有cpu寄存器,堆棧,還有和程序中共有的部分,正文段,用戶數據段,系統數據段。直接看框圖更好理解

2.進程的特性:

1>併發性:多進程併發執行

2>動態性:進程狀態不斷變化

3>交互性:進程間交互,同步互斥等

4>獨立性:地址空間相互獨立

3.進程的類型

主要就是三大類型

1>交互式進程:典型的就是shell命令進程,可前臺運行,也可以後臺運行

2>批處理進程:與終端無關,作業隊列中順序執行,不需要很快響應,編譯器的編譯操作,數據庫搜索等都屬於批處理進程

3>守護進程:後臺運行,系統進程都是以這種形式存在。

4.進程的狀態:

運行態,等待態,停止態,死亡態。

 

二.進程的常見命令

我們對進程有了一點了解,那麼我們還是要在終端上對進程進行一些操作,如查看一下狀態啊等。

1.進程的查看,常用的幾個命令

ps aux   查看所有進程信息,包括誰創建的,pid,cpu佔用率,狀態等

ps -elf

ps -elf|grep test 詳細的查看某一個進程的信息

top  查看進程動態信息。

top |grep init  詳細的查看某一個進程的動態信息

2.改變進程優先級

1> nice 按照用戶指定的優先級運行(優先級範圍-20--19)

例:

./test 然後通過ps -elf|grep test 查看test進程的信息,pid等。

nice -n 19 ./test 修改完後通過ps -elf|grep test 查看pid進程號,

然後top -p 10113(進程號),查看進程動態詳細信息,發現進程優先級已經改成功

2>renice 運行態,改變正在運行的進程優先級

例:renice 10 10113 優先級就改變了。

3.進程的前後臺操作

jobs查看後臺幾個進程

bg  將掛起的進程運行

fg 1 將後臺進程放到前臺運行

ctrl+z 前臺變爲後臺,並停止。

三.進程的創建和結束及回收

1.進程創建

pid_t  fork(void); 一個fork會有兩個返回值,通過不同的返回值得到父子進程,是個岔子函數。

失敗:-1 父進程:返回子進程進程號  子進程:返回0

int main(){
	pid_t pid;
	int i;
	pid = fork();
	if(pid <0){
	    perror("fork");
	    return 0;
	}else if(pid==0){
		printf("son\n");
	}else{
		printf("father\n");
	
	}
	while(1) sleep(1);
}	

2.進程的結束

void  exit(int  status); 結束時會刷新緩衝區。

void  _exit(int  status); 結束當前進程並將status返回

3.父子進程關係

1> 子進程繼承父進程內容

2> 父子進程有獨立空間,互不影響

3> 若父進程先結束,子進程成爲孤兒進程,被init進程收養,子進程變爲後臺進程

4> 若子進程先結束,父進程沒有及時回收,子進程變爲殭屍進程。

5> 子進程是從fork後開始運行,不是從main開始

6> 父子進程誰先運行依賴於操作系統調度策略

7>父子進程可以多次創建

4.進程的回收

子進程結束時由父進程回收,若不及時回收就會出現殭屍進程。

孤兒進程由init 進程回收。

1> pid_t wait(int *status)

成功:子進程進程號 失敗:EOF

子進程沒有結束,父進程一直阻塞

status爲NULL表示直接釋放進程PCB,不接收返回值(不接收遺言)

2> pid_t waitpid(pid_t pid,int *status,int option)

指定回收哪一個子進程。option 指定回收方式

3>通過以下幾個宏定義,可以判斷子進程是什麼原因死的

WIFEXITE(status)判斷子進程是否正常結束

WEXITSTATUS(status)獲取子進程返回值

WIFSIGNALED(status)判斷子進程是否被信號結束

WTERMSIG(status)獲取結束子進程的信號類型

int main(){
	pid_t pid;
	int i;
	int status;

	pid = fork();
	if(pid <0){
		perror("fork");
		return 0;
	}else if(pid==0){
		printf("bbbbbb\n");
		sleep(2);
		exit(2);
	}else{
		printf("aaaaaa\n");
		//wait(&status); //回收進程
		sleep(4);
	    waitpid(pid,&status,WNOHANG); //回收指定進程
    	printf("st=%d\n", WEXITSTATUS(status));

	}
	
	while(1) sleep(1);
	return 0;
	
}

四.exec函數族

爲了實現父子進程執行不同的程序,exec函數族就是爲了執行第三方程序。

以下幾個函數都是爲了執行第三方程序,只是操作方式不一樣。

int execl(const char *path, const char *arg, …);

  if(execl("/bin/ls", "ls", "-a", "-l", "./", NULL) < 0) {
     perror("execl");
  } 

int execlp(const char *file, const char *arg, …);

  if(execlp("ls", "ls", "-a", "-l", "./", NULL) < 0) {
     perror("execl");
  }  //從path路徑下查找文件

int execv(const char *path, char *const argv[]);

  char  *arg[] = {"ls", "-a", "-l", "./", NULL};
  printf("aaaaaaaaaaah\n");
  if  (execv("/bin/ls", arg) < 0) {
     perror("execv");
  } 

int execvp(const char *file, char *const argv[]);

  char  *arg[] = {"ls", "-a", "-l", "./", NULL};
  printf("aaaaaaaaaaah\n");
  if  (execvp("ls", arg) < 0) {
     perror("execv");
  } 

上面幾個函數執行了第三方函數,但是自己的函數也不能丟啊,就有了system函數

int system(const char *command);

system("ls -l -a ./");  

相當於把exec函數進行了封裝,fork了一個進程,子進程exec執行操作,父進程阻塞等待子進程結束後,繼續執行

不替換程序內容。

五.守護進程

作爲三大進程之一,重要性自然不必多說,那麼什麼是守護進程,又如何創建呢??

1.守護進程特點

始終後臺運行,獨立於任何終端,週期性的執行某種任務或等待處理特定事件。

一般的進程關閉會話後,所有進程就會結束。

2.守護進程的創建過程

1>先與終端脫離關係,讓子進程變爲孤兒進程。

2>子進程創建一個新的會話,併成爲新的會話組長。

3>守護進程一直在後天運行,其工作目錄不能被卸載,重新設定當前目錄(假如是臨時目錄,容易出現問題,所以更改目錄,路徑不限定)

4>改變文件掩碼,防止設置權限時受影響

5>關閉所有從父進程繼承的打開文件

最後查看編寫的程序是否爲後臺程序,關閉終端後是否會影響進程。

只能用kill殺死進程。

創建一個守護進程,將系統時間保存到log文件中

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){
	pid_t pid;
	
	pid = fork();
	if(pid<0){
		perror("fork");
		return -1;
	}else if(pid>0){
		exit(0);
	}
	
	pid = setsid();
	if(pid==-1){
		perror("setsid");
		return -1;
	}
	
	chdir("/");
	
	umask(0);
	int i;
	for(i = 0;i<2;i++){
		close(i);
	}
	
	FILE *fp;
	time_t ctm;
	fp = fopen("1.log","w");
	while(1){
		ctm = time(NULL);
		fputs(ctime(&ctm),fp);
		fflush(fp);
		sleep(1);
	}
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章