實驗一 進程控制實驗

一、實驗目的

1、掌握進程的概念,理解進程和程序的區別。

2、認識和了解并發執行的實質。

3、學習使用系統調用fork()創建新的子進程方法,理解進程樹的概念。

4、學習使用系統調用wait()或waitpid()實現父子進程同步。

5、學習使用getpid()和getppid()獲得當前進程和父進程的PID號。

6、掌握使用exec簇函數實現進程映像更換的方法。

7、了解系統編程,學習父進程如何通過創建一個子進程來完成某項特定任務的方法。

二、實驗內容

1、進程的創建

??? 編寫一段程序,使用系統調用fork( )創建兩個子進程,在系統中有一個父進程和兩個子進程活動。讓每個進程在屏幕上顯示一個字符;父進程顯示字符“a”,子進程分別顯示字符“b” 和“c”。試觀察記錄屏幕上的顯示結果,并分析結果。(1分)

??? <參考程序>

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<sys/types.h>

int main()

{ ? int? p1, p2;

??? ?? while((p1=fork())==-1);

??? ??? if(p1==0)

??? ??????? printf("b ");

??? ??? else

???? ?? { ? while((p2=fork())==-1);

??????? ??? if(p2==0)

??????? ??????? printf("c ");

??????? ??? else

??????????????? printf("a ");

??????? }

??????? return 0;

}

執行結果及結果分析:

shell窗口也是一個進程,所以看到4個進程信息,一個父進程,二個子進程和一個shell進程。先是父進程輸出a, 子進程1輸出b,之后是子進程2輸出c,之后輸出shell窗口提示符。

  1. 修改第一題,在父進程中顯示當前進程識別碼,在每個子進程中顯示當前進程識別碼和父進程識別碼,運行程序查看結果,分析運行結果。

試做:

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<sys/types.h>

int main()

{ ? int? p1, p2;

??? while((p1=fork())==-1);

??? if(p1==0)??? //p1子進程

??? ??? printf("b: pid=%d ppid=%d\n",getpid(),getppid());

?? ?else??????? //父進程

??? { ? while((p2=fork())==-1);

??????? if(p2==0)//p2子進程

??????? ??? printf("c: pid=%d ppid=%d\n",getpid(),getppid());

?????? ?else???? //父進程

??????????? printf("a: pid=%d\n",getpid());

??? }

??????? return 0;

}

運行結果:

結果分析:

先打印父進程 然后創建第一個子進程p1,然后父進程創建第二個子進程p2,如果不想讓父進程在子進程結束之前結束,可以用wait(0)讓父進程等待子進程結束,之后父進程再結束。2個wait(0)是因為有2個子進程要等待。

  1. 改進第二題,使父進程等待兩個子進程結束之后再結束。

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<sys/types.h>

int main()

{ ? int? p1, p2;

??? while((p1=fork())==-1);

??? if(p1==0)

??? ??? printf("b:pid=%d ppid=%d\n",getpid(),getppid());

??? else

??? { ? while((p2=fork())==-1);

??????? if(p2==0)

??????? ??? printf("c:pid=%d ppid=%d\n",getpid(),getppid());

??????? else

??????????? {

wait(0);

wait(0);

??????????????? printf("a:pid=%d\n",getpid());

??????????? }

??? }

??????? return 0;

}

運行結果:

從上述子進程和父進程識別碼可以看出父子進程之間的關系。


?

圖1進程樹的參考程序:

#include<stdio.h>

#include<unistd.h>

int main()

{

??? int? p1,p2,p3;

??? while((p1=fork())== -1);

??? if(p1==0)

??? {

? ????? while((p2=fork())==-1);???????

?? ???? if(p2==0)

?? ???? {

??? ??????? while((p3=fork())==-1);???????

????? ????? if(p3==0)?? //p3子進程

????? ????????? printf(" d,Mypid=%d, myppid=%d\n", getpid(), getppid());

???? ?????? ?else?? //p2子進程

??????????????? printf(" c,Mypid=%d, myppid=%d\n", getpid(), getppid());

??????? }

??? ??? else //p1子進程

????? ? printf(" b,Mypid=%d, myppid=%d\n", getpid(), getppid());

??? }

??? else //主進程

??????? printf(" a,Mypid is %d\n", getpid());

getchar();

}

