2024.10.18 IO多线程编程练习

使用多线程完成两个文件的拷贝,分支线程1,拷贝前一半,分支线程2拷贝后一半,主线程用于回收分支线程的资源

#include <myhead.h>

//声明全局变量
pthread_mutex_t mutex; //互斥锁
int source = -1;       //源文件描述符 
int dest = -1; 		   //目标文件描述符
int len = 0;   		   //源文件总长度
int half_len = 0; 	   //源文件的一半长度

//线程1 负责拷贝源文件的前半部分
void *task1(void *arg)
{
	char rbuf[128] = "";         //用于存储读取的数据的缓冲区
	lseek(source, 0, SEEK_SET);  //设置源文件指针到文件开头
	int sum = 0;                 //设置读取的字节总数

	while(sum < half_len)        //循环读取直到读取的字节数达到文件的一半
	{
		pthread_mutex_lock(&mutex); //加锁 防止其他线程干扰文件操作
		int res = read(source, rbuf, sizeof(rbuf)); //读取数据到缓冲区 
		if(res == 0) //如果读取到文件末尾 退出循环
		{
			pthread_mutex_unlock(&mutex); //解锁 
			break;
		}
		sum += res; //更新已读取的字节总数

		if(sum > half_len) //如果超过文件的一半 仅写入多余部分 避免越界写入
		{
			write(dest, rbuf, res - (sum - half_len)); //写入目标文件的剩余部分
		}
		else
		{
			write(dest, rbuf, res); //写入读取的完整数据
		}

		pthread_mutex_unlock(&mutex); //解锁 允许其他线程操作
	}

	pthread_exit(NULL); //线程结束
}

//线程2 负责拷贝源文件的后半部分
void *task2(void *arg)
{
	char rbuf[128] = ""; //用于存储读取的数据的缓冲区
	lseek(source, half_len, SEEK_SET); //设置源文件指针到文件的中间位置
	int res;

	while(1)
	{
		pthread_mutex_lock(&mutex); //加锁 防止其他线程干扰文件操作 
		res = read(source, rbuf, sizeof(rbuf)); //读取数据到缓冲区
		if(res == 0) //如果读取到文件末尾 退出循环
		{
			pthread_mutex_unlock(&mutex); //解锁
			break;
		}
		write(dest, rbuf, res); //将读取的数据写入目标文件
		pthread_mutex_unlock(&mutex); //解锁,允许其他线程操作
	}

	pthread_exit(NULL); //线程结束
}

int main(int argc, const char *argv[])
{
	pthread_mutex_init(&mutex, NULL); //初始化互斥锁

	//打开源文件 只读模式
	if((source=open("./source.txt",O_RDONLY))==-1)
	{
		perror("open source error"); //打开失败 输出错误信息
		return -1;
	}

	//打开目标文件 写模式 如果不存在则创建 存在则清空内容 
	if((dest = open("dest.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664)) == -1)
	{
		perror("open dest error"); //打开失败,输出错误信息
		close(source); //关闭已打开的源文件
		return -1;
	}

	//获取源文件的长度 
	len = lseek(source, 0, SEEK_END);
	if(len == -1)
	{
		perror("lseek error"); //获取文件长度失败 输出错误信息
		close(source); //关闭源文件
		close(dest); //关闭目标文件
		return -1;
	}

	//计算源文件的一半长度
	half_len = (len + 1) / 2;

	//创建线程1 负责拷贝前半部分
	pthread_t tid1, tid2;
	if(pthread_create(&tid1, NULL, task1, NULL) != 0)
	{
		printf("tid1 create error\n");
		return -1;
	}

	//创建线程2 负责拷贝后半部分
	if(pthread_create(&tid2, NULL, task2, NULL) != 0)
	{
		printf("tid2 create error\n");
		return -1;
	}

	//打印线程的ID 便于调试 
	printf("tid1 = %#lx, tid2 = %#lx\n", tid1, tid2);

	//等待线程1 线程2 执行结束
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);

	pthread_mutex_destroy(&mutex); //销毁互斥锁

	close(source); //关闭源文件
	close(dest); //关闭目标文件

	printf("拷贝成功\n"); 

	return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值