返回顶部
首页 > 资讯 > 操作系统 >在linux内核中如何操作某个文件
  • 469
分享到

在linux内核中如何操作某个文件

2023-06-15 15:06:16 469人浏览 安东尼
摘要

这篇文章将为大家详细讲解有关在linux内核中如何操作某个文件,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、问题描述如何在内核中操作某个文件?二、操作函数1. 分析在用户态,读写文件可以通过read和

这篇文章将为大家详细讲解有关在linux内核中如何操作某个文件,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、问题描述

如何在内核中操作某个文件?

在linux内核中如何操作某个文件

二、操作函数

1. 分析

在用户态,读写文件可以通过read和write这两个系统调用来完成(C库函数实际上是对系统调用的封装)。但是,在内核态没有这样的系统调用,我们又该如何读写文件呢?

阅读Linux内核源码,可以知道陷入内核执行的是实际执行的是sys_read和sys_write这两个函数,但是这两个函数没有使用EXPORT_SYMBOL导出,也就是说其他模块不能使用。

在fs/open.c中系统调用具体实现如下(内核版本3.14):

SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) {  if (force_o_largefile())   flags |= O_LARGEFILE;   return do_sys_open(AT_FDCWD, filename, flags, mode); }

跟踪do_sys_open()函数,

long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) {  struct open_flags op;  int fd = build_open_flags(flags, mode, &op);  struct filename *tmp;   if (fd)   return fd;   tmp = getname(filename);  if (IS_ERR(tmp))   return PTR_ERR(tmp);   fd = get_unused_fd_flags(flags);  if (fd >= 0) {   struct file *f = do_filp_open(dfd, tmp, &op);   if (IS_ERR(f)) {    put_unused_fd(fd);    fd = PTR_ERR(f);   } else {    fsnotify_open(f);    fd_install(fd, f);   }  }  putname(tmp);  return fd; }

就会发现它主要使用了do_filp_open()函数该函数在fs/namei.c中,

struct file *do_filp_open(int dfd, struct filename *pathname,   const struct open_flags *op) {  struct nameidata nd;  int flags = op->lookup_flags;  struct file *filp;   filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);  if (unlikely(filp == ERR_PTR(-ECHILD)))   filp = path_openat(dfd, pathname, &nd, op, flags);  if (unlikely(filp == ERR_PTR(-ESTALE)))   filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_REVAL);  return filp; }

该函数最终打开了文件,并返回file类型指针。所以我们只需要找到其他调用了do_filp_open()函数的地方,就可找到我们需要的文件操作函数。

而在文件fs/open.c中,filp_open函数也是调用了file_open_name函数,

 struct file *filp_open(const char *filename, int flags, umode_t mode) {  struct filename name = {.name = filename};  return file_open_name(&name, flags, mode); } EXPORT_SYMBOL(filp_open);

函数file_open_name调用了do_filp_open,并且接口和sys_open函数极为相似,调用参数也和sys_open一样,并且使用EXPORT_SYMBOL导出了,所以在内核中可以使用该函数打开文件,功能非常类似于应用层的open。

 struct file *file_open_name(struct filename *name, int flags, umode_t mode) {  struct open_flags op;  int err = build_open_flags(flags, mode, &op);  return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op); }

2. 所有操作函数

使用同样的方法,找出了一组在内核操作文件的函数,如下:

在linux内核中如何操作某个文件

这些函数的参数非常类似于应用层文件io函数,open、read、write、close。

3. 用户空间地址

虽然我们找到了这些函数,但是我们还不能直接使用。

因为在vfs_read和vfs_write函数中,其参数buf指向的用户空间的内存地址,如果我们直接使用内核空间的指针,则会返回-EFALUT。

这是因为使用的缓冲区超过了用户空间的地址范围。一般系统调用会要求你使用的缓冲区不能在内核区。这个可以用set_fs()、get_fs()来解决。

在include/asm/uaccess.h中,有如下定义:

#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) #define get_ds() (KERNEL_DS) #define get_fs() (current->addr_limit) #define set_fs(x) (current->addr_limit = (x))

如果使用,可以按照如下顺序执行:

mm_segment_t fs = get_fs(); set_fs(KERNEL_FS); //vfs_write(); //vfs_read(); set_fs(fs);

详解:系统调用本来是提供给用户空间的程序访问的,所以,对传递给它的参数(比如上面的buf),它默认会认为来自用户空间,在read或write()函数中,为了保护内核空间,一般会用get_fs()得到的值来和USER_DS进行比较,从而防止用户空间程序“蓄意”破坏内核空间。

