1
2
3
#include <stdio.h> // 标准输入输出函数(如perror)
#include <stdlib.h> // 标准库函数(如exit)
#include <unistd.h> // POSIX API(fork, read, write, lseek等)
#include <sys/stat.h> // 文件状态获取(stat)
#include <fcntl.h> // 文件控制选项(open的flags定义)
#include <sys/wait.h> // 进程等待函数(wait)
#define BUF_SIZE 4096 // 文件读写缓冲区大小(4KB块大小优化磁盘IO)
#define SOURCE_FILE "./1.png" // 硬编码源文件路径
#define DEST_FILE "./2.png" // 硬编码目标文件路径
int main() {
struct stat st; // 文件状态结构体
int src_fd, dest_fd; // 文件描述符(源文件/目标文件)
/*-- 获取源文件信息 --*/
if (stat(SOURCE_FILE, &st) { // 获取文件元数据
perror("stat failed");
exit(EXIT_FAILURE); // 错误时直接终止程序
}
off_t total_size = st.st_size; // 文件总字节数
off_t half_size = total_size / 2;// 分割点(整型除法自动取整)
/*-- 创建/清空目标文件 --*/
dest_fd = open(DEST_FILE, O_WRONLY | O_CREAT |O_TRUNC,0644);
if (dest_fd == -1) {
perror("open dest failed");
exit(EXIT_FAILURE);
}
/*-- 创建子进程 --*/
pid_t pid = fork();
if (pid == -1) { // fork失败处理
perror("fork failed");
close(dest_fd); // 关闭已打开的文件描述符
exit(EXIT_FAILURE);
}
if (pid > 0) { // 父进程分支:负责前半段拷贝
/*-- 父进程打开源文件 --*/
src_fd = open(SOURCE_FILE, O_RDONLY); // 只读模式打开
if (src_fd == -1) {
perror("open source failed");
close(dest_fd);
exit(EXIT_FAILURE);
}
/*-- 分块拷贝逻辑 --*/
char buf[BUF_SIZE]; // IO缓冲区
off_t bytes_copied = 0; // 已拷贝字节计数器
while (bytes_copied < half_size) {
// 计算本次读取量(避免最后一块超出half_size)
ssize_t to_read = (half_size - bytes_copied > BUF_SIZE)
? BUF_SIZE
: half_size - bytes_copied;
// 读取源文件数据
ssize_t nread = read(src_fd, buf, to_read);
if (nread <= 0) break; // 读错误或EOF时终止
// 写入目标文件(注意:父进程始终从文件头开始顺序写入)
ssize_t nwrite = write(dest_fd, buf, nread);
if (nwrite != nread) { // 写入量不匹配时报错
perror("parent write failed");
break;
}
bytes_copied += nread; // 更新进度
}
/*-- 收尾工作 --*/
close(src_fd); // 关闭源文件
wait(NULL); // 等待子进程退出
close(dest_fd); // 关闭目标文件
/*-- 文件校验 --*/
printf("Verifying...\n");
// 使用system调用diff命令,-q参数只报告是否不同
int diff_ret = system("diff -q " SOURCE_FILE " " DEST_FILE);
if (diff_ret == 0) { // diff返回0表示文件相同
printf("Files are identical\n");
} else { // 非零返回值表示差异
printf("Files differ!\n");
}
}
else { // 子进程分支:负责后半段拷贝
/*-- 子进程打开源文件 --*/
src_fd = open(SOURCE_FILE, O_RDONLY);
if (src_fd == -1) {
perror("child open source failed");
exit(EXIT_FAILURE);
}
/*-- 子进程独立打开目标文件 --*/
int child_dest = open(DEST_FILE, O_WRONLY); // 必须重新打开以避免共享文件指针
if (child_dest == -1) {
perror("child open dest failed");
close(src_fd);
exit(EXIT_FAILURE);
}
/*-- 定位到分割点 --*/
// 将源文件指针移动到中间位置
lseek(src_fd, half_size, SEEK_SET); // SEEK_SET表示基于文件头偏移
// 将目标文件指针同步移动到中间位置
lseek(child_dest, half_size, SEEK_SET);
/*-- 拷贝剩余数据 --*/
char buf[BUF_SIZE];
ssize_t nread;
while ((nread = read(src_fd, buf, BUF_SIZE)) > 0) { // 循环直到EOF
ssize_t nwrite = write(child_dest, buf, nread);
if (nwrite != nread) { // 写入完整性检查
perror("child write failed");
break;
}
}
/*-- 收尾工作 --*/
close(src_fd); // 关闭源文件
close(child_dest); // 关闭目标文件
exit(EXIT_SUCCESS); // 子进程正常退出
}
return 0;
}