【练】创建两个线程:其中一个线程拷贝图片的前半部分,另一个线程拷贝后半部分

news2024/12/26 22:52:26

方法一:

        先在主函数创建并清空拷贝的目标文件,再创建两个线程,在两个线程内部同时打开要读取的文件以及要拷贝的目标文件(两个线程不共用同一份资源)。

使用到的函数:

  1. 标准IO函数(fprintf)【用于打印错误信息】
  2. 文件IO函数(open、close、lseek)
  3. 有关线程的函数(pthread_create、pthread_exit、pthread_join)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <head.h>
//线程的执行体
void* callback_1(void* arg)   //void* arg = (void*)&c
{
    umask(0);
    int fp_r=open("./1.png",O_RDONLY);                                               
    if(fp_r < 0)
    {
        ERR_MSG("open");
    }
    int fp_w=open("./copy.png",O_WRONLY);
    if(fp_w <0)
    {
        ERR_MSG("open");
    }
    char c = 0;
    off_t len=lseek(fp_r,0,SEEK_END);
    int i=0;
    lseek(fp_r,0,SEEK_SET);
    lseek(fp_w,0,SEEK_SET);
    for(i=0;i<len/2;i++)
    {
        bzero(&c,sizeof(c));
        read(fp_r,&c,1);
        write(fp_w,&c,1);
    }

    close(fp_r);
    close(fp_w);

    printf("前半部分拷贝完毕\n");
    pthread_exit(NULL);
}
void* callback_2(void* arg)
{
    umask(0);
    int fp_r=open("./1.png",O_RDONLY);
    if(fp_r < 0)
    {
        ERR_MSG("open");
    }
    int fp_w=open("./copy.png",O_WRONLY);
    if(fp_w < 0)
    {
        ERR_MSG("open");
    }
    char c = 0;
    off_t len=lseek(fp_r,0,SEEK_END);
    int i=0;
    lseek(fp_r,len/2,SEEK_SET);
    lseek(fp_w,len/2,SEEK_SET);
    for(i=0;i<len/2;i++)
    {
        bzero(&c,sizeof(c));
        read(fp_r,&c,sizeof(c));
        write(fp_w,&c,sizeof(c));
    }

    close(fp_r);
    close(fp_w);
    printf("后半部分拷贝完毕\n");
    pthread_exit(NULL);

}
int main(int argc, const char *argv[])
{
    //两个线程在拷贝前,确保文件w存在,且是清空状态
    int fp_w=open("./copy.png",O_WRONLY|O_CREAT|O_TRUNC,0664);
    if(fp_w <0)
    {
        ERR_MSG("open");
    }
    close(fp_w);

    pthread_t tid_1,tid_2;
    if(pthread_create(&tid_1,NULL,callback_1,NULL) != 0)
    {
        fprintf(stderr, "pthread_create failed __%d__\n",__LINE__);
        return -1;
    }

    pthread_join(tid_1,NULL);

    if(pthread_create(&tid_2,NULL,callback_2,NULL)!=0)
    {
        fprintf(stderr, "pthread_create failed __%d__\n",__LINE__);
        return -1;
    }

    pthread_join(tid_2,NULL);
    printf("主线程准备退出... ...\n");
    return 0;
}
                                                                                     
                                                                                    

方法二:

        创建一个结构体用于存放需要打开的两个文件文件标识符、需要拷贝的字节大小。

        在主函数中打开两个文件,计算好需要拷贝的字节大小,再创建两个线程,将结构体fileinfo的地址传递到线程中(强转成(void*)类型再传,否则报错),线程中用指针void* arg接fileinfo的地址。线程中需要将指针arg的地址转为struct Msg类型。

        PS:两个线程共享同一份资源,使用pthread_exit函数使线程1先完成拷贝(与sleep达到的效果一致)。

使用到的函数:

  1. 结构体struct
  2. 标准IO函数(fprintf)【用于打印错误信息】
  3. 文件IO函数(open、close、lseek)
  4. 有关线程的函数(pthread_create、pthread_exit、pthread_join)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <head.h>