而现在要在内核空间使用系统调用,此时传递给read或write()的参数地址就是内核空间的地址了,在USER_DS之上(USER_DS ~  KERNEL_DS),如果不做任何其它处理,在write()函数中,会认为该地址超过了USER_DS范围,所以会认为是用户空间的“蓄意破坏”,从而不允许进一步的执行。

为了解决这个问题, set_fs(KERNEL_DS),将其能访问的空间限制扩大到KERNEL_DS,这样就可以在内核顺利使用系统调用了!

在VFS的支持下,用户态进程读写任何类型的文件系统都可以使用read和write这两个系统调用,但是在linux内核中没有这样的系统调用我们如何操作文件呢?

我们知道read和write在进入内核态之后,实际执行的是sys_read和sys_write,但是查看内核源代码,发现这些操作文件的函数都没有导出(使用EXPORT_SYMBOL导出),也就是说在内核模块中是不能使用的,那如何是好?

通过查看sys_open的源码我们发现,其主要使用了do_filp_open()函数,该函数在fs/namei.c中,而在改文件中,filp_open函数也是间接调用了do_filp_open函数,并且接口和sys_open函数极为相似,调用参数也和sys_open一样,并且使用EXPORT_SYMBOL导出了,所以我们猜想该函数可以打开文件,功能和open一样。

三、实例

Makefile

ifneq ($(KERNELRELEASE),) obj-m:=sysopen.o else KDIR :=/lib/modules/$(shell uname -r)/build PWD  :=$(shell pwd) all:  $(info "1st")  make -C $(KDIR) M=$(PWD) modules clean:  rm -f *.ko *.o *.mod.o *.symvers *.cmd  *.mod.c *.order endif

sysopen.c

#include <linux/module.h> #include <linux/syscalls.h> #include <linux/file.h> #include <linux/fcntl.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/uaccess.h>  MODULE_LICENSE("GPL"); MODULE_AUTHOR("yikoulinux");  void test(void) {  struct file *file = NULL;  mm_segment_t old_fs;  loff_t  pos;   char buf[64]="yikoulinux";   printk("test()");  file = filp_open("/home/peng/open/test.txt\n",O_RDWR|O_APPEND|O_CREAT,0644);  if(IS_ERR(file)){   return ;  }  old_fs = get_fs();  set_fs(KERNEL_DS);  pos = 0;  vfs_write(file,buf,sizeof(buf),&pos);   pos =0;  vfs_read(file, buf, sizeof(buf), &pos);  printk("buf:%s\n",buf);    filp_close(file,NULL);  set_fs(old_fs);  return; }   static int hello_init(void) {  printk("hello_init \n");  test();  return 0; } static void hello_exit(void) {  printk("hello_exit \n");  return; }  module_init(hello_init); module_exit(hello_exit);

编译:

在linux内核中如何操作某个文件

安装模块:

在linux内核中如何操作某个文件

查看操作的文件:

在linux内核中如何操作某个文件

查看文件内容:

在linux内核中如何操作某个文件

可见在内核模块中成功操作了文件。

关于“在linux内核中如何操作某个文件”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: 在linux内核中如何操作某个文件

