一:题目介绍
设计一个带参数的模块,其参数为源文件1和源文件2的文件名(可能带路径),模块功能是把源文件2的内容追加到源文件1的末尾。
本题主要考察了Linux内核的插入,以及打开文件,读文件,写文件等操作。
本题的关键点在于运用库中的函数来进行文件的操作:读写等。
二:实验思路
图1:copy.c文件思路
注解:.c文件主要是实现功能的文件,通过分析题目加上个人的理解和资料的查找之后,撰写了该代码中成功实现了文件的复制功能。
该代码中主要有四个参数分别为两个文件的路径,buffer缓冲区以及一个状态参数。两个文件的路径是实现文件复制功能上的必要条件,buffer缓冲区是实现功能的必要工具,而状态参数主要是为了提高代码的灵活性和维护性。
通过题目的分析以实现的功能逻辑编写了功能函数,主要实现复制文件功能。按照书上的描述,为.c文件编写了主要的框架包括了头文件,模块许可申明,初始化与清理函数。
三:遇到的问题及解决方法
- 之前未接触过Linux系统,所以对于一些基本操作还不熟悉。从头开始学习Linux系统如何新建文件,写文件,保存文件等。
- 未了解内核概念直接开始编写.c文件,没有写模块许可申明以及初始化与清理函数导致无法编译。之后看过书中的介绍之后,才学会该如何系统地编写一个内核模块。
- 插入内核之后,想要再次执行功能函数,结果出错。发现了内核在插入过程中才实施了功能的操作。此时需要移除内核之后再插入内核才可以再次实现功能。
四:代码
static int append_file(void)
{
struct file *file1 = NULL, *file2 = NULL;
loff_t offset = 0;
int ret = 0;
char buffer[4096];
// 打开文件 1,以写模式打开
file1 = filp_open(file_path1, O_WRONLY | O_APPEND, 0644);
if (IS_ERR(file1)) {
ret = PTR_ERR(file1);
printk(KERN_ERR "Error opening file %s, %d\n", file_path1, ret);
return ret;
}
// 打开文件 2,以读模式打开
file2 = filp_open(file_path2, O_RDONLY, 0);
if (IS_ERR(file2)) {
ret = PTR_ERR(file2);
printk(KERN_ERR "Error opening file %s, %d\n", file_path2, ret);
filp_close(file1, NULL);
return ret;
}
// 读取文件 2 的内容
while ((ret = kernel_read(file2, buffer, sizeof(buffer), &offset)) > 0) {
// 把文件 2 的内容写入到文件 1 的末尾
ret = kernel_write(file1, buffer, ret, &file1->f_pos);
if (ret < 0) {
printk(KERN_ERR "Error appending file %s, %d\n", file_path1, ret);
break;
}
}
if (ret < 0) {
// 写入出错,清理资源并返回错误码
filp_close(file1, NULL);
filp_close(file2, NULL);
return ret;
}
// 关闭文件
filp_close(file1, NULL);
filp_close(file2, NULL);
return 0;
}
五:实验结果
图2:插入内核之前的目标文件和源文件
图3:终端上执行的命令
图4:插入内核之后的目标文件和源文件