Linux学习日记5:CP指令的实现
本文介绍了Linux系统中的CP指令实现原理。首先讲解了main函数参数argc和argv[]的作用,为理解CP指令参数处理打下基础。然后详细说明了CP指令的基本语法、常用选项以及不同场景下的复制行为准则。最后通过代码示例展示了CP指令的实现流程:通过open函数打开源文件和目标文件,使用read/write函数循环读写数据,并最终关闭文件描述符。文章提供了一个完整的文件复制程序实现,验证了其功能
一、前言
前面我们学习了lseek函数的基本用法,今天我们来学习CP指令的相关知识。
二、main函数参数
在学习CP指令之前,我们先来学习一下main函数参数的相关知识,有助于我们刚好地了解CP指令。
1、main函数参数介绍
int main(int argc, char *argv[])
{
return 0;
}
C语言规定了main函数的参数只能有两个,一个是argc,一个是argv,其中,argc表示命令行的参数个数, argv表示指向字符串数组的指针,每个字符串表示一个命令行参数,比如argv[0]表示第一个参数——指向程序的名称(或路径),比如运行./a,out时, argv[0]表示“./a,out”,若通过绝对路径/usr/bin/a.out时,则argv[0]表示“/usr/bin/a.out”;argv[1]到argv[argc-1]表示依次指向用户传递的额外参数,比如./a.out a b中,argv[1]=“a”,argv[2]=“b”;argv[argc]固定为NULL指针,作为数组的结束标志。
2、示例
先创建一个文件test.c

写入以下代码:
#include<stdio.h>
int main(int argc,char*argv[])
{
printf("total is %d\n",argc);
printf("first is %d\n",argv[0]);
printf("second is %d\n",argc[1]);
printf("third is %d\n",argc[2]);
return 0;
}
然后使用gcc编译器进行编译,生成默认文件a.out,然后运行:
可以看到第一个程序时./a.out,第二个是参数是a,第三个参数是b;
这里可以看到最后一个参数是null。
三、CP指令
1、定义
在Linux系统中,CP是是最常用的文件管理命令之一,用于复制文件或目录。它的核心功能是将一个或多个 “源” 文件 / 目录复制到指定的 “目标” 位置,支持灵活的复制策略(如保留文件属性、递归复制目录、交互式操作等)。
2、基本语法
cp [选项] 源文件/目录... 目标文件/目录
其中,源可以是一个或多个文件 / 目录(用空格分隔);目标是复制的终点,可以是文件仅当源为单个文件时)或目录(当源为多个文件 / 目录,或需要将源放入目标目录时)。
3、常用选项
cp支持大量选项,以下是常用的选项(可组合使用,如cp -iv):

4、核心行为准则
cp的行为会根据“源”和 “目标” 的类型(文件 / 目录)而变化,核心规则如下:
1、源是单个文件,目标是文件:
若目标文件不存在:创建目标文件,并将源文件内容复制到其中(文件名由目标指定);
若目标文件已存在:默认直接覆盖(用 -i 选项可进行提示是否选择覆盖);
2、源是单个文件,目标是目录:
若目标目录存在:将源文件复制到该目录下,文件名保持不变;
若目标目录不存在:会进行报错;
3、源是多个文件,目标必须是目录:
所有源文件会被复制到该目录下,文件名保持不变。若目标目录不存在,直接报错。
4、源是目录,目标必须是目录:
必须使用 -r(或 -R)选项进行递归复制,否则会报错;
若目标目录不存在:创建目标目录,并将源目录下的所有内容(包括子目录、文件)复制到其中;
若目标目录已存在:将源目录整体复制到目标目录下(即目标目录中会新增一个与源目录同名的子目录)。
5、实现CP指令的基本流程
在上面我们介绍了很多关于CP指令的内容,那么CP指令在Linux系统中是怎么工作的呢?基本流程是什么?
假设要复制源文件src.c的内容到目标文件des.c,需要执行以下流程:
1、使用open函数打开源文件(src.c)
2、使用open函数打开目标文件(des.c)
3、使用read函数读取src文件到缓存数组
4、使用write函数写入目标文件
5、使用close函数关闭源文件与目标文件
以上是CP指令的基本工作流程,接下来用代码进行表示:
先创建一个文件file.c,用来写接下来的代码:

代码如下所示:
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
//int open(const char *pathname, int flags, mode_t mode);
// int close(int fd);
// ssize_t read(int fd, void *buf, size_t count);
// ssize_t write(int fd, const void *buf, size_t count);
int main(int argc,char *argv[])
{
int src_fd;//源文件
int des_fd;//目标文件
int read_src;
char readbuf[1024]={0};//缓存数组
if(argc !=3)
{
printf("error\n");
return -1;
}
src_fd=open(argv[1],O_RDWR);//打开源文件
if(src_fd<0)
{
printf("open file %d failed\n",src_fd);
return -2;
}
des_fd=open(argv[2],O_RDWR|O_CREAT,0755);//打开目标文件
if(des_fd<0)
{
printf("open file %d failed\n",des_fd);
return -3;
}
while(1)//循环读取和写入,防止有数据冗余的情况
{
read_src=read(src_fd,&readbuf[0],128);
if(read_src<128)break;
write(des_fd,readbuf,read_src);
memset(readbuf,0,128);//每读取和写入一次,清理数组中的数据
}
write(des_fd,readbuf,read_src);//写入剩余的数据
close(src_fd);//关闭源文件
close(des_fd);//关闭目标文件
return 0;
}
然后使用gcc编译器进行编译,使用生成的a.out文件进行复制:
可以看到经过diff指令的验证后,hello.c文件个hello2.c文件的内容一致,这说明成功将源文件的数据复制到了目标文件里。
更多推荐

所有评论(0)