本文链接: https://lsjlt.com/news/280642.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 在linux内核中如何操作某个文件
    这篇文章将为大家详细讲解有关在linux内核中如何操作某个文件,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、问题描述如何在内核中操作某个文件二、操作函数1. 分析在用户态,读写文件可以通过read和w...
    99+
    2023-06-15
  • linux有没有内核文件操作函数
    这篇文章主要介绍“linux有没有内核文件操作函数”,在日常操作中,相信很多人在linux有没有内核文件操作函数问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux有没有...
    99+
    2023-03-02
    linux
  • linux内核文件如何查看
    要查看Linux内核文件,可以使用以下命令: 查看当前系统正在运行的内核版本: uname -r 查看内核文件的路径: l...
    99+
    2024-04-02
  • 如何在Linux系统上安装Linux内核头文件
    本篇内容主要讲解“如何在Linux系统上安装Linux内核头文件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何在Linux系统上安装Linux内核头文件”吧!当你在编译一个设备驱动模块时,你...
    99+
    2023-06-13
  • 如何理解Linux内核的文件
    本篇内容介绍了“如何理解Linux内核的文件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Linux文件预读算法磁盘I/O性能的发展远远滞后...
    99+
    2023-06-13
  • Java面试:如何在Linux文件系统中操作文件?
    在Java开发中,经常需要进行文件操作,比如读取文件内容、写入文件内容、创建文件夹等等。而在Linux操作系统中,文件系统是一种非常重要的资源,因此掌握在Linux文件系统中操作文件的技能也变得尤为重要。本文将介绍在Java中如何在Lin...
    99+
    2023-08-04
    面试 linux 文件
  • Linux如何压缩某个文件夹
    小编给大家分享一下Linux如何压缩某个文件夹,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Linux 压缩某个文件夹的实现方法tar -zcvf /home/xahot.tar.gz /xahot tar -zcvf 打...
    99+
    2023-06-09
  • linux如何替换文件中某个字符串
    linux替换文件中某个字符串的方法:1、打开linux终端;2、在命令行中使用sed命令来进行替换文件中某个字符串即可。具体操作步骤:在linux系统桌面中使用快捷键【Ctrl+Alt+T】打开linux终端命令行模式。在linux终端命...
    99+
    2024-04-02
  • 文件目录操作——Linux命令核心
    目录 相对路径和绝对路径  查看和切换工作目录 pwd 显示当前工作目录的绝对路径 cd 切换目录 列出目录内容 ls 列出目录的内容 创建和删除目录文件夹 mkdir创建一个新目录 rmdir 删除一个空的目录 touch 创建空文件 ...
    99+
    2023-09-11
    linux 运维 服务器
  • 如何在vbs中操作txt文本文件
    这篇文章将为大家详细讲解有关如何在vbs中操作txt文本文件,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。创建文件dim fso, fset fso ...
    99+
    2023-06-08
  • 如何在Linux中使用sed命令在文件某行前后添加内容
    这期内容当中小编将会给大家带来有关如何在Linux中使用sed命令在文件某行前后添加内容,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、在某行的前一行或后一行添加内容具休操作如下:#匹配行前加sed -...
    99+
    2023-06-12
  • Linux内核中的位数组和位操作
    这篇文章主要介绍“Linux内核中的位数组和位操作”,在日常操作中,相信很多人在Linux内核中的位数组和位操作问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux内核中的位数组和位操作”的疑惑有所帮助!...
    99+
    2023-06-16
  • Linux中怎么实现内核升级操作
    Linux中怎么实现内核升级操作,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1.下载内核cd /usr/srcwget linux/kernel/v2.6...
    99+
    2023-06-16
  • 如何在PHP中操作临时文件
    目录获取 PHP 的默认临时创建文件目录创建一个临时文件根据目录状态创建一个唯一名称的临时文件总结获取 PHP 的默认临时创建文件目录 学习过 Linux 操作系统的都会知道有一个...
    99+
    2024-04-02
  • 如何在Python中进行文件操作
    如何在Python中进行文件操作文件操作是编程中常见的任务之一,而Python提供了丰富的文件操作功能和简洁的语法来帮助我们有效地进行文件的读写和处理。本文将介绍如何在Python中进行文件操作,并提供一些具体的代码示例。打开和关闭文件在进...
    99+
    2023-10-22
    Python文件操作
  • 在PHP中如何进行文件操作?
    PHP是一种广为应用的服务器端编程语言,在开发过程中经常需要进行文件操作。文件操作涉及读取、写入、删除和追加文件等操作。本文将介绍在PHP中如何进行文件操作。打开文件打开文件是进行文件操作的第一步,通过PHP内置的fopen()函数可以打开...
    99+
    2023-05-21
    PHP文件操作 文件读写PHP PHP目录操作
  • Linux如何实现文件操作
    这篇文章主要介绍了Linux如何实现文件操作,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。文件是linux中的一个重要概念。在Linux中,一切(几乎一切)都是文件。简单的说...
    99+
    2023-06-28
  • Java文件学习笔记:如何在Linux系统中操作?
    Java是一种广泛使用的编程语言,用于开发各种类型的应用程序,包括Web应用程序、桌面应用程序、移动应用程序等等。在Java编程中,文件操作是非常重要的一部分,因为它涉及到读取和写入文件、创建和删除文件等功能。在本篇文章中,我们将讨论如何...
    99+
    2023-08-30
    文件 学习笔记 linux
  • 如何在Linux操作系统下创建锁文件
    这篇文章主要介绍“如何在Linux操作系统下创建锁文件”,在日常操作中,相信很多人在如何在Linux操作系统下创建锁文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何在Linux操作系统下创建锁文件”的疑...
    99+
    2023-06-17
  • 如何在Python中对文件进行操作
    目录前言1.open()函数2.读文件3.写文件4.通过 with 来读写文件前言 在Python中,我们可以通过一些内置函数来操作电脑上的文件,并对文件进行读写,这种读写操作是很常...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作