編譯及執行程序:

結果截屏:

  1. 模仿第2題,按圖2進程樹編寫程序,給出編譯及執行過程和結果截屏。(1分)

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <sys/wait.h>

int main() {

??? pid_t a, b, c, d, e;

??? a = fork();

??? if (a < 0) {

??????? perror("fork");

??????? exit(1);

??? }

??? if (a == 0) {

??????? printf("I am process A\n");

??????? b = fork();

??????? if (b < 0) {

??????????? perror("fork");

??????????? exit(1);

??????? }

??????? if (b == 0) {

??????????? printf("I am process Bn");

??????????? c = fork();

??????????? if (c < 0) {

??????????????? perror("fork");

??????????????? exit(1);

??????????? }

??????????? if (c == 0) {

??????????????? printf("I am process C\n");

??????????? } else {

??????????????? printf("I am process B, and my child is process C\n");

??????????????? wait(NULL);

??????????? }

??????? } else {

??????????? printf("I am process A, and my child is process B\n");

??????????? wait(NULL);

??????? }

??? } else {

??????? d = fork();

??????? if (d < 0) {

??????????? perror("fork");

??????????? exit(1);

??????? }

??????? if (d == 0) {

??????????? printf("I am process Dn");

??????????? e = fork();

??????????? if (e < 0) {

??????????????? perror("fork");

??????????????? exit(1);

??????????? }

??????????? if (e == 0) {

??????????????? printf("I am process E\n");

??????????? } else {

??????????????? printf("I am process D, and my child is process E\n");

??????????????? wait(NULL);

??????????? }

??????? } else {

??????????? printf("I am process A, and my child is process D\n");

??????????? wait(NULL);

??????? }

??? }

??? return 0;

}

結果截屏:

  1. 分析程序,給出編譯及執行過程和結果截屏。(2分)
  1. #include<unistd.h>

#include<stdlib.h>

#include<stdio.h>

#include <sys/wait.h>

int main()

{?? int child,p;

??????? while((child=fork())==-1);

??????? if(child==0)??? //子進程下

??????? {?? printf("In child: sleep for 10 seconds and then exit. \n");

??????????? sleep(10);

??????????? exit(0);

??????? }

??????? else??? //父進程下

??????? {?? do

??????????? {?? p=waitpid(child,NULL,WNOHANG);? //非阻塞式等待子進程結束

??????????????? if(p==0)

??????????????? {?? printf("In father: The child process has not exited.\n");

?????????????????? sleep(1);

??????????????? }

??????????? }while(p==0);

??????????? if(p==child)

??????????? {?? printf("Get child exitcode then exit!\n");}

??????????? else

??????????? {?? printf("Error occured!\n");}

??????? }

??????? exit(0);

}

編譯及執行過程和運行結果截屏:

分析程序功能:

該程序的功能是創建一個子進程,并在子進程中睡眠10秒后退出,父進程不阻塞地等待子進程結束并獲取退出狀態碼,然后退出。

2) #include<unistd.h>

#include<stdlib.h>

#include<stdio.h>

main()

{?? int child,p;

??????? while((child=fork())==-1);

??????? if(child==0)??? //子進程下

??????? {?? execl("/home/student/welcome.out","",NULL);

??????????? exit(0);

??????? }

??????? else??? //父進程下

??????? {?? p=waitpid(child,NULL,0);? //阻塞式等待子進程結束??

if(p==child)

printf("Get child exitcode then exit!\n");

else

??????????????? printf("Error occured!\n");

??????? }

exit(0);

}

子進程要加載程序的源程序welcome.c

#include<stdio.h>

main()

{?? printf("Hello! This is another process.\n");}

編譯及執行過程和運行結果截屏:

5. 編程創建2個子進程,子進程1運行指定路徑下的可執行文件(如:/home/student/welcome.out),子進程2暫停10s之后退出,父進程先用阻塞方式等待子進程1的結束,然后用非阻塞方式等待子進程2的結束,待收集到二個子進程結束的信息,父進程就返回。(2分)

參考程序框架:

#include<unistd.h>

#include<stdlib.h>

#include<stdio.h>

