你的代码是一个用于并行拷贝文件的C语言程序。它使用了多线程来实现文件拷贝的功能,将源文件分为两部分分别在两个线程中进行拷贝。以下是对这段代码的一些分析和可能需要注意的地方:
主要功能
- 获取源文件大小和创建目标文件:get_srcfile_len_and_create_destfile函数打开源文件并计算其长度,然后创建目标文件。
- 并行拷贝:copy_file函数在新线程中运行,用于从源文件读取数据并写入到目标文件。
- 多线程:主函数创建两个线程,每个线程负责拷贝一半的数据。
注意事项
- 错误处理: - ERR_LOG宏未定义,建议添加相应的错误处理逻辑,比如打印错误信息或退出程序。
- 检查所有系统调用(如 open,lseek,read,write, 和pthread_create)返回值,并适当处理错误。
 
- 缓冲区大小: - 在 copy_file中使用的缓冲区大小为10字节,这在性能上可能不够理想,可以根据需求增大这个值(例如1024字节)。
 
- 在 
- 偏移量问题: - 确保你正确地管理每个线程中的偏移量,以及数据写入时是否出现越界。
 
- 关闭文件描述符: - 确保在任何情况下都能关闭打开的文件描述符,包括发生错误时。
 
- 内存管理: - 虽然这里没有动态分配内存,但若将来有涉及,请确保正确释放资源以避免内存泄漏。
 
- 线程安全性: - 在本例中,每个线程操作不同的数据块,因此不会出现竞争条件,但如果你扩展此代码,要注意共享资源的访问同步问题。
 
- 命令行参数检查: - 目前只检查了参数数量,建议添加更详细的参数验证,例如检查输入路径是否有效等。
 
下面是对以上一些改进点做出具体修改后的示例代码:
#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助手提供,问题来源于学员提问


 
                             
         
        
 
         
         
         
         
         
         
        
 
                 
                 
                 
                 
                 
                 
                 
                 
                