关于cp命令的编写
关于cp命令的编写
娄老师在课上详细的讲了命令who的编写过程~对此,我很有启发!于是想亲自动手试试~ 有什么不足的地方请大家提出来!
Learning by doing ~ 做中学,真的只有自己动手去实践一遍,才能体会到其中的精髓!我跟着娄老师讲who命令时的思路来做了一遍cp,收获颇多~很爽!
参考资料——别出心材的Linux系统调用
在编写cp命令之前,同样有三个问题:
- cp命令能做什么
- cp命令是如何实现的?
- 能不能自己编写一个cp命令?
问题1. cp命令能做什么?
cp能够复制文件,典型的用法是:
cp source-file target-file
如果target-file所指定的文件不存在,cp就创建这个文件,如果已经存在就覆盖,target-file的内容与source-file相同。
问题2. cp命令是如何实现的?
一个Linux命令的功能我们可以通过whatis或man -f来查看,当然最好的方法是自己通过使用来体验一下:

要进一步了解cp的用法,需要借助联机帮助manpages。我们输入man -k cp,再输入man 1 cp。


要学会在帮助文档中寻找有用的信息!


到这,即使以前没有用过cp命令,也大概知道它的功能了。
了解cp的功能后,写出其伪代码:
- 打开source-file
- 创建target-file
- 从source-file读出一段数据
- 把这段数据写入target-file
- 关闭source-file
- 关闭target-file
现在的问题是如何创建文件?如何打开文件?如何读文件,如何写文件?
如何创建文件:


如何读文件:
我们用man -k read | grep file | grep 2搜一下,再man 2 read

如何打开文件:


图片中红线内部是需要用到的库。
然后使用grep -nr XXX /usr/include查找相关宏。

如何写文件:


问题3.能不能自己编写一个cp命令
看代码的时候我最先不理解的就是main函数的定义:
int main(int argc, char *argv[]){}
经查阅得知,argc是用来表示在命令行下输入命令时的参数个数,包括指令本身;argv[]是用来取得你输入的参数。针对具体指令分析如下(每一步解释由注释形式给出)。
首先先先看一下涉及到的头文件的用处:
- stdio.h 标准输入输出
- stdlib.h C标准函数库
- unistd.h Unix类系统定义符号常量
- fcntl.h 定义了很多宏和open,fcntl函数原型
- sys/types.h 基本系统数据类型
- dirent.h unix类目录操作的头文件,包含了许多UNIX系统服务的函数原型,例如opendir函数、readdir函数。
- termios.h 在Posix规范中定义的标准接口
代码如下:
#include <stdio.h>//标准输入输出
#include <stdlib.h>//C标准函数库
#include <unistd.h>//Unix类系统定义符号常量
#include <fcntl.h>//定义了很多宏和open,fcntl函数原型
#define BUFFERSIZE 4096//定义存储器容量
#define COPYMODE 0644//定义复制的长度
void oops(char *, char *);
int main(int argc, char *argv[])
{
int in_fd, out_fd, n_chars;//三个描述符值
char buf[BUFFERSIZE];//存储器位置
/*cp的参数有两个,分别是要复制的文件,和目的目录,这样一共应该是有三个操作数
所以要先检查argc的值是否为三,如果不是,返回标准错误*/
if (argc != 3) {
fprintf(stderr, "usage: %s source destination\n", *argv);
exit(1);
}
/*检查cp的第一个参数,要复制的文件,用open打开,in_fd为open返回的描述符
如果返回-1,代表打开失败,提示错误*/
if ((in_fd = open(argv[1], O_RDONLY)) == -1)
oops("Cannot open ", argv[1]);
/*检查cp的第二个参数,复制的目的地址,用create在目的地址创建新文件,out_fd为open返回的描述符
如果返回-1,代表创建失败,提示错误*/
if ((out_fd = creat(argv[2], COPYMODE)) == -1)
oops("Cannot creat", argv[2]);
/*cp指令的动作就是读取一个文件的内容到存储器,在新的地址创建空白文件,再从存储器将内容写入新文件。
这里判断复制是否成功:
如果能读取顺利,而读取的位数和写的位数不同,是写错误;
如果读取失败,是读错误。*/
while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
if (write(out_fd, buf, n_chars) != n_chars)
oops("Write error to ", argv[2]);
if (n_chars == -1)
oops("Read error from ", argv[1]);
/*这里执行的是关闭文件的动作,in_fd和out_fd两个文件描述符
所指向的文件只要有一个关闭错误,就提示关闭错误。*/
if (close(in_fd) == -1 || close(out_fd) == -1)
oops("Error closing files", "");
}
/*这个是用来输出错误信息的函数*/
void oops(char *s1, char *s2)
{
fprintf(stderr, "Error: %s ", s1);
perror(s2);//用来将上一个函数发生错误的原因输出到标准设备(stderr)
exit(1);
}
这里要注意main函数的两个参数:
- argc记录了用户在运行程序的命令行中输入的参数的个数。
- arg[]指向的数组中至少有一个字符指针,即arg[0].它通常指向程序中的可执行文件的文件名。
代码验证:
首先新建两个txt文件,我这里为1.txt和2.txt。
1.txt里面的内容是111111;2.txt的内容为222222.


