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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;即便原始请求是…