#include<sys/wait.h>

int main()

{?? int child1,child2,p;

??? while((child1=fork())==-1);

??? if(child1==0)?? //child1置換進程

??? {

???????? execl("/home/gzh0624/welcome.o","welcome.o",NULL);

???????? perror("execl");

???????? exit(0);

??? ? }

??? else??? //father

??? {?? while((child2=fork())==-1);

??????? if(child2==0)?? //child2暫停10秒退出

??????? {??

??????????????????? sleep(10);

??????????????????? exit(0);

??????? ? }

??????? else??? //father等待子進程結束

??????? {?? p=waitpid(child1,NULL,0);//阻塞式等待子進程1結束??

??????????? if(p==child1)

??????????????? printf("Get child1 exitcode then exit!\n");

??????????? else

??????????????? printf("Error occured!\n");

??????????? do

??????????? {p=waitpid(child2,NULL,WNOHANG);//非阻塞式等待子進程2結束

??????????????? if(p==0)

??????????????? {??

?????????????????? printf("In father: The child2 process has not exited.\n");

?????????????????? sleep(1);

??????????????? }

??????????? }while(p==0);

??????????? if(p==child2)??

??????????????? printf("Get child2 exitcode then exit!\n");

??????????? else???

??????????????? printf("Error occured!\n");

??????? }

??? }

??? exit(0);

}編譯及執行過程:

結果截屏:

分析程序功能:

程序的功能是創建兩個子進程,其中一個子進程調用另一個可執行文件welcome.o,另一個子進程暫停10秒后退出。父進程等待子進程結束,并打印相應的信息。

  1. 編寫一個簡易的shell解釋程序。其運行原理是:當命令行上有命令需要執行時,shell進程獲得該命令,然后創建子進程,讓子進程執行該命令,shell進程等待子進程退出,之后繼續等待命令行上的命令周而復始。(附加題)

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/wait.h>

#include <string.h>

#define MAX_CMD_LENGTH 100

void execute_command(char *command) {

??? pid_t pid;

??? pid = fork();

??? if (pid < 0) {

??????? fprintf(stderr, "Fork failed\n");

??????? exit(1);

??? } else if (pid == 0) { // Child process

??????? char *args[MAX_CMD_LENGTH];

??????? // Split the command into arguments

??????? char *token = strtok(command, " ");

??????? int i = 0;

??????? while (token != NULL) {

??????????? args[i++] = token;

??????????? token = strtok(NULL, " ");

??????? }

??????? args[i] = NULL;

??????? // Execute the command

??????? execvp(args[0], args);

??????? // If execvp returns, there was an error

??????? fprintf(stderr, "Command not found: %s\n", args[0]);

??????? exit(1);

??? } else { // Parent process

??????? int status;

??????? waitpid(pid, &status, 0);

??? }

}

int main() {

??? char command[MAX_CMD_LENGTH];

??? while (1) {

??????? printf("shell> ");

??????? fgets(command, MAX_CMD_LENGTH, stdin);

??????? // Remove new line character

??????? command[strcspn(command, "\n")] = 0;

??????? // Check if user wants to exit

??????? if (strcmp(command, "exit") == 0) {

??????????? break;

??????? }

??????? execute_command(command);

??? }

??? return 0;

}

編譯及執行過程:

結果截屏:

三、實驗總結和體會

? 在本次實驗中,我們深入學習并實踐了Linux進程控制的相關知識和技術。通過對進程創建、銷毀、管理等操作的實踐,我對Linux進程控制有了更加深入的理解和掌握。

首先,通過實驗,我學會了如何創建新的進程。我們使用了fork()系統調用,它可以創建一個與原進程幾乎完全相同的新進程,包括代碼、數據、運行時堆棧等。我們還學習了如何在新的進程中執行不同的代碼,以實現不同的功能。

其次,我學會了如何控制進程的執行。通過實驗中的信號處理,我們可以向進程發送信號,從而實現對進程的控制。我們學習了不同的信號及其對應的處理方式,如SIGINT、SIGKILL、SIGSTOP等。通過實驗,我更加了解了信號的工作原理和使用方法。