经过cp命令后,1.txt的内容拷贝到了2.txt里面。


将2.txt里面的内容复原后,用编写的cp命令来试一下,



果然经过编写的cp命令后,1.txt的内容拷贝到了2.txt里面。

说明编写的cp代码正确!
总结
通过上面的例子,我们学习了Linux中学习Linxu系统编程的方法:
- 仔细研究manpages
- 问题驱动,使用man -k key1|grep key2|...在manpages中搜索你要的内容
- 阅读.h文件: 可以通过grep -nr XXXX /usr/incldue查找相关的宏定义,结构体定义,类型定义等
- 解决一个问题要多个系统调用,可以参考manpages的SEE ALSO部分来得到相关系统调用的信息
关于cp命令的编写的更多相关文章
- cp命令的编写——浅谈系统调用
摘要:linux中cp命令的实现,通过这个程序,我们需要了解系统调用耗费时间的方面,同时学会系统调用的错误处理机制. 本文来源:http://blog.csdn.net/trochiluses/art ...
- cp/tar/用c语言编写程序 实现cp命令的效果
1.cp (拷贝) 已存在文件路径 要拷贝的文件路径 实现cp命令的代码如下: #include <stdio.h> //因为要在命令中得到两个路径,所以要用到main函数的两个参数 i ...
- linux系统编程:自己动手写一个cp命令
cp命令的基本用法: cp 源文件 目标文件 如果目标文件不存在 就创建, 如果存在就覆盖 实现一个cp命令其实就是读写文件的操作: 对于源文件: 把内容全部读取到缓存中,用到的函数read 对于目标 ...
- 每天一个Linux命令(10)cp命令
cp命令用来将一个或多个源文件或者目录复制到指定的目的文件或目录.它可以将单个源文件复制成一个指定文件名的具体的文件或一个已经存在的目录下.cp命令还支持同时复制多个文件,当一次复制多个文件时,目标文 ...
- Linux命令学习总结:cp命令
命令简介: cp命令用来复制文件或目录.指令英文原义:copy 指令所在路径:/bin/cp 命令语法: Usage: cp [OPTION]... [-T] SOURCE DEST or: cp [ ...
- 【初级】linux cp 命令详解及使用方法实战
cp:复制文件或者目录 前言: cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不 ...
- linux命令(8):cp 命令
cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...
- Linux cp命令使用说明
Linux cp命令使用说明 --功能说明:复制目录或文件 --命令格式:cp [参数] <文件或目录> <文件或目录> --常用参数: -R 复制目录 -i 覆盖文件之 ...
- 每天一个linux命令(8):cp 命令
cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...
随机推荐
- Oracle安全之 Oracle 11g flashback技术详解
Oracle11g提供的闪回技术用于对抗人为错误,主要有以下7种技术组成: 闪回查询-(闪回时间查询.闪回版本查询): 闪回数据归档: 闪回事务查询: 闪回事务: 闪回表: 闪回删表: 闪回数据库. ...
- MySQL在linux上的rpm包方式安装方法
1.下载上传mysql server和client rpm包: [root@faspdev mnt]# ls MySQL-client-5.5.53-1.el6.x86_64.rpm MySQL-se ...
- MySQL Error 1215: Cannot add foreign key constraint
MySQL Error 1215: Cannot add foreign key constraint DROP TABLE IF EXISTS `r_role_region`; CREATE TAB ...
- 通过qemu复现路由器漏洞
目录 简介 环境搭建 固件解包 复现漏洞,IDA调试 参考资料 简介 qemu和vmware一样,一种虚拟机软件,只不过qemu能够虚拟的平台更加丰富一些.能够虚拟很多嵌入式平台的设备. 工作上需要向 ...
- vue - vue-cli脚手架安装和webpack-simple模板项目生成
ue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. GitHub地址是:https://github.com/vuejs/vue-cli 一.安 ...
- 2018/03/31 每日一个Linux命令 之 date
date 命令主要用于查看和修改时间和时区 -- 这里主要学习基本的查看和设置时间和时区的方法. 直接显示日期 date '+%D' 效果 vagrant@hong:~$ date '+%D' 03/ ...
- spring读取配置文件内容并自动注入
添加注解: @PropertySource(value={"classpath:venus.properties"}) 示例: import org.springframework ...
- 为帝国cms模板添加站内搜索小教程
由于客户的需要,最近都在整帝国cms,很多东西还是不熟悉,特别是帝国cms模板,以前用的那些网站模板一般是保存在ftp文件中,而帝国cms模板是直接保存在数据库中,修改是在网站后台的模板管理,得慢慢适 ...
- 帝国cms底部代码哪里改?要修改版权和统计代码
最近接手的几个站是用帝国cms做的,底部代码那边都有一个**设计的链接,还有一些不相关的东西,第一眼看到就想把那些帝国cms底部代码清理掉,这就是让别人建站的烦恼,让他们删除说要收费,坑就一个字,自己 ...
- [py]类和实例方法/内建方法
内建方法 dir(__builtins__) 类和实例方法对比 class person: def __init__(self, job): self.job = job name = "m ...