linux有没有内核文件操作函数

服务器   发布日期:2023年07月25日   浏览次数:554

这篇文章主要介绍“linux有没有内核文件操作函数”,在日常操作中,相信很多人在linux有没有内核文件操作函数问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux有没有内核文件操作函数”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

linux有内核文件操作函数,例filp_open()函数可用于打开文件、vfs_read()函数可用于读取文件、vfs_write()函数可用于写文件、filp_close()函数可用于关闭文件。在vfs_read和vfs_write函数中,其第二个参数指向的用户空间的内存地址,如果直接使用内核空间的指针,则会返回“-EFALUT”。

1. 内核空间文件操作

功能 函数原型
打开文件 struct file *filp_open(const char *filename, int flags, int mode)
读文件 ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
写文件 ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
关闭文件 int filp_close(struct file *filp, fl_owner_t id)

2. 内核空间与用户空间

在vfs_read和vfs_write函数中,其参数buf指向的用户空间的内存地址,如果我们直接使用内核空间的指针,则会返回-EFALUT。这是因为使用的缓冲区超过了用户空间的地址范围。一般系统调用会要求你使用的缓冲区不能在内核区。这个可以用

  1. set_fs()、get_fs()
来解决。

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

  1. #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
  2. #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
  3. #define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
  4. #define get_ds() (KERNEL_DS)
  5. #define get_fs() (current->addr_limit)
  6. #define set_fs(x) (current->addr_limit = (x))

如果使用,如下:

  1. mm_segment_t fs = get_fs();
  2. set_fs(KERNEL_FS);
  3. //vfs_write();
  4. vfs_read();
  5. set_fs(fs);

详尽解释:系统调用本来是提供给用户空间的程序访问的,所以,对传递给它的参数(比如上面的buf),它默认会认为来自用户空间,在read或write()函数中,为了保护内核空间,一般会用

  1. get_fs()
得到的值来和USER_DS进行比较,从而防止用户空间程序“蓄意”破坏内核空间;而现在要在内核空间使用系统调用,此时传递给read或write()的参数地址就是内核空间的地址了,在USER_DS之上(USER_DS ~ KERNEL_DS),如果不做任何其它处理,在write()函数中,会认为该地址超过了USER_DS范围,所以会认为是用户空间的“蓄意破坏”,从而不允许进一步的执行;为了解决这个问题
  1. set_fs(KERNEL_DS)
将其能访问的空间限制扩大到KERNEL_DS,这样就可以在内核顺利使用系统调用了!