struct Msg
{
	int fp_r;
	int fp_w;
	off_t size;
};
//线程1的执行体:拷贝前半部分
void* callback_1(void* arg)   //void* arg = &fileinfo
{
	struct Msg *tp=(struct Msg*)arg;
	int fp_r=tp->fp_r;
	int fp_w=tp->fp_w;
	off_t size=tp->size;
	
	//将光标偏移到开头,拷贝size/2个字节到目标文件中
	lseek(fp_r,0,SEEK_SET);
	lseek(fp_w,0,SEEK_SET);
	char c = 0;
	for(int i=0;i<size/2;i++)
	{
		bzero(&c,sizeof(c));
		read(fp_r,&c,1);
		write(fp_w,&c,1);
	}
	printf("前半部分拷贝完毕\n");
	pthread_exit(NULL);//退出分支线程
}
//线程2的执行体
void* callback_2(void* arg)  //void* arg = &fileinfo
{
	//sleep(5);//主动放弃cpu资源,让线程1先执行
	struct Msg *tp=(struct Msg*)arg;
	int fp_r=tp->fp_r;
	int fp_w=tp->fp_w;
	off_t size=tp->size;

	//将光标偏移到size/2的位置,拷贝size/2个字节到目标文件中
	lseek(fp_r,size/2,SEEK_SET);
	lseek(fp_w,size/2,SEEK_SET);
	char c = 0;
	for(int i=0;i<size/2;i++)
	{
		bzero(&c,sizeof(c));
		read(fp_r,&c,sizeof(c));
		write(fp_w,&c,sizeof(c));
	}
	printf("后半部分拷贝完毕\n");
	pthread_exit(NULL);//退出分支线程
}
int main(int argc, const char *argv[])
{
	struct Msg fileinfo;
	//以读的方式打开1.png
	fileinfo.fp_r=open("./1.png",O_RDONLY);
	if(fileinfo.fp_r < 0)
	{
		ERR_MSG("open");
		return -1;
	}
	//以写的方式打开并创建(若存在则清空)copy.png
	fileinfo.fp_w=open("./copy.png",O_WRONLY|O_CREAT|O_TRUNC,0664);
	if(fileinfo.fp_w <0)
	{
		ERR_MSG("open");
		return -1;
	}
	//计算需要拷贝的字节大小
	fileinfo.size=lseek(fileinfo.fp_r,0,SEEK_END);

	//创建2个线程
	pthread_t tid_1,tid_2;
	if(pthread_create(&tid_1,NULL,callback_1,(void *)&fileinfo) != 0)
	{
		fprintf(stderr, "pthread_create failed __%d__\n",__LINE__);
		return -1;
	}
	pthread_join(tid_1,NULL);//阻塞等待线程1完成

	if(pthread_create(&tid_2,NULL,callback_2,(void *)&fileinfo) !=0)
	{
		fprintf(stderr, "pthread_create failed __%d__\n",__LINE__);
		return -1;
	}
	pthread_join(tid_2,NULL);//阻塞等待线程2完成

	//关闭文件
	close(fileinfo.fp_r);
	close(fileinfo.fp_w);
	printf("主线程准备退出\n");
	return 0;
}

方法三:

       创建一个结构体用于存放需要打开的两个文件文件标识符、需要拷贝的字节大小。

        PS:两个线程共享同一份资源,利用互斥锁完成任务。

使用到的函数:

  1. 结构体struct
  2. 标准IO函数(fprintf)【用于打印错误信息】
  3. 文件IO函数(open、close、lseek)
  4. 有关线程的函数(pthread_create、pthread_exit、pthread_join)
  5. 互斥锁(创建互斥锁pthread_mutex_init、上锁pthread_mutex_lock、解锁pthread_mutex_unlock、销毁互斥锁pthread_mutex_destroy)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <head.h>