此外,我還學會了如何管理進程的資源。通過實驗中的共享內存和進程間通信,我們可以實現不同進程之間的數據傳遞和共享。我們學習了共享內存的創建、映射和銷毀等操作,以及如何使用信號量進行進程間的同步和互斥。

通過這次實驗,我深刻體會到了進程控制在操作系統中的重要性。進程是操作系統中最基本的運行單位,掌握好進程控制的知識和技術對于編程和系統管理都非常重要。通過實踐,我對Linux進程控制有了更加深入的理解,并且進一步培養了自己的編程能力和解決問題的能力。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/902440.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902440.shtml
英文地址,請注明出處:http://en.pswp.cn/news/902440.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Python Web開發】01-Socket網絡編程01

文章目錄 1.套接字(Socket)1.1 概念1.2 類型1.3 使用步驟 Python 的網絡編程主要用于讓不同的計算機或者程序之間進行數據交換和通信&#xff0c;就好像人與人之間打電話、發消息一樣。 下面從幾個關鍵方面通俗易懂地介紹一下&#xff1a; 1.套接字(Socket) 在 Python 網絡編…

Git 配置 GPG 提交簽名

使用 GPG 對 Git 提交進行簽名&#xff0c;可以證明該提交確實是你本人提交的。這在團隊協作和代碼審核中非常有用&#xff0c;GitHub/GitLab 等平臺也會顯示 “Verified” 標簽。 &#x1f9e9; 一、檢查是否已安裝 GPG gpg --version 如果未安裝&#xff0c;可使用以下命令…

MySQL運維三部曲初級篇:從零開始打造穩定高效的數據庫環境

文章目錄 一、服務器選型——給數據庫一個舒適的家二、系統調優——打造高性能跑道三、MySQL配置——讓數據庫火力全開四、監控體系——數據庫的體檢中心五、備份恢復——數據安全的最后防線六、主從復制——數據同步的藝術七、安全加固——守護數據長城 引言&#xff1a;從小白…

實踐項目開發-hbmV4V20250407-跨平臺開發框架深度解析與VSCode一站式開發實踐

跨平臺開發框架深度解析與VSCode一站式開發實踐 在當今多端應用開發需求激增的背景下&#xff0c;跨平臺開發框架成為了眾多開發者的首選。本文將圍繞React Native、Taro及其結合方案&#xff0c;以及Uni-app、MUI、Quasar等輕量級框架展開詳細分析&#xff0c;并探討如何在VS…

Android15沉浸式界面頂部有問題

Android15沉浸式界面頂部有問題 往往開發人員的手機沒這么高級&#xff0c;客戶或者老板的手機是Android15的。 我明明就設了狀態欄透明&#xff0c;我的手機也沒問題。但Android15是有問題的。 先看下有問題的界面&#xff1a; 解決方案&#xff1a; 處理1&#xff1a; if (…

uni-app 狀態管理深度解析:Vuex 與全局方案實戰指南

uni-app 狀態管理深度解析&#xff1a;Vuex 與全局方案實戰指南 一、Vuex 使用示例 1. 基礎 Vuex 配置 1.1 項目結構 src/ ├── store/ │ ├── index.js # 主入口文件 │ └── modules/ │ └── counter.js # 計數器模塊 └── main.js …

【STM32單片機】#11 I2C通信(軟件讀寫)

主要參考學習資料&#xff1a; B站江協科技 STM32入門教程-2023版 細致講解 中文字幕 開發資料下載鏈接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 單片機套裝&#xff1a;STM32F103C8T6開發板單片機C6T6核心板 實驗板最小系統板套件科協 實驗&…

每天一道面試題@第一天

1&#xff1a;TCP和UDP的區別&#xff0c;TCP為什么是三次握手&#xff0c;不是兩次&#xff1f; 因為TCP是全雙工協議&#xff0c;區別在于TCP可靠&#xff0c;UDP不可靠&#xff0c;效率更高。 詳解&#xff1a; TCP&#xff08;傳輸控制協議&#xff09;和 UDP&#xff08;…

一款強大的實時協作Markdown工具 | CodiMD 9.6K ?

CodiMD 介紹 CodiMD 是一個開源的實時協作 Markdown 筆記工具&#xff0c;它允許用戶在任何平臺上共同編輯 Markdown 文檔。核心功能是實時協作&#xff0c;它允許多個用戶同時編輯同一個文檔&#xff0c;并實時看到彼此的更改。支持實時渲染預覽&#xff0c;支持超多的富文本格…