3.Linux struct inode结构

  1. /*索引节点对象由inode结构体表示,定义文件在linux/fs.h中
  2. */
  3. struct inode {
  4. struct hlist_node i_hash; /* 哈希表 */
  5. struct list_head i_list; /* 索引节点链表 */
  6. struct list_head i_dentry; /* 目录项链表 */
  7. unsigned long i_ino; /* 节点号 */
  8. atomic_t i_count; /* 引用记数 */
  9. umode_t i_mode; /* 访问权限控制 */
  10. unsigned int i_nlink; /* 硬链接数 */
  11. uid_t i_uid; /* 使用者id */
  12. gid_t i_gid; /* 使用者id组 */
  13. kdev_t i_rdev; /* 实设备标识符 */
  14. loff_t i_size; /* 以字节为单位的文件大小 */
  15. struct timespec i_atime; /* 最后访问时间 */
  16. struct timespec i_mtime; /* 最后修改(modify)时间 */
  17. struct timespec i_ctime; /* 最后改变(change)时间 */
  18. unsigned int i_blkbits; /* 以位为单位的块大小 */
  19. unsigned long i_blksize; /* 以字节为单位的块大小 */
  20. unsigned long i_version; /* 版本号 */
  21. unsigned long i_blocks; /* 文件的块数 */
  22. unsigned short i_bytes; /* 使用的字节数 */
  23. spinlock_t i_lock; /* 自旋锁 */
  24. struct rw_semaphore i_alloc_sem; /* 索引节点信号量 */
  25. struct inode_operations *i_op; /* 索引节点操作表 */
  26. struct file_operations *i_fop; /* 默认的索引节点操作 */
  27. struct super_block *i_sb; /* 相关的超级块 */
  28. struct file_lock *i_flock; /* 文件锁链表 */
  29. struct address_space *i_mapping; /* 相关的地址映射 */
  30. struct address_space i_data; /* 设备地址映射 */
  31. struct dquot *i_dquot[MAXQUOTAS]; /* 节点的磁盘限额 */
  32. struct list_head i_devices; /* 块设备链表 */
  33. struct pipe_inode_info *i_pipe; /* 管道信息 */
  34. struct block_device *i_bdev; /* 块设备驱动 */
  35. unsigned long i_dnotify_mask; /* 目录通知掩码 */
  36. struct dnotify_struct *i_dnotify; /* 目录通知 */
  37. unsigned long i_state; /* 状态标志 */
  38. unsigned long dirtied_when; /* 首次修改时间 */
  39. unsigned int i_flags; /* 文件系统标志 */
  40. unsigned char i_sock; /* 可能是个套接字吧 */
  41. atomic_t i_writecount; /* 写者记数 */
  42. void *i_security; /* 安全模块 */
  43. __u32 i_generation; /* 索引节点版本号 */
  44. union {
  45. void *generic_ip; /* 文件特殊信息 */
  46. } u;
  47. };
  48. /*
  49. *索引节点的操作inode_operations定义在linux/fs.h中
  50. */
  51. struct inode_operations {
  52. int (*create) (struct inode *, struct dentry *,int);
  53. /*VFS通过系统调用create()和open()来调用该函数,从而为dentry对象创建一个新的索引节点。在创建时使用mode制定初始模式*/
  54. struct dentry * (*lookup) (struct inode *, struct dentry *);
  55. /*该韩式在特定目录中寻找索引节点,该索引节点要对应于dentry中给出的文件名*/
  56. int (*link) (struct dentry *, struct inode *, struct dentry *);
  57. /*该函数被系统调用link()电泳,用来创建硬连接。硬链接名称由dentry参数指定,连接对象是dir目录中ld_dentry目录想所代表的文件*/
  58. int (*unlink) (struct inode *, struct dentry *);
  59. /*该函数被系统调用unlink()调用,从目录dir中删除由目录项dentry制动的索引节点对象*/
  60. int (*symlink) (struct inode *, struct dentry *, const char *);
  61. /*该函数被系统电泳symlik()调用,创建符号连接,该符号连接名称由symname指定,连接对象是dir目录中的dentry目录项*/
  62. int (*mkdir) (struct inode *, struct dentry *, int);
  63. /*该函数被mkdir()调用,创建一个新鲁姆。创建时使用mode制定的初始模式*/
  64. int (*rmdir) (struct inode *, struct dentry *);
  65. /*该函数被系统调用rmdir()调用,删除dir目录中的dentry目录项代表的文件*/
  66. int (*mknod) (struct inode *, struct dentry *, int, dev_t);
  67. /*该函数被系统调用mknod()调用,创建特殊文件(设备文件、命名管道或套接字)。要创建的文件放在dir目录中,其目录项问dentry,关联的设备为rdev,初始权限由mode指定*/
  68. int (*rename) (struct inode *, struct dentry *,
  69. struct inode *, struct dentry *);
  70. /*VFS调用该函数来移动文件。文件源路径在old_dir目录中,源文件由old_dentry目录项所指定,目标路径在new_dir目录中,目标文件由new_dentry指定*/
  71. int (*readlink) (struct dentry *, char *, int);
  72. /*该函数被系统调用readlink()调用,拷贝数据到特定的缓冲buffer中。拷贝的数据来自dentry指定的符号链接,最大拷贝大小可达到buflen字节*/
  73. int (*follow_link) (struct dentry *, struct nameidata *);
  74. /*该函数由VFS调用,从一个符号连接查找他指向的索引节点,由dentry指向的连接被解析*/
  75. int (*put_link) (struct dentry *, struct nameidata *);
  76. /*在follow_link()调用之后,该函数由vfs调用进行清楚工作*/
  77. void (*truncate) (struct inode *);
  78. /*该函数由VFS调用,修改文件的大小,在调用之前,索引节点的i_size项必须被设置成预期的大小*/
  79. int (*permission) (struct inode *, int);
  80. /*该函数用来检查给低昂的inode所代表的文件是否允许特定的访问模式,如果允许特定的访问模式,返回0,否则返回负值的错误码。多数文件系统 都将此区域设置为null,使用VFS提供的通用方法进行检查,这种检查操作仅仅比较索引及诶但对象中的访问模式位是否和mask一致,比较复杂的系统, 比如支持访问控制链(ACL)的文件系统,需要使用特殊的permission()方法*/
  81. int (*setattr) (struct dentry *, struct iattr *);
  82. /*该函数被notify_change调用,在修改索引节点之后,通知发生了改变事件*/
  83. int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
  84. /*在通知索引节点需要从磁盘中更新时,VFS会调用该函数*/
  85. int (*setxattr) (struct dentry *, const char *,
  86. const void *, size_t, int);
  87. /*该函数由VFS调用,向dentry指定的文件设置扩展属性,属性名为name,值为value*/
  88. ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
  89. /*该函数被VFS调用,向value中拷贝给定文件的扩展属性name对应的数值*/
  90. ssize_t (*listxattr) (struct dentry *, char *, size_t);
  91. /*该函数将特定文件所有属性别表拷贝到一个缓冲列表中*/
  92. int (*removexattr) (struct dentry *, const char *);
  93. /*该函数从给定文件中删除指定的属性*/
  94. };

4.Linux struct file结构
struct file结构体定义在/linux/include/linux/fs.h(Linux 2.6.11内核)中,其原型是:

  1. struct file {
  2. /*
  3. * fu_list becomes invalid after file_free is called and queued via
  4. * fu_rcuhead for RCU freeing
  5. */
  6. union {
  7. struct list_head fu_list;
  8. struct rcu_head fu_rcuhead;
  9. } f_u;
  10. struct path f_path;
  11. #define f_dentry f_path.dentry
  12. #define f_vfsmnt f_path.mnt
  13. const struct file_operations *f_op;
  14. atomic_t f_count;
  15. unsigned int f_flags;
  16. mode_t f_mode;
  17. loff_t f_pos;
  18. struct fown_struct f_owner;
  19. unsigned int f_uid, f_gid;
  20. struct file_ra_state f_ra;
  21. unsigned long f_version;
  22. #ifdef CONFIG_SECURITY
  23. void *f_security;
  24. #endif
  25. /* needed for tty driver, and maybe others */
  26. void *private_data;
  27. #ifdef CONFIG_EPOLL
  28. /* Used by fs/eventpoll.c to link all the hooks to this file */
  29. struct list_head f_ep_links;
  30. spinlock_t f_ep_lock;
  31. #endif /* #ifdef CONFIG_EPOLL */
  32. struct address_space *f_mapping;
  33. };

文 件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码 中,struct file的指针通常被命名为file或filp。

以上就是linux有没有内核文件操作函数的详细内容,更多关于linux有没有内核文件操作函数的资料请关注九品源码其它相关文章!