//临界资源
struct Msg
{
	int fp_r;
	int fp_w;
	off_t size;
	pthread_mutex_t mutex;//互斥锁
};
//线程1的执行体:拷贝前半部分
void* callback_1(void* arg)   //void* arg = &fileinfo
{
	struct Msg *fileinfo=(struct Msg*)arg;

	/************************临界区***************************/
	//上锁
	pthread_mutex_lock(&fileinfo->mutex);

	int fp_r=fileinfo->fp_r;
	int fp_w=fileinfo->fp_w;
	off_t size=fileinfo->size;

	
	//将光标偏移到开头,拷贝size/2个字节到目标文件中
	lseek(fp_r,0,SEEK_SET);
	lseek(fp_w,0,SEEK_SET);
	char c = 0;
	for(int i=0;i<size/2;i++)
	{
		bzero(&c,sizeof(c));
		read(fp_r,&c,1);
		write(fp_w,&c,1);
	}
	printf("前半部分拷贝完毕\n");
	
	//解锁
	pthread_mutex_unlock(&fileinfo->mutex);
	/************************临界区***************************/
	pthread_exit(NULL);//退出分支线程
}
//线程2的执行体
void* callback_2(void* arg)  //void* arg = &fileinfo
{
	struct Msg *fileinfo=(struct Msg*)arg;
	/************************临界区***************************/
	//上锁
	pthread_mutex_lock(&fileinfo->mutex);

	int fp_r=fileinfo->fp_r;
	int fp_w=fileinfo->fp_w;
	off_t size=fileinfo->size;

	//将光标偏移到size/2的位置,拷贝size/2个字节到目标文件中
	lseek(fp_r,size/2,SEEK_SET);
	lseek(fp_w,size/2,SEEK_SET);
	char c = 0;
	for(int i=0;i<size/2;i++)
	{
		bzero(&c,sizeof(c));
		read(fp_r,&c,sizeof(c));
		write(fp_w,&c,sizeof(c));
	}
	printf("后半部分拷贝完毕\n");
	//解锁
	pthread_mutex_unlock(&fileinfo->mutex);
	/************************临界区***************************/
	pthread_exit(NULL);//退出分支线程
}
int main(int argc, const char *argv[])
{
	struct Msg fileinfo;
	//以读的方式打开1.png
	fileinfo.fp_r=open("./1.png",O_RDONLY);
	if(fileinfo.fp_r < 0)
	{
		ERR_MSG("open");
		return -1;
	}
	//以写的方式打开并创建(若存在则清空)copy.png
	fileinfo.fp_w=open("./copy.png",O_WRONLY|O_CREAT|O_TRUNC,0664);
	if(fileinfo.fp_w <0)
	{
		ERR_MSG("open");
		return -1;
	}
	//计算需要拷贝的字节大小
	fileinfo.size=lseek(fileinfo.fp_r,0,SEEK_END);
	//申请一个互斥锁
	pthread_mutex_init(&fileinfo.mutex,NULL);
	
	//创建2个线程
	pthread_t tid_1,tid_2;
	if(pthread_create(&tid_1,NULL,callback_1,(void *)&fileinfo) != 0)
	{
		fprintf(stderr, "pthread_create failed __%d__\n",__LINE__);
		return -1;
	}
	pthread_detach(tid_1);  //分离线程1
 
	if(pthread_create(&tid_2,NULL,callback_2,(void *)&fileinfo) !=0)
	{
		fprintf(stderr, "pthread_create failed __%d__\n",__LINE__);
		return -1;
	}
	pthread_join(tid_2,NULL);//阻塞等待线程2完成
 
	//关闭文件
	close(fileinfo.fp_r);
	close(fileinfo.fp_w);
	printf("主线程准备退出\n");
	//销毁互斥锁
	pthread_mutex_destroy(&fileinfo.mutex);
	return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/831784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(数据库系统概论|王珊)第一章绪论-第一节:数据库系统概论

目录 一&#xff1a;四大基本概念 &#xff08;1&#xff09;数据(Data) &#xff08;2&#xff09;数据库(DataBase,DB) &#xff08;3&#xff09;数据库管理系统(DataBase Management System,DBMS) &#xff08;4&#xff09;数据库系统(Database System&#xff0c;DBS…

HBN:2023年原生白护肤白皮书(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 调研数据表明&#xff0c;近九成的消费者对自己肤色不满&#xff0c;其中偏黄、偏黑是大家的核心困扰&#xff08;图1-1&#xff09;。在此情况下&#xff0c;“美白” 在各社媒平台的搜素量近年来一…

开利网络受邀出席数利丰应用研讨会 分享企业数字化转型落地经验

数利丰应用研讨会在广州举办。本次研讨会的主题为「聚焦数据价值&#xff0c;引领数字转型」。 广州市开利网络科技有限公司总经理、和合生态联合发起人付立军先生受邀出席研讨会并同在座40余国内外企业创始人与高管共同探讨企业经营所面临的共性问题&#xff0c;分享在企业数…

【力扣】19. 删除链表的倒数第 N 个结点 <链表指针、快慢指针>

【力扣】19. 删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;head [1], n…

【java安全】原生反序列化利用链JDK7u21

文章目录 【java安全】原生反序列化利用链JDK7u21前言原理equalsImpl()如何调用equalsImpl()&#xff1f;HashSet通过反序列化间接执行equals()方法如何使hash相等&#xff1f; 思路整理POCGadget为什么在HashSet#add()前要将HashMap的value设为其他值&#xff1f; 【java安全】…

毫米波雷达 TI IWR6843 官方测试程序(Out Of Box Demo)

1.硬件准备 1.IWR6843AOP板子 2.两个USB转串口模块&#xff08;因为我的是自己做的板子&#xff0c;板子上没有集成USB转串口芯片&#xff09; 2.软件准备 1.最新版本的CCS&#xff0c;注意后缀没有THEIA https://www.ti.com/tool/CCSTUDIO?DCMPdsp_ccs_v4&HQSccs 2.最…

PageObjects支持库-Poium使用方法

PO模式 学过自动化的都知道PageObjects模式&#xff0c;将页面对象封装为类&#xff0c;页面元素和操作封装为类的属性和方法&#xff0c;在测试方法中调用页面对象进行测试。 关于PO模式可见&#xff1a;http://t.csdn.cn/0DBlP 在PO模式下&#xff0c;我们一般定义个一个基…

MacOS上用docker运行mongo及mongo-express

MongoDB简介 MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。 前提 要求…

蓝牙资讯|苹果智能戒指专利曝光,可与苹果智能设备进行交互

根据美国商标和专利局&#xff08;USPTO&#xff09;公示的清单&#xff0c;苹果获得了一项智能戒指专利&#xff0c;可以作为 MacBook、电视、AirPods、智能眼镜和 iPhone 等设备的输入交互设备。 苹果在专利中展示了 16 种智能戒指的交互方式&#xff0c;其中图 2 展示了该…

Python高阶技巧 正则表达式

正则表达式&#xff0c;又称规则表达式&#xff08;Regular Expression&#xff09;&#xff0c;是使用单个字符串来描述、匹配某个句法规则的字符串&#xff0c;常被用来检索、替换那些符合某个模式&#xff08;规则&#xff09;的文本。 简单来说&#xff0c;正则表达式就是使…

大模型系列|基于大模型复杂数据系统架构(二)

张俊林老师在 2023 WAIC AI 开发者论坛的演讲非常有概括性&#xff0c;这边沿着思路进行一定的整理。&#xff08;文章来源&#xff1a;WAIC 2023 | 张俊林&#xff1a;大语言模型带来的交互方式变革&#xff09; 文章目录 1 PlanningProgramming 模式的系统技术架构2 HuggingG…

运维:18工作中常用 Shell 脚本, 强烈推荐

1、检测两台服务器指定目录下的文件一致性 #!/bin/bash ###################################### 检测两台服务器指定目录下的文件一致性 ##################################### #通过对比两台服务器上文件的md5值,达到检测一致性的目的 dir=/data/web b_ip=192…

el-popover使用自定义图标

使用el-popover实现鼠标点击或浮动到自定义图标上弹出表格弹窗&#xff0c;官方文档上使用的是按钮el-button&#xff0c;如果想换成图标或其他的组件的话直接把el-button替换掉即可。注意替换之后的组件一定要加slot“reference”&#xff0c;不然组件是显示不出来的。 代码如…

数据可视化(六)多个子图及seaborn使用

1.多个子图绘制 #绘制多个子图 #subplot&#xff08;*args&#xff0c;**kwargs&#xff09; 每个subplot函数只能绘制一个子图 #subplots&#xff08;nrows&#xff0c;ncols&#xff09; #fig_add_subplot(行&#xff0c;列&#xff0c;区域) #绘制子图第一种方式 plt.subp…

qq邮箱 会自动拦截 github 邮件,醉了!

今天登录Github&#xff0c;修改密码&#xff0c;qq邮箱一直收不到Github的邮件 打开自助查询一看&#xff0c;自助查询在右边栏 为什么steam登陆 qq邮箱收不到验证码了&#xff1f; - 知乎 点击左上角设置&#xff0c;点击反垃圾&#xff0c;点击设置右键地址白名单 然后就可…

恒运资本:满仓的含义?

满仓&#xff0c;望文生义&#xff0c;便是财经领域中的一个术语。它指的是出资者将一切可用资金悉数用于购买股票、基金或其他金融资产。满仓的意义是出资者对某种出资产品充满决心&#xff0c;并乐意将自己的大部分资金投入其中&#xff0c;以希望取得更高的报答。但是&#…

Mongodb安装(Centos7)

1. 下载 MongoDB: The Developer Data Platform | MongoDB 2. 安装 上传至服务器 解压 tar -zxvf mongodb-linux-x86_64-rhel70-5.0.19.tgz 移动 mv mongodb-linux-x86_64-rhel70-5.0.19 /usr/local/mongodb 3. 配置 vim /etc/profile # set mongodb configuration expor…

shell centos 7 一键部署 KVM软件脚本

这个脚本有限地方还需要完善下 设计思路&#xff1a; 1、创建检查内核函数 check_kernel() 2、创建升级内核函数 update_kernel() 3、创建检查是否支持虚拟化函数 check_virtual() 4、创建检查操作系统函数 check_system() 5、创建检查网络函数 check_network() 6…

安防视频汇聚平台EasyCVR视频广场面包屑侧边栏支持拖拽操作

智能视频监控平台EasyCVR能在复杂的网络环境中&#xff0c;将海量设备实现集中统一接入与汇聚管理&#xff0c;实现视频的处理与分发、录像与存储、按需调阅、平台级联等。 TSINGSEE青犀视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协…

实例029 半透明渐显窗体

实例说明 很多专业软件在启动前都会显示一个说明该软件信息或用途的窗口&#xff0c;有的则是一个漂亮的启动界面&#xff0c;如Adobe公司的Acrobat。该窗口使软件显得更加专业。本例将实现一个半透明的渐显窗体&#xff0c;运行本软件会显示一个启动画面&#xff0c;并且画面…