進程全家桶,看這一篇就夠了 | 原力計劃
CSDN · 程式 ·

進程全家桶,看這一篇就夠了 | 原力計劃

進程處於可執行狀態,休眠,掛起等。2性質,由於unix有很多變種,進程

作者 | 看,未來

責編 | 王曉曼

出品 | CSDN博客

口」,具體實現是task_struct數據結構:1狀態信息,例如這個

初見進程,先查一下戶口

1、進程環境


進程控制塊PCB:就是進程在作業系統中的「戶口」,具體實現是 task_struct數據結構:
1.狀態信息,例如這個進程處於可執行狀態,休眠,掛起等。
2.性質,由於unix有很多變種,進程有自己獨特的性質。
3.資源,資源的連結比如內存,還有資源的限制和權限等。
4.組織,例如按照家族關係建立起來的樹(父進程,子進程等)。

2、進程狀態


運行狀態R(TASK_RUNNING)
可中斷睡眠狀態S(TASK_INTERRUPTIBLE)
不可中斷睡眠狀態D(TASK_UNINTERRUPTIBLE)
暫停狀態T(TASK_STOPPED或TASK_TRACED)
僵死狀態Z(EXIT_ZOMBIE)
退出狀態X(EXIT_DEAD)
以上兩部分,了解即可

3、進程原語

(1)fork


#include <unistd.h>
pid_t fork(void);

功能:子進程複製父進程中的0~3G空間和PCB,但ID號不同。

Fork調用一次返回兩次

父進程中返回子進程ID (就是大於0的意思)

子進程返回0

讀時共享寫時複製,可保高效

與之相關函數:


#include<sys/types.h>
#include<unistd.h>
pid_t getpid(void); //獲取進程ID
pid_t getppid(void); //獲取父進程ID

#include <unistd.h>
#include <sys/types.h>
uid_t getuid(void);//返回實際用戶ID
uid_t geteuid(void);//返回有效用戶ID

進程的產生方式:

進程的產生有多種方式,但是追本溯源是相通的。


(1)複製父進程的系統環境(放心,只要是你開的進程,肯定有父進程)
(2)在內核中建立進程結構
(3)將結構插入到進程列表,便於維護
(4)分配資源給該進程
(5)複製父進程的內存映射消息
(6)管理文件描述符和連結點
(7)通知父進程

下面是一張進程列表的圖,命令:Pstree。

1、進程環境進程控制塊PCB:就是進程在作業系統中的「戶

可以看到Init是所有進程的父進程,其他進程都是有Init進程直接或間接Fork出來的。

(2)Exec族為什麼需要Exec函數?

  • Fork子進程是為了執行新程序(Fork創建了子進程後,子進程和父進程同時被OS調度執行,因此子進程可以單獨的執行一個程序,這個程序宏觀上將會和父進程程序同時進行)。

  • 可以直接在子進程的IF中寫入新程序打代碼。但這樣不夠靈活,因為我們只能把子進程程序的原始碼貼過來執行(必須知道原始碼,而且原始碼太長了也不好控制)使用Exec族函數運行新的可執行程序。Exec族函數可以直接把一個編譯好的可執行程序直接加載運行。

  • 有了Exec族函數後,典型打父子進程程序是這樣的:子進程需要運行的程序被單獨編寫、單獨編譯連結成一個可執行程序(Hello)。主進程為父進程,Fork創建了子進程後在子進程中Exec來執行Hello,達到父子進程分別做不同程序同時(宏觀上)運行的效果。

代碼貼這兒,看這裡講解Exec族:


#include<unistd.h>
int execve(const char *path,char *const argv[],char *const envp[]);//這個是真正的系統調用
//以下的函數最後都是調用這個函數
int execl(const char *path,char *const argv,···);
int execlp(const char *file,char *const argv,···);
int execle(const char *path,char *const argv,···· ,char *const envp[]);
int execv(const char *path,char *const argv[]);
int execvp(const char *file,char *const argv,);

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(void)
{
pid_t pid;
if((pid = fork) < 0)
{
perror("fork");
exit(1);
}
else if(pid == 0)
{
/* child */
execl("/bin/ls", "ls", "-l", "-a",);
}
else
{
printf("parent, child id = %d.\n",pid);
}
return 0;
}

(3)Wait/Waitpid

