一、实验题目
程序编写
·拷贝文件功能
·模仿cp命令的执行效果
·错误检查(参数检查,程序逻辑,函数返回值判断等)
(只考虑文件,不考虑目录)
strace调用
·查看所编写程序执行过程中调用的系统调用
·strace用来判断一个程序执行出错的原因
二、相关原理与知识
1.GNU CC
使用GNU CC(简称gcc),在Linux里编译,编译流程为:预处理、编译、汇编、链接。如下:
Pre - processing
gcc -E hello.c>hello.i
Compiling
gcc -S hello.c
Assembling
gcc -c hello.c
Linking
gcc -o hello hello.c
2.VIM编译器
使用vim编译器,基本步骤:
- vi进入vi编辑器
- a或者i进入编辑模式
- <Esc>到命令行模式
- :进入底行命令模式
- q,q! 退出vi
- w ,w file保存缓冲区的文件
3.C语言
用C语言实现将一个文件的内容复制到目标文件的程序。该程序首先提示用户输入源文件和目标文件的名称,包括所有必要的错误检查,包括确保源文件是否存在。
4.使用strace跟踪程序
strace是一个功能强大的Linux命令行工具,主要用于诊断和调试程序的行为。它是用户空间跟踪器,专门用于监控用户空间进程与内核之间的交互,包括系统调用、信号传递以及进程状态变更等。
三、实验过程
程序编写
·拷贝文件功能
使用C语言的标准库函数fopen、fgetc和fputc来复制文件。这个程 序首先提示用户输入源文件和目标文件的名称,然后打开这两个文件, 并逐个字符地从源文件中读取内容,然后写入到目标文件中。
·模仿cp命令的执行效果
对于错误检查,我检查了源文件是否存在,是否能打开,目标文件 是否能打开,如果不能打开,与用户交互:“无法打开源文件”或者“无 法打开目标文件”,并且返回函数值为1。
如果复制成功,与用户交互:“文件复制成功!”,并且返回函数值0。
strace
首先用“sudo apt-get install strace”下载strace,在编写完代码后,我将文件存入copy.c里,使用命令“strace ./copy.c”来观察跟踪此程序,为了方便和界面的简化,我采用“strace -o output.txt ./copy”的方式将测试结果放到output.txt文件中。
四、实验结果与分析
·在Windows中编写测试的结果
程序运行前的预设:
正确执行文件的结果如图:
目标结果如图:
如果错误输入文件名结果如图所示:
·在Linux 系统中运行结果
程序运行前的预设:
正确执行文件的结果如图:
目标结果如图:
此时已经成功将1.txt中的内容复制到2.txt中了。
如果错误输入文件名结果如图所示:
·使用strace进行程序跟踪
在strace ./copy.c命令下运行结果如图所示
为了视图更简洁,我采用了strace -o output.txt ./copy命令将正确运行和错误运行结果分别存入了output1.txt和output2.txt中 。
正确和错误运行结果如图所示
在正确的运行结果下,output1.txt中主程序部分,未出现返回值为-1的语句。
但是在错误输入的运行结果下,在output2.txt中,找到语句如图所示:
原理分析:在查找文件1的 时候,未找到文件,返回值-1,并且报错,在交互界面输出“无法打开源文件”,实验结果符合预期。
五、问题总结
1、对vi编译器不熟悉,写入文件和保存文件后,不知道如何调用和再次打开该文件。在机房电脑中,命令vim hello.c不起作用,在更新虚拟机后,问题解决。
2、未安装gcc和strace,导致一直出现“command not found”提示。安装后解决。
3、Strace返回的语句杂乱,不知道如何查看错误位置。猜想检查返回值为-1的语句,查阅资料得到验证。
六、源代码
#include <stdio.h>
int main() {
FILE* sourceFile, * targetFile;
char sourceName[100], targetName[100];
char ch;
printf("请输入源文件名:");
scanf("%s", sourceName);
printf("请输入目标文件名:");
scanf("%s", targetName);
sourceFile = fopen(sourceName, "r");
if (sourceFile == NULL) {
printf("无法打开源文件");
return 1;
}
targetFile = fopen(targetName, "w");
if (targetFile == NULL) {
printf("无法打开目标文件");
return 1;
}
ch = fgetc(sourceFile);
while (ch != EOF) {
fputc(ch, targetFile);
ch = fgetc(sourceFile);
}
printf("文件复制成功!");
fclose(sourceFile);
fclose(targetFile);
return 0;
}