Day03_C語言IO進程線程

01.思維導圖

02.創建一個進程扇

#include <25051head.h>
int main(int argc, const char *argv[])
{pid_t pid;int i;for(i=0;i<4;++i){pid=fork();if(pid==0){//printf("子進程:pid=[%d]\n",pid);printf("子進程%d:子進程pid=[%d],父進程pid=[%d]\n",i+1,getpid(),getppid());//子進程輸出信息后退出循環,不再創建新進程break;}else if(pid<0){ERRLOG("fork_error..\n");exit(EXIT_FAILURE);}}if(pid>0){sleep(1);	//父進程等待所有子進程結束int status;pid_t wpid;i=1;while((wpid=wait(&status))>0){//打印子進程結束信息printf("子進程%d:%d已結束,退出狀態:%d\n",i,wpid,WEXITSTATUS(status));i++;}}//while(1);return 0;
}

25051head.h

#ifndef __25051HED_H__
#define __25051HED_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>//引入open函數
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>//引入 getdtablesize函數,獲取文件描述符個數,包含close函數
#include <time.h>
#include <sys/wait.h>#define ERRLOG(msg) do{printf("__%d__",__LINE__);fflush(stdout);perror(msg);return -1;}while(0)  
#endif

03.創建一個進程扇

#include <25051head.h>
int main(int argc, const char *argv[])
{pid_t pid;int i;//打印自定義的進程編號的pid_t child_pids[4];int child_index[4];for (i = 0; i<4;++i) {pid = fork();if (pid < 0) {perror("fork");exit(EXIT_FAILURE);} else if (pid == 0) {// 子進程繼續循環創建下一個子進程printf("進程 %d,進程 ID: %d,父進程 ID: %d\n", i+1, getpid(), getppid());} else {// 父進程退出循環  記錄子進程對應的PID和對應的序號child_pids[i]=pid;child_index[i]=i+1;break;}}if (pid > 0) {// 父進程等待子進程結束int status;pid_t wpid;while((wpid= wait(&status))>0){for(int j=0;j<4;++j){if(child_pids[j]==wpid){printf("父進程%d: %d 等待子進程結束后退出\n",child_index[j],getpid());}}}} else {// 最后一個子進程不需要等待,直接退出if (i == 3) {printf("最后一個子進程 %d 退出\n", getpid());}}//while(1);return 0;
}

學習總結:

1. 進程結構
鏈式進程:呈現出線性的層次結構。每個進程(除了最后一個子進程)只創建一個子進程,形成類似鏈條的結構。例如,進程 A 創建進程 B,進程 B 創建進程 C,進程 C 創建進程 D,以此類推。
扇形進程:是一種扁平的結構。由一個父進程一次性創建多個子進程,所有子進程都是該父進程的直接子進程。例如,進程 A 同時創建進程 B、C、D、E 等。
2. 創建邏輯
鏈式進程:代碼里,子進程會繼續循環創建下一個子進程,而父進程創建子進程后就退出循環。一般通過在 fork 后,子進程不跳出循環,父進程跳出循環來實現。示例代碼如下:
// 鏈式進程示例

for (i = 0; i < 4; ++i) {pid = fork();if (pid < 0) {perror("fork");exit(EXIT_FAILURE);} else if (pid == 0) {// 子進程繼續循環創建下一個子進程} else {// 父進程退出循環break;}
}


扇形進程:父進程通過循環多次調用 fork 函數創建多個子進程,每個子進程創建后直接退出循環,不再創建新的子進程。示例代碼如下:
// 扇形進程示例

// 扇形進程示例
for (i = 0; i < 4; ++i) {pid = fork();if (pid < 0) {perror("fork");exit(EXIT_FAILURE);} else if (pid == 0) {// 子進程輸出信息后退出循環,不再創建新進程break;}// 父進程繼續循環創建子進程
}


3. 資源管理
鏈式進程:每個進程只需要管理自己創建的一個子進程,資源管理相對簡單。父進程只需等待自己的直接子進程結束,就能避免僵尸進程。
扇形進程:父進程需要管理多個子進程,要確保等待所有子進程結束,防止出現多個僵尸進程。通常使用循環調用 wait 或 waitpid 函數來等待所有子進程。
4. 復雜度和應用場景
鏈式進程:結構簡單,邏輯清晰,適用于任務需要按順序依次執行,每個任務依賴前一個任務結果的場景。
扇形進程:可以充分利用多核 CPU 的并行計算能力,適用于多個獨立任務可以同時執行的場景,比如并行處理多個文件、同時進行多個網絡請求等。

0.4.解析代碼

代碼解析結果:

#include <25051head.h>
int main(int argc, const char *argv[])
{pid_t pid1,pid2;//返回值->父進程:pid>0;子進程:pid=0;運行失敗:pid<0if((pid1=fork())==0){sleep(3);printf("info1 from child process_1\n");exit(0);printf("info2 from child process_1\n");}else{if((pid2=fork())==0){sleep(1);printf("info1 from child process_2\n");exit(0);}else{sleep(7);printf("info1 from parent process\n");printf("info2 from parent process");_exit(0);}	}while(1);return 0;
}

輸出結果:
info1 from child process_2
info1 from child process_1
info1 from parent process

05.實現文件的拷貝,父進程拷貝前一部分,子進程拷貝后一部分

方法一:標準IO

#include <25051head.h>
int main(int argc, const char *argv[])
{//1.打開文件FILE* src_fp=fopen("/home/ubuntu/25041/linux/lj/day21_IO/hm/my.txt","a+");if(NULL==src_fp){ERRLOG("src_fopen_error");}printf("src_fopen_success..\n");FILE* dest_fp=fopen("/home/ubuntu/25041/linux/lj/day21_IO/hm/my2.txt","w+");if(NULL==dest_fp){ERRLOG("dest_fopen_error");}printf("dest_fopen_success..\n");//2.循環寫入數據#if 1//循環輸入char buf[128]="";while(1){memset(buf,0,sizeof(buf));printf("請輸入buf:");if(scanf("%s",buf)!=1){ERRLOG("scanf_error");}if(strcmp(buf,"#")==0){printf("輸入字符#結束輸入.\n");break;}
#if 1if(EOF==fputs(buf,src_fp)){printf("src_fputs_error..\n");return -1;}//寫入換行符,方便讀取時按行處理if(EOF==fputc('\n',src_fp)){printf("src_fputs_error..\n");return -1;}
#endif}
#if 0snprintf(buf,sizeof(buf)-1,"%s",buf);size_t res=fwrite(buf,1,strlen(buf),src_fp);if(res<strlen(buf)){printf("src_fwrite_error");return -1;}rewind(src_fp);
#endif#endiffflush(src_fp);rewind(src_fp);//3.讀取文件size_t res;while(1){memset(buf,0,sizeof(buf));res=fread(buf,1,sizeof(buf)-1,src_fp);if(res>0){//printf("%s\n",buf);}if(feof(src_fp)){printf("讀取到文件的結尾..\n");break;}if(ferror(src_fp)){printf("函數運行失敗..\n");break;}}//獲取文件大小fseek(src_fp,0,SEEK_END);long file_size=ftell(src_fp);printf("file_size=%ld\n",file_size);rewind(src_fp);//創建子進程pid_t pid=fork();if(pid<0){ERRLOG("fork_error");}else if(pid==0){//sleep(1);FILE* child_src_fp=fopen("/home/ubuntu/25041/linux/lj/day21_IO/hm/my.txt","r");FILE* child_dest_fp=fopen("/home/ubuntu/25041/linux/lj/day21_IO/hm/my2.txt","r+");if(child_src_fp==NULL||child_dest_fp==NULL){ERRLOG("child_open_error");}//子進程處理文件后半部分的內容fseek(child_src_fp,file_size/2,SEEK_SET);fseek(child_dest_fp,file_size/2,SEEK_SET);while((res=fread(buf,1,sizeof(buf),child_src_fp))>0){if(fwrite(buf,1,res,child_dest_fp)!=res){printf("子進程:dest_fwrite_error\n");fclose(child_src_fp);fclose(child_dest_fp);return -1;}}fclose(child_src_fp);fclose(child_dest_fp);exit(EXIT_SUCCESS);}else{//sleep(1);//父進程處理文件前半部分while(ftell(src_fp)<file_size/2){res=fread(buf,1,sizeof(buf),src_fp);if(res>0){if(fwrite(buf,1,res,dest_fp)!=res){printf("父進程:dest_fwrite_error\n");return -1;}}}//等待子進程結束int status;wait(&status);}//4.關閉文件if(EOF==fclose(src_fp)){ERRLOG("src_fclose_error");}printf("src_fclose_success..\n");if(EOF==fclose(dest_fp)){ERRLOG("dest_fclose_error");}printf("dest_fclose_success..\n");return 0;
}

?方法二:文件IO(不需要考慮緩沖區的問題,不需要重新再打開文件在子進程中)

#include <25051head.h>
int main(int argc, const char *argv[])
{umask(0);//1.打開文件int src_fd = open("/home/ubuntu/25041/linux/lj/day21_IO/hm/my.txt", O_RDWR | O_CREAT | O_APPEND, 0777);if (src_fd == -1) {ERRLOG("src_open_error");}printf("src_open_success..\n");int dest_fd = open("/home/ubuntu/25041/linux/lj/day21_IO/hm/my2.txt", O_RDWR | O_CREAT | O_TRUNC, 0777);if (dest_fd == -1) {ERRLOG("dest_open_error");}printf("dest_open_success..\n");//2.循環寫入數據char buf[128] = "";while (1) {memset(buf, 0, sizeof(buf));printf("請輸入buf:");if (scanf("%s", buf) != 1) {ERRLOG("scanf_error");}if (strcmp(buf, "#") == 0) {printf("輸入字符#結束輸入.\n");break;}ssize_t write_res = write(src_fd, buf, strlen(buf));if (write_res == -1) {printf("src_write_error..\n");close(src_fd);close(dest_fd);return -1;}// 寫入換行符,方便讀取時按行處理write_res = write(src_fd, "\n", 1);if (write_res == -1) {printf("src_write_error..\n");close(src_fd);close(dest_fd);return -1;}}// 獲取文件大小off_t file_size = lseek(src_fd, 0, SEEK_END);printf("file_size=%ld\n", (long)file_size);lseek(src_fd, 0, SEEK_SET);// 創建子進程pid_t pid = fork();if (pid < 0) {ERRLOG("fork_error");} else if (pid == 0) {// 子進程處理文件后半部分的內容lseek(src_fd, file_size / 2, SEEK_SET);lseek(dest_fd, file_size / 2, SEEK_SET);ssize_t res;while ((res = read(src_fd, buf, sizeof(buf))) > 0) {if (write(dest_fd, buf, res) != res) {printf("子進程:dest_write_error\n");close(src_fd);close(dest_fd);exit(EXIT_FAILURE);}}close(src_fd);close(dest_fd);exit(EXIT_SUCCESS);} else {// 父進程處理文件前半部分off_t pos = 0;while (pos < file_size / 2) {ssize_t res = read(src_fd, buf, sizeof(buf));if (res > 0) {if (write(dest_fd, buf, res) != res) {printf("父進程:dest_write_error\n");close(src_fd);close(dest_fd);return -1;}pos += res;}}// 等待子進程結束int status;wait(&status);}//4.關閉文件if (close(src_fd) == -1) {ERRLOG("src_close_error");}printf("src_close_success..\n");if (close(dest_fd) == -1) {ERRLOG("dest_close_error");}printf("dest_close_success..\n");return 0;
}	

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

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

相關文章

獲取Qwen 2.5 內部網絡結構 講解

獲取Qwen 2.5 內部網絡結構 講解 Qwen2DecoderLayer( (self_attn): Qwen2Attention( (q_proj): Linear(in_features=2048, out_features=2048, bias=True) (k_proj): Linear(in_features=2048, out_features=256, bias=True) (v_proj): Linear(in_features=2048, out_features…

在深度學習中,batch、epoch 和 iteration 的關系

用一個實際例子和簡單代碼來清晰解釋 batch、epoch 和 iteration 的關系&#xff1a; ------------------------------------------------------------------------------------ 假設場景 你有一個數據集&#xff1a;1000 張貓狗圖片 你設置 batch_size 100&#xff08;每次…

RabbitMQ 高級特性之持久性

1. 簡介 在 RabbitMQ 的消息發送流程中&#xff0c;一共有三種消息丟失的情況&#xff1a; 生產者給 broker 發送的消息&#xff0c;broker 沒有收到broker 將消息丟失broker 給消費者發送消息時消息丟失 對于第一種情況&#xff0c;我們可以使用 RabbitMQ 提供的發布確認模…

應急響應靶機-近源OS-1-知攻善防實驗室

前景需要&#xff1a; 小王從某安全大廠被優化掉后&#xff0c;來到了某私立小學當起了計算機老師。某一天上課的時候&#xff0c;發現鼠標在自己動彈&#xff0c;又發現除了某臺電腦&#xff0c;其他電腦連不上網絡。感覺肯定有學生搗亂&#xff0c;于是開啟了應急。 1.攻擊…

Linux 內存管理與緩存機制

文章目錄 內存介紹buff/cache 與匿名頁Swap&#xff08;交換空間&#xff09;&#xff1a;內存的臨時倉庫 內存回收與Swap機制內存頁的兩種類型內核回收決策流程如何解讀內存狀態drop_caches 參數說明 實踐操作查看內存狀態查看Swap狀態釋放 buff/cache 緩存 內存介紹 當使用 …

【嵌入式電機控制#6】編碼器原理與內部構造

一、簡介 編碼器是一種將直線位移和角位移數據轉換為脈沖信號、二進制編碼的設備。常用于測量物體運動的位置、角度或速度。 二、分類 1. 按檢測分類&#xff1a; &#xff08;1&#xff09;光電式編碼器 &#xff08;2&#xff09;磁電式編碼器 2. 編碼類型分類&#xff1a; …

FastAPI 安裝使用教程

一、FastAPI 簡介 FastAPI 是一個現代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;基于 Python 3.7 和標準類型提示構建&#xff0c;廣泛應用于 API 服務開發。它使用 Pydantic 進行數據驗證&#xff0c;集成自動生成 OpenAPI 和文檔 UI&#xff0c;非常適合…

【WPF】WPF(樣式)

Window.Resources 當前窗體作用域資源 TargetType“Button” 使得當前窗體的組件類型都適配此樣式<Window.Resources><Style TargetType"Button"><Setter Property"Background" Value"WhiteSmoke"></Setter><Setter…

Jmeter(六):json斷言元件,jmeter參數化實現

&#x1f345; 點擊文末小卡片 &#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 json斷言元件 json斷言元件介紹 json斷言元件與響應斷言元件的功能類型&#xff0c;它只針對響應正文為json數據格 式的內容進行斷言功能。 添加路徑&…

python3常用模塊

1 數學運算模塊 math “math”模塊提供了許多常用的數學函數&#xff0c;例如三角函數、四舍五入、指數、對數、平方根、總和等 import math1.1 常數 math.pi 返回圓周率的數學常數。math.e 返回指數的數學常數示例&#xff1a; print(math.pi) print(math.e)1.2 fabs(x) …

基于Pandas和FineBI的昆明職位數據分析與可視化實現(二)- 職位數據清洗與預處理

文章目錄 一、數據集介紹二、缺失值處理三、重復值處理四、薪資數據格式處理五、技能格式處理六、拆分薪資列并處理異常值七、拆分工作區域列八、清洗后的數據集九、完整代碼 一、數據集介紹 這份昆明職位數據集源自 Boss 直聘&#xff0c;數據量頗為豐富&#xff0c;包含 177…

工業4.0核心引擎!意法STM32F407ZET6 單片機 賦能智能PLC/網關設計

STM32F407ZET6 單片機深度解析 1. 產品定位 STM32F407ZET6 是意法半導體&#xff08;STMicroelectronics&#xff09;推出的 高性能ARM Cortex-M4單片機&#xff0c;采用 LQFP144封裝&#xff0c;主打 浮點運算、豐富外設和工業級可靠性&#xff0c;廣泛應用于需要復雜算法和實…

[Andrej Karpathy_2] vibe coding | 大型語言模型的1960年代 | 自主性滑塊

Hugging Face的Tom Wolf分享了一段我非常喜歡的視頻&#xff0c;這些孩子正在進行氛圍編程。 我覺得這是一個非常治愈的視頻&#xff0c;我愛這個視頻。&#xff08;they grow up "knowing" they can build anything &#x1f62d;greatness) 未來是美好的 前文&…

uv包管理常用命令

uv常用命令 uv init 初始化項目 uv add 包名 添加包&#xff1b;多個包名&#xff0c;中間用空格 uv tree 包的關系 uv remove 刪除所有包 uv sync 重新解析 安裝工具 1、mypy 檢測工具 uv tool install mypy uv tool run mypy xxx.py 使用 2、Ruff uv tool…

Nano-vLLM 源碼學習

以下內容由Trae生成。我只管問和排版。 Nano-vLLM 是一個從零構建的輕量級vLLM實現項目&#xff0c;具備快速離線推理、代碼可讀性高和優化功能豐富等特點&#xff0c;性能表現和原版vLLM相媲美。以下是該項目各目錄和文件的功能說明&#xff1a; 1. 根目錄&#xff1a; benc…

MySQL 8.4 備份與恢復完全指南

本文全面解析MySQL 8.4的備份與恢復機制&#xff0c;涵蓋備份類型、方法、策略及實際操作示例。 一、備份類型解析 1. 物理(原始)備份 vs 邏輯備份 特性物理備份邏輯備份原理直接復制數據庫目錄/文件&#xff08;如數據文件、日志&#xff09;導出邏輯結構&#xff08;CREATE…

Mac 部署Latex OCR并優化體驗(打包成App并支持全局快捷鍵)

&#x1f341; 前言 最近閱讀論文&#xff0c;在做筆記的時候總是要手動輸入一些latex公式&#xff0c;非常耗時。我使用Hapigo的Latex 公式識別&#xff0c;感覺還挺好用&#xff0c;但是缺陷是只有30次免費額度&#xff0c;于是在網上搜索了一下&#xff0c;發現可以通過本地…

128K 長文本處理實戰:騰訊混元 + 云函數 SCF 構建 PDF 摘要生成器

一、背景 在數字化辦公時代&#xff0c;PDF 文檔因其格式穩定、兼容性強等特點&#xff0c;成為知識分享與文檔存儲的主要載體之一。但隨著文檔規模的增長&#xff0c;如何快速提取關鍵信息成為亟待解決的問題。尤其對于 128K 字符及以上的長文本 PDF&#xff0c;傳統處理方法…

Elasticsearch 排序性能提升高達 900 倍

作者&#xff1a;來自 Elastic Benjamin Trent, Mayya Sharipova, Chenhui Wang 及 Libby Lin 了解我們如何通過更快的 float / half_float 排序和 integer 排序的延遲優化來加快 Elasticsearch 排序速度。 Elasticsearch 引入了大量新功能&#xff0c;幫助你為你的使用場景構建…

Nginx重定向協議沖突解決方案:The plain HTTP request was sent to HTTPS port

問題原因 ??服務器運行在 HTTPS 模式&#xff0c;但代碼卻發出了 HTTP 重定向指令&#xff0c;兩套協議對不上&#xff0c;瀏覽器直接報錯。?? 在Java中&#xff0c;常見于response.sendRedirect()方法的使用。該方法默認生成基于HTTP的絕對URL&#xff0c;即便原始請求是…