若依如何切換 tab 不刷新

方法 如上圖配置 菜單中選是否緩存&#xff1a;緩存 資料 前端手冊 |RuoYi:

【浙江大學DeepSeek公開課】回望AI三大主義與加強通識教育

回望AI三大主義與加強通識教育 一、人工智能三大主義二、人工智能發展歷程三、從 ChatGPT 到 DeepSeek四、人工智能通識教育五、人工智能的挑戰與未來 一、人工智能三大主義 符號主義 &#xff1a;邏輯推理&#xff0c;將推理視為計算過程。如蘇格拉底三段論&#xff0c;通過前…

邊緣計算全透視:架構、應用與未來圖景

邊緣計算全透視&#xff1a;架構、應用與未來圖景 一、產生背景二、本質三、特點&#xff08;一&#xff09;位置靠近數據源&#xff08;二&#xff09;分布式架構&#xff08;三&#xff09;實時性要求高 四、關鍵技術&#xff08;一&#xff09;硬件技術&#xff08;二&#…

C++——多態、抽象類和接口

目錄 多態的基本概念 如何實現多態 在C中&#xff0c;派生類對象可以被當作基類對象使用 編程示例 關鍵概念總結 抽象類 一、抽象類的定義 基本語法 二、抽象類的核心特性 1. 不能直接實例化 2. 派生類必須實現所有純虛函數才能成為具體類 3. 可以包含普通成員函數和…

初級達夢dba的技能水準

在x86環境&#xff08;windows、linux&#xff09;安裝單機軟件&#xff0c;安裝客戶端創建過至少20套數據庫&#xff0c;優化參數并更新過正式許可會用邏輯導出導入以及dmrman備份了解manager工具的使用配置sqllog日志&#xff0c;并能解釋輸出內容能夠分析因磁盤空間不足、內…

監控頁面卡頓PerformanceObserver

監控頁面卡頓PerformanceObserver 性能觀察器掘金 const observer new PerformanceObserver((list) > {}); observer.observe({entryTypes: [longtask], })

智能座艙測試內容與步驟

智能座艙的測試步驟通常包括以下環節&#xff1a; 1.測試環境搭建與準備 ? 硬件需求分析&#xff1a;準備測試車輛、服務器與工作站、網絡設備以及傳感器和執行器模擬器等硬件設備。 ? 軟件需求分析&#xff1a;選擇測試管理軟件、自動化測試工具、模擬軟件和開發調試工具等。…

Redis——網絡模型

目錄 前言 1.用戶空間和內核空間 1.2用戶空間和內核空間的切換 1.3切換過程 2.阻塞IO 3.非阻塞IO 4.IO多路復用 4.1.IO多路復用過程 4.2.IO多路復用監聽方式 4.3.IO多路復用-select 4.4.IO多路復用-poll 4.5.IO多路復用-epoll 4.6.select poll epoll總結 4.7.IO多…

電力系統中為什么采用三相交流電?

電力系統中為什么采用三相交流電 電力系統中采用三相交流電&#xff0c;主要是因為它在輸電效率、設備使用、能量傳輸平穩性等方面相比單相交流或直流電具有顯著優勢。下面我詳細解釋一下原因&#xff1a; &#x1f31f; 1. 提高輸電效率&#xff08;節省電纜材料&#xff09;…

python簡介與入門

目錄 python初始 python的優勢 python的特性 python的應用領域 Linux環境中安裝python 下載python3.11.6 安裝依賴包 解壓python壓縮包 安裝python 編譯及安裝 建立軟連接 測試python3運行 設置國內pip更新源 更新pip版本&#xff08;必須更新&#xff09; wind…

Web內網滲透知識大全

內網滲透 端口轉發 需要三個主機&#xff0c;Windows7、Windows2016、kali Windows7為內網主機 Windows2016為跳板機 kali為攻擊機 使用到的工具 netsh、MSF 我們先在Windows7上開啟一個80服務&#xff0c;而這個80服務只能由Windows2016訪問&#xff0c;kali不能訪問 我們…