操作系統:Linux進程與線程


這里是一部分內容,還會做修改。

一:目的及內容

學習fork(),exec,pthread庫函數的使用,閱讀源碼,分析fork,exec,pthread_create函數的機理

代碼實現:

進程A創建子進程B

子進程B與父進程A分別對應不同的可執行體:A打印Hello world,B實現sum累加

進程B具有三線程,主線程創建新的線程1實現sum累加(從1到參數x),線程2監控輸入參數x

若輸入x是非負整數,線程1開始計算;如果線程1正在計算前次程序,線程2的輸入非負整數和最近一次的又不同,線程1應重新計算;若相同則不需要重新計算

若輸入字母p,則線程1暫停執行。

輸入字母e則線程1打印退出信息后整個進程A和B都退出

若輸入的是其他字符,則線程1打印一個輸入錯誤提示,任務繼續

分析運行中各個執行體的處理器使用,內存使用等基本信息

二 步驟

參考

Linux C編程--fork()詳解 - 張勤一 - CSDN博客 

[並發並行]_[pthread]_[對工作線程進行簡單控制-暫停-繼續-停止] - 心如止水 - CSDN博客

Linux多任務編程(三)---exec函數族及其基礎實驗 - 王大壯的博客 - CSDN博客

Linux多線程編程並傳遞多個參數實例 - blankqdb - 博客園

有關pthread線程的暫停與恢復的討論 - 一天 一小步 - CSDN博客

根據題目要求,可知需要兩個執行體A和B。根據模塊化的原則先設計A,再設計B。

1. 審題,根據題目要求,寫了進程A的代碼

#include提供fork(),execlp()函數

#include <sys/wait.h> 提供wait()函數

#include 提供類型pid_t的定義

代碼比較簡單,主要就是創建子進程,子進程用一個新的進程映像替換當前進程映像。


 

2. 之后寫子進程B的代碼

充分利用模塊化的設計方法。

先是頭文件

#include<pthread.h>提供pthread庫函數

而需要注意,gcc編譯時加上-lpthread,因為pthread並非Linux默認的庫


 

之后是幾個全局變量,減少線程間傳遞參數的麻煩。


 

1.主線程

功能是創建2個子線程,線程2監控輸入,線程1打印信息和計算累加。

當線程1,2都退出后主線程退出。

使用pthread_create創建子線程。

使用pthread_join等待線程結束


 

2.線程2

因為線程2要監控輸入,所以先寫線程2.

線程2第一部分:

主要進行輸入的處理。

詳情見圖片和代碼的注釋。

這里用c++的string處理輸入,因為沒有限制輸入類型


 

線程2第二部分:

根據輸入確定func值。func作為全局變量調整線程1的工作狀態

同時根據recent和cal判斷是否要重新計算。target是線程1從1開始的累加目標。


 

線程2第三部分:

根據第二部分得到的func調整線程1工作狀態。

func==2時,利用pthread_join()先等待線程1打印錯誤信息,再退出。

pthread_suspend()  pthread_resume()函數是自己定義的函數,用以實現線程1暫停。暫停的實現具體解釋見實驗報告后續部分。


 

3. 線程1

第一部分:實現線程1的暫停。

利用

pthread_mutex_lock(),pthread_mutexunlock(),pthread_cond_wait(),pthread_cond_broadcast()實現線程的暫停。

源碼體現的暫停實現過程更清晰。


 

 

 

第二部分:線程1進行累加,輸出信息等操作

sleep是為了體現p操作,兩次輸入相同,不同操作而設置。否則可能人輸入的速度不如計算機計算速度,導致第二次輸入還沒到,就得出上一次的結果。

 


 

綜上,進程B結構如下

void pthread_suspend(void)

void pthread_resume(coid)

void thread1(void* arg)

void thread2(void*arg)

int main()

三.分析運行中各個執行體的處理器使用,內存使用等基本信息

首先在終端運行進程A。


 

pgrep 是通過程序的名字來查詢進程的工具,一般是用來判斷程序是否正在運行。在服務器的配置和管理中,這個工具常被應用,簡單明了;

然后打開另一個終端,pgrep -l A查看進程名和pid


 

pstree -p 26638。以樹狀圖顯示進程,並顯示進程pid。可見父子進程和線程的關系。


 

ps -T -p 26639 可以查看進程B的線程信息。


 

使用top查看進程cpu和內存信息。

下圖為示例:


 

top命令的第三行,cpu狀態:

依次對應:

us:user 用戶空間占用cpu的百分比

sy:system 內核空間占用cpu的百分比

ni:niced 改變過優先級的進程占用cpu的百分比

id:空閑cpu百分比

wa:IO wait IO等待占用cpu的百分比

hi:Hardware IRQ 硬中斷 占用cpu的百分比

si:software 軟中斷 占用cpu的百分比

st:被hypervisor偷去的時間

top命令第四行,內存狀態:

total,free ,used ,buff/cache

依次對應:物理內存總量,空閑內存總量,使用中的內存總量,緩沖內存量

 

進入top后,交互時,輸入s,系統提示更改刷新間隔。輸入0則不斷刷新。


 

top -p 26638查看pid為26638的進程(即A)的信息


 

top -p - H 26639

top命令可以實時顯示各個線程情況。要在top輸出中開啟線程查看,請調用top命令的“-H”選項,該選項會列出所有Linux線程。在top運行時,你也可以通過按“H”鍵將線程查看模式切換為開或關。


 

四 遇到的問題及解決:

1.編譯時出現c++11標准庫未定義錯誤,因為編譯器使用的庫版本不同。


 

 

解決:使用-l鏈接 stdc++


 

2. gcc編譯時報錯


 

解決:

在32位模式時,int 和指針類型變量都占32位在64位模式下,int占32位,指針變量占64位


 

3.如圖


 

又是-lstdc++解決

五.實驗結果記錄:

執行程序A。程序A 父進程fork 出子進程,之后打印Hello, world!然后執行wait(),等待子進程結束。

子進程調用execlp,執行另一個執行體B。

執行體B中線程2開始監控輸入。

輸入15,是非負整數,之后線程1計算1累加到15.結果為120。120后跟着的15表明計算的是1-15累加。

輸入16,是非負整數,之后線程1計算1累加到16.結果為136。136后跟着的16表明計算的是1-16累加。

輸入18,之后輸入20.線程2監控到由於20與18不同,故線程1不再進行1-18累加,而進行1-20累加。

輸出210.

輸入25,再輸入25.線程2監控到25相同,不需要重新計算,打印信息“輸入相同,不需要重新計算”。線程1計算第一個25,輸出325.

輸入afd。線程2監控,屬於其他字符,線程1打印錯誤信息“input wrong”。

輸入fg。線程2監控,屬於其他字符,線程1打印錯誤信息“input wrong”。

輸入p,線程1暫停執行。打印信息“pause”表明線程1已暫停。

輸入123.線程2檢測到是非負整數,先調用恢復函數解除線程1的暫停。之后打印信息“resume”表示線程1已經恢復。之后線程1執行1-123累加,輸出7626.

輸入e。線程2檢測到要退出。之后線程1打印信息“A and B exited”表示主進程,子進程都要退出。之后主進程和子進程都退出。

結束。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM