ZBLOG

#include typedef struct _Msg{ const char *src_file; const char *dest_file; int offset; int cp_len; }msg_t; //获取源文件大小,创建目标文件 int get_srcfile_len_and_create_destfile(const char *src_file, const char *dest_file){ //获...

你的代码是一个用于并行拷贝文件的C语言程序。它使用了多线程来实现文件拷贝的功能,将源文件分为两部分分别在两个线程中进行拷贝。以下是对这段代码的一些分析和可能需要注意的地方:

主要功能

  1. 获取源文件大小和创建目标文件get_srcfile_len_and_create_destfile函数打开源文件并计算其长度,然后创建目标文件。
  2. 并行拷贝copy_file函数在新线程中运行,用于从源文件读取数据并写入到目标文件。
  3. 多线程:主函数创建两个线程,每个线程负责拷贝一半的数据。

注意事项

  1. 错误处理

    • ERR_LOG宏未定义,建议添加相应的错误处理逻辑,比如打印错误信息或退出程序。
    • 检查所有系统调用(如 open, lseek, read, write, 和 pthread_create)返回值,并适当处理错误。
  2. 缓冲区大小

    • copy_file 中使用的缓冲区大小为10字节,这在性能上可能不够理想,可以根据需求增大这个值(例如1024字节)。
  3. 偏移量问题

    • 确保你正确地管理每个线程中的偏移量,以及数据写入时是否出现越界。
  4. 关闭文件描述符

    • 确保在任何情况下都能关闭打开的文件描述符,包括发生错误时。
  5. 内存管理

    • 虽然这里没有动态分配内存,但若将来有涉及,请确保正确释放资源以避免内存泄漏。
  6. 线程安全性

    • 在本例中,每个线程操作不同的数据块,因此不会出现竞争条件,但如果你扩展此代码,要注意共享资源的访问同步问题。
  7. 命令行参数检查

    • 目前只检查了参数数量,建议添加更详细的参数验证,例如检查输入路径是否有效等。

下面是对以上一些改进点做出具体修改后的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

#define ERR_LOG(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

typedef struct _Msg{
    const char *src_file;
    const char *dest_file;
    int offset;
    int cp_len;
}msg_t;

//获取源文件大小,创建目标文件
int get_srcfile_len_and_create_destfile(const char *src_file, const char *dest_file){
    //获取源文件大小
    int src_fd = open(src_file, O_RDONLY);
    if(-1 == src_fd)
        ERR_LOG("open error");
    
    int length = lseek(src_fd, 0, SEEK_END);
    close(src_fd);
    
    //创建目标文件
    int dest_fd = open(dest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if(-1 == dest_fd)
        ERR_LOG("create destination file error");
    
    close(dest_fd);
    
    return length;
}

//拷贝文件
void *copy_file(void *arg){
    msg_t *p = (msg_t *)arg;

    // 打开源和目标文件
    int src_fd = open(p->src_file, O_RDONLY);
    if(-1 == src_fd)
        ERR_LOG("open source file error");

    int dest_fd = open(p->dest_file, O_WRONLY);
    if(-1 == dest_fd)
        ERR_LOG("open destination file error");

    // 定位光标
    lseek(src_fd, p->offset, SEEK_SET);

    // 拷贝内容
    char buff[1024]; // 增加缓冲区大小,提高性能
	int total_copied = 0; 
	int nbytes;

	while ((nbytes = read(src_fd, buff, sizeof(buff))) > 0) {
		if (total_copied + nbytes > p->cp_len) {
			nbytes = p->cp_len - total_copied; // 限制写入字节数
		}
		write(dest_fd, buff, nbytes);
		total_copied += nbytes;

		if (total_copied >= p->cp_len) {
			break; // 达到复制要求,退出循环
		}
	}

	close(src_fd);
	close(dest_fd);

	return NULL; // 返回NULL表示正常结束
}

int main(int argc, const char *argv[]) {
	if(argc != 3){
	    printf("Usage : %s src_file dest_file\n", argv[0]);
	    exit(EXIT_FAILURE);
	}

	int length = get_srcfile_len_and_create_destfile(argv[1], argv[2]);

	msg_t tasks[2] = {
	    { .src_file = argv[1], .dest_file = argv[2], .offset = 0, .cp_len = length / 2 },
	    { .src_file = argv[1], .dest_file = argv[2], .offset = length / 2, .cp_len = length - (length / 2) }
	};

	pthread_t tid[2];

	for(int i=0; i<2; i++) {
	    if(pthread_create(&tid[i], NULL, copy_file, &tasks[i]) != 0) {
	        printf("pthread_create error: [%s]\n", strerror(errno));
	        exit(EXIT_FAILURE);
	    }
	}

	for(int i=0; i<2; i++) {
	    pthread_join(tid[i], NULL); // 等待每个线程结束
	}

	return EXIT_SUCCESS;
}

改动总结:

  • 增加了缓冲区大小,提高性能。
  • 错误处理进行了简化和统一。
  • 调整了一些细节以提高代码健壮性和可读性。


    内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=5846

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?