进程-调度

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值