這裡幾個概念:

  • 殭屍進程:子進程退出,父進程沒有及時回收,子進程成為殭屍進程

  • 孤兒進程:父進程退出,而子進程沒有退出,子進程成為孤兒進程

  • Init進程:1號進程,負責收留孤兒進程,成為他們的父進程


有5種方式終止進程:
(1)main返回
(2)調用exit
(3)調用_exit
(4)調用abort(給自己發送異常終止信號)
(5)由一個信號終止

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status);
//這裡的status為一個整形指針,是該子進程的返回狀態。若該指針不為空,則可以通過該指針獲取子進程退出時的狀態。
pid_t waitpid(pid_t pid,int *status,int options);
// pid是進程號
/*
<-1 回收指定進程組內的任意子進程
-1 回收任意子進程
0 回收和當前waitpid調用一個組的所有子進程
>0 回收指定ID的子進程
*/
//options:
/*
WNOHANG:強制回收,不阻塞。
WUNTRANCED:一般用上面那個
*/
出品|CSDN博客初見進程,先查一下戶口

來個聯繫方式吧,進程間通信

常用的通信方式有:管道、消息隊列、共享內存、文件空間映射1、管道:兩個進程間通信,最古老的通信方式了。2、消息隊列:在內核中建立一個鍊表,發送方按照一定標識將數據發送到內核中,內核將其放入鍊表。

接收方發送請求後,內核按照標識取出消息。

消息隊列是一種完全異步的通信方式。

3、共享內存:共享內存是將內存中的一段地址,在多個進程間共享。多個進程通過掛載在自己名下的地址直接對共享內存進行操作。4、文件空間映射:Mmap函數用來將文件或設備空間映射到內存中,可以通過對映射後的內存空間操作來獲得與操作文件一致的效果。進程間同步

進程間同步的方法主要有system信號量和進程間鎖。

作者|看,未來責編|王曉曼

家庭關係如何?(進程間關係)

1、進程組一個或多個進程組成的集合,進程組的組ID是一個正整數。


//獲取當前進程組組ID
pid_t getpgid(pid_t pid);
pid_t getpgrp(void);

幾個概念:

  • 組長進程:進程ID號等於組ID。

  • 組長進程可以創建一個進程組,創建該進程組中的進程。

  • 只要進程中有一個進程存在,進程組就存在,與組長進程是否終止無關。
  • 進程組生存期:進程組創建到最後一個進程離開(終止或轉移到另一個進程組)


//一個進程可以為自己或子進程設置進程組ID
int setpgid(pid_t pid,pid_t pgid);
//非root進程只能改變自己創建的子進程,或有權限操作的進程

2、會話


pid_t setsid(void);
  • 調用進程不能是進程組組長,該進程變成新會話的首進程。
  • 該進程成為一個新進程組的組長進程。

  • 需要有Root權限(Ubunt不需要)

  • 新會話丟棄原有控制終端,該會話沒有控制終端。

  • 建立新會話時,先用Fork,然後父進程終止,子進程調用。


pid_t getsid(pid_t pid);

用於查看當前進程的會話ID。

注意點:組長進程不能成為新會話首進程,新會話首進程必定成為組長進程。

來串偽代碼:


#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main
{
pid_t pid;
pid = fork;
if(pid == 0)
{
//列印:
getpid;//進程ID
getpgid(0);//組ID
getsid(0);//會話ID
sleep(10);
setsid;//子進程設為會話組長
//子進程非組長進程,故其成為新會話首進程,且成為組長進程。
//該進程ID即為會話進程ID
//再列印一遍
getpid;//進程ID
getpgid(0);//組ID
getsid(0);//會話ID
}
}

程序、進程與線程的區分

這個問題老師問過我,當時我沒答上來。1、進程是動態的,程序是靜態的。2、一個進程只能對應一個程序,而一個程序可以對應多個進程。

從作業系統方面來看,進程代表的是作業系統分配的內存、CPU時間片等資源的基本單位,是為正在運行的程序準備的運行環境。

版權聲明:本文為CSDN博主「看,未來」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本聲明。

原文連結:

https://blog.csdn.net/qq_43762191/article/details/106024446

聲明:文章觀點僅代表作者本人,PTTZH僅提供信息發布平台存儲空間服務。
喔!快樂的時光竟然這麼快就過⋯
繼續其他精彩內容吧!
more