每天十分钟真的能改变健康吗

在Linux系统中,cp命令用于复制文件或目录,本文将详细讲解如何用C语言实现基础的文件复制功能(仅限单个文件),涵盖核心系统调用、错误处理及代码实现。


实现原理

Linux的cp命令本质是完成以下操作:

  1. 打开源文件(source)
  2. 创建目标文件(destination)
  3. 从源文件读取数据
  4. 将数据写入目标文件
  5. 处理错误并关闭文件

涉及关键系统调用:

  • open():打开/创建文件
  • read():读取文件内容
  • write():写入数据
  • close():关闭文件描述符

完整代码实现

#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define BUFFER_SIZE 4096  // 高效读写缓冲区大小
int main(int argc, char *argv[]) {
    // 参数校验
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <source> <destination>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    int src_fd, dst_fd;
    ssize_t bytes_read;
    char buffer[BUFFER_SIZE];
    // 1. 打开源文件 (只读模式)
    src_fd = open(argv[1], O_RDONLY);
    if (src_fd == -1) {
        perror("Error opening source file");
        exit(EXIT_FAILURE);
    }
    // 2. 创建目标文件 (读写模式 | 创建新文件 | 截断已存在文件)
    dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (dst_fd == -1) {
        perror("Error creating destination file");
        close(src_fd);  // 关闭已打开的源文件
        exit(EXIT_FAILURE);
    }
    // 3. 循环读写数据
    while ((bytes_read = read(src_fd, buffer, BUFFER_SIZE)) > 0) {
        ssize_t bytes_written = write(dst_fd, buffer, bytes_read);
        if (bytes_written != bytes_read) {
            perror("Write error");
            close(src_fd);
            close(dst_fd);
            exit(EXIT_FAILURE);
        }
    }
    // 4. 检查读取错误
    if (bytes_read == -1) {
        perror("Read error");
        close(src_fd);
        close(dst_fd);
        exit(EXIT_FAILURE);
    }
    // 5. 关闭文件描述符
    if (close(src_fd) == -1) perror("Close source error");
    if (close(dst_fd) == -1) perror("Close destination error");
    printf("File copied successfully!\n");
    return EXIT_SUCCESS;
}

关键代码解析

  1. 参数验证
    argc != 3 确保用户输入源文件和目标文件路径。

  2. 文件打开模式

    • 源文件:O_RDONLY(只读)
    • 目标文件:
      O_WRONLY(只写)
      O_CREAT(不存在则创建)
      O_TRUNC(存在则清空)
      0644(文件权限:用户读写,组和其他只读)
  3. 高效读写循环

    • BUFFER_SIZE=4096 匹配磁盘块大小,减少系统调用次数
    • read()返回实际读取字节数,write()确保写入等量数据
  4. 错误处理

    • 所有系统调用后检查返回值
    • perror()输出具体错误原因
    • 失败时关闭已打开的文件描述符

功能局限性说明

当前实现为基础版本,与系统cp命令相比:

  1. 不支持目录复制
    需使用opendir()/readdir()递归处理
  2. 不保留元数据
    如权限、时间戳需额外调用fchmod()/futimens()
  3. 无符号链接处理
    需使用lstat()判断文件类型
  4. 无大文件支持
    超过2GB文件需定义_FILE_OFFSET_BITS=64

扩展建议

  1. 添加目录支持

    #include <dirent.h>
    #include <sys/stat.h>

    递归遍历目录,对每个文件调用复制函数。

  2. 保留文件属性

    struct stat src_stat;
    fstat(src_fd, &src_stat);  // 获取元数据
    fchmod(dst_fd, src_stat.st_mode);  // 复制权限
  3. 进度显示
    通过lseek()获取文件大小,计算并打印复制进度百分比。


编译与测试

  1. 编译代码:
    gcc my_cp.c -o my_cp
  2. 测试复制:
    ./my_cp source.txt destination.txt
  3. 验证结果:
    diff source.txt destination.txt  # 无输出表示内容一致

本文实现的C语言版cp命令覆盖了文件复制的核心逻辑,通过系统级I/O操作实现高效数据传输,实际开发中可逐步添加目录处理、权限保留等进阶功能,完整代码已通过GCC编译测试,适用于Linux环境下的基础文件操作场景。

引用说明
本文代码基于Linux POSIX标准系统调用实现,参考《Advanced Programming in the UNIX Environment》(Richard Stevens著)中文件I/O操作规范,错误处理遵循IEEE Std 1003.1-2017标准。

原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/7566.html

(0)
酷番叔酷番叔
上一篇 4天前
下一篇 4天前

相关推荐

  • 如何在不同系统打开终端?

    Windows系统命令提示符(CMD)快捷键:Win + R → 输入 cmd → 回车搜索栏:点击任务栏搜索图标 → 输入“命令提示符” → 选择应用文件管理器:打开任意文件夹 → 地址栏输入 cmd → 回车(直接定位当前路径)PowerShell(更强大的替代品)开始菜单右键 → 选择“Windows P……

    2025年7月13日
    1100
  • 如何定义编译器和参数?

    在软件开发中,make命令是自动化构建项目的核心工具,它通过读取Makefile文件中的指令,智能编译源代码、管理依赖关系并执行复杂任务,以下是根据Linux基金会文档和GNU Make手册整理的权威执行指南:环境准备(安装make)Linux系统终端执行:sudo apt update &&amp……

    2025年7月4日
    1500
  • Shell中let命令如何传递算术结果?

    算术结果:通过变量赋值存储退出状态码:表示运算的真假性(非0为真,0为假)let如何”返回值”?算术结果通过变量传递let将计算结果直接赋给变量,而非打印到终端,示例:let "sum=5+3" # 计算5+3,结果存入变量sumecho $sum # 输出8退出状态码表示逻辑真假规则:若计……

    2025年7月5日
    1000
  • 路由命令添加网关如何操作?

    网关的作用网关(Gateway)是不同网络间的“出口”,当设备需访问其他网段(如互联网)时,数据会先发送到网关,再由网关转发,添加路由网关可手动指定特定流量的传输路径,Windows 系统添加网关临时添加(重启失效)打开命令提示符(管理员权限)Win + R 输入 cmd → 右键选择“以管理员身份运行”,添加……

    2025年7月5日
    1000
  • 如何快速修改CAD命令?

    在AutoCAD中修改命令别名(即命令行快捷指令)是提升设计效率的关键技巧,以下提供两种主流方法,均通过AutoCAD官方功能实现,操作前请务必备份文件以防误操作,通过自定义界面修改(推荐初学者)步骤详解:打开自定义设置命令行输入 CUI → 回车 → 弹出【自定义用户界面】对话框定位命令别名文件左侧面板展开……

    2025年6月14日
    1300

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信