Bootstrap

linux内核中打开文件并写入文件

内核版本

Linux 5.15.0-58-generic

实例代码

#include <linux/uaccess.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/errno.h>

static struct file *open_dump_file(char* string, mm_segment_t* fs)
{
	struct file *filp = NULL;
	filp = filp_open(string, O_RDWR | O_CREAT | O_APPEND, 0644);
	if (IS_ERR(filp)) {
		return NULL;
	}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
	*fs = get_fs();
	set_fs(KERNEL_DS);
#else
	*fs = force_uaccess_begin();
#endif
	return filp;
}

static int close_dump_file(struct file * filp, mm_segment_t* fs)
{
	if (filp == NULL || fs == NULL)
		return -EFAULT;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
	set_fs(*fs);
#else
	force_uaccess_end(*fs);
#endif
	filp_close(filp, NULL);
	return 0;
}

static int write_file(struct file * filp, char* buf, int len)
{
	int ret = 0;
	if (filp == NULL || buf == NULL)
		return -EFAULT;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
	ret = kernel_write(filp, buf, len, &filp->f_pos);
#else
	if (filp->f_op->write)
		ret = vfs_write(filp, buf, len, &filp->f_pos);
	else {
		return -EFAULT;
	}
#endif
	memset(buf, 0, len);
	return ret;
}

int write_test(void)
{
	struct file *filp = NULL;
	mm_segment_t fs;
	char test_data[32] = {0};
	int ret = 0;
	filp = open_dump_file("/var/log/test.log", &fs);
	if (filp == NULL) {
				printk("open file failed.\n");
				return -EFAULT;
	}
	sprintf(test_data, "just for test!");
	ret = write_file(filp, test_data, strlen(test_data));
	if (ret) {
		printk("write_file failed.\n");
		return ret;
	}
	ret = close_dump_file(filp, &fs);
	if (ret) {
		printk("close file failed. ret = %d\n", ret);
		return ret;
	}
	return 0;
}

小结

网上当时找了很多的内容,但都没有说明内核版本,全都是vfs_write啥的,但在高版本时内核新建的文件,在系统中对应的读写成员 filp->f_op->write、filp->f_op->read都是空指针,因此根本无法用,最后还是找经验丰富的学长才知道代码版本导致。这次真是被版本🕳了,好好更新就行了嘛非得换接口。

;