Does Linux have kernel file operation functions?

王林
Release: 2023-05-20 13:16:46
forward
1295 people have browsed it

Linux has kernel file operation functions. For example, filp_open() function can be used to open files, vfs_read() function can be used to read files, vfs_write() function can be used to write files, filp_close( ) function can be used to close the file. In the vfs_read and vfs_write functions, the second parameter points to the memory address of the user space. If the kernel space pointer is used directly, "-EFALUT" will be returned.

1. Kernel space file operation

Function Function prototype
Open file struct file *filp_open(const char *filename, int flags, int mode)
Read File ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
Write file ssize_t vfs_write( struct file *file, const char __user *buf, size_t count, loff_t *pos)
Close file int filp_close(struct file *filp, fl_owner_t id)

2. Kernel space and user space

In the vfs_read and vfs_write functions, the memory address of the user space pointed to by the parameter buf , if we use the kernel space pointer directly, -EFALUT will be returned. This is because the buffer used exceeds the user space address range. General system calls will require that the buffer you use cannot be in the kernel area. This can be solved using set_fs(), get_fs().

In include/asm/uaccess.h, there is the following definition:

#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))
Copy after login

If used, it is as follows:

mm_segment_t fs = get_fs();

set_fs(KERNEL_FS);

//vfs_write();

vfs_read();

set_fs(fs);
Copy after login

Detailed explanation: System calls are originally provided to user-space programs for access. Therefore, for the parameters passed to it (such as the above buf), it will be considered to come from user-space by default. In read or write () function, in order to protect the kernel space, the value obtained by get_fs() is generally used to compare with USER_DS, thereby preventing user space programs from "deliberately" destroying the kernel space; now it is used in the kernel space System call. At this time, the parameter address passed to read or write() is the address of the kernel space. It is above USER_DS (USER_DS ~ KERNEL_DS). If no other processing is done, the address will be considered in the write() function. It exceeds the scope of USER_DS, so it will be considered as "deliberate destruction" of the user space, and further execution is not allowed; in order to solve this problemset_fs(KERNEL_DS)expand the space limit that it can access to KERNEL_DS, so You can now use system calls in the kernel smoothly!

3.Linux struct inode structure

/*索引节点对象由inode结构体表示,定义文件在linux/fs.h中
*/
struct inode {
        struct hlist_node       i_hash;              /* 哈希表 */
        struct list_head        i_list;              /* 索引节点链表 */
        struct list_head        i_dentry;            /* 目录项链表 */
        unsigned long           i_ino;               /* 节点号 */
        atomic_t                i_count;             /* 引用记数 */
        umode_t                 i_mode;              /* 访问权限控制 */
        unsigned int            i_nlink;             /* 硬链接数 */
        uid_t                   i_uid;               /* 使用者id */
        gid_t                   i_gid;               /* 使用者id组 */
        kdev_t                  i_rdev;              /* 实设备标识符 */
        loff_t                  i_size;              /* 以字节为单位的文件大小 */
        struct timespec         i_atime;             /* 最后访问时间 */
        struct timespec         i_mtime;             /* 最后修改(modify)时间 */
        struct timespec         i_ctime;             /* 最后改变(change)时间 */
        unsigned int            i_blkbits;           /* 以位为单位的块大小 */
        unsigned long           i_blksize;           /* 以字节为单位的块大小 */
        unsigned long           i_version;           /* 版本号 */
        unsigned long           i_blocks;            /* 文件的块数 */
        unsigned short          i_bytes;             /* 使用的字节数 */
        spinlock_t              i_lock;              /* 自旋锁 */
        struct rw_semaphore     i_alloc_sem;         /* 索引节点信号量 */
        struct inode_operations *i_op;               /* 索引节点操作表 */
        struct file_operations  *i_fop;              /* 默认的索引节点操作 */
        struct super_block      *i_sb;               /* 相关的超级块 */
        struct file_lock        *i_flock;            /* 文件锁链表 */
        struct address_space    *i_mapping;          /* 相关的地址映射 */
        struct address_space    i_data;              /* 设备地址映射 */
        struct dquot            *i_dquot[MAXQUOTAS]; /* 节点的磁盘限额 */
        struct list_head        i_devices;           /* 块设备链表 */
        struct pipe_inode_info  *i_pipe;             /* 管道信息 */
        struct block_device     *i_bdev;             /* 块设备驱动 */
        unsigned long           i_dnotify_mask;      /* 目录通知掩码 */
        struct dnotify_struct   *i_dnotify;          /* 目录通知 */
        unsigned long           i_state;             /* 状态标志 */
        unsigned long           dirtied_when;        /* 首次修改时间 */
        unsigned int            i_flags;             /* 文件系统标志 */
        unsigned char           i_sock;              /* 可能是个套接字吧 */
        atomic_t                i_writecount;        /* 写者记数 */
        void                    *i_security;         /* 安全模块 */
        __u32                   i_generation;        /* 索引节点版本号 */
        union {
                void            *generic_ip;         /* 文件特殊信息 */
        } u;
};

/*
*索引节点的操作inode_operations定义在linux/fs.h中
*/
struct inode_operations {
        int (*create) (struct inode *, struct dentry *,int);
        /*VFS通过系统调用create()和open()来调用该函数,从而为dentry对象创建一个新的索引节点。在创建时使用mode制定初始模式*/
        struct dentry * (*lookup) (struct inode *, struct dentry *);
        /*该韩式在特定目录中寻找索引节点,该索引节点要对应于dentry中给出的文件名*/
        int (*link) (struct dentry *, struct inode *, struct dentry *);
        /*该函数被系统调用link()电泳,用来创建硬连接。硬链接名称由dentry参数指定,连接对象是dir目录中ld_dentry目录想所代表的文件*/
        int (*unlink) (struct inode *, struct dentry *);
        /*该函数被系统调用unlink()调用,从目录dir中删除由目录项dentry制动的索引节点对象*/
        int (*symlink) (struct inode *, struct dentry *, const char *);
        /*该函数被系统电泳symlik()调用,创建符号连接,该符号连接名称由symname指定,连接对象是dir目录中的dentry目录项*/
        int (*mkdir) (struct inode *, struct dentry *, int);
        /*该函数被mkdir()调用,创建一个新鲁姆。创建时使用mode制定的初始模式*/
        int (*rmdir) (struct inode *, struct dentry *);
        /*该函数被系统调用rmdir()调用,删除dir目录中的dentry目录项代表的文件*/
        int (*mknod) (struct inode *, struct dentry *, int, dev_t);
        /*该函数被系统调用mknod()调用,创建特殊文件(设备文件、命名管道或套接字)。要创建的文件放在dir目录中,其目录项问dentry,关联的设备为rdev,初始权限由mode指定*/
        int (*rename) (struct inode *, struct dentry *,
                       struct inode *, struct dentry *);
        /*VFS调用该函数来移动文件。文件源路径在old_dir目录中,源文件由old_dentry目录项所指定,目标路径在new_dir目录中,目标文件由new_dentry指定*/
        int (*readlink) (struct dentry *, char *, int);
        /*该函数被系统调用readlink()调用,拷贝数据到特定的缓冲buffer中。拷贝的数据来自dentry指定的符号链接,最大拷贝大小可达到buflen字节*/
        int (*follow_link) (struct dentry *, struct nameidata *);
        /*该函数由VFS调用,从一个符号连接查找他指向的索引节点,由dentry指向的连接被解析*/
        int (*put_link) (struct dentry *, struct nameidata *);
        /*在follow_link()调用之后,该函数由vfs调用进行清楚工作*/
        void (*truncate) (struct inode *);
        /*该函数由VFS调用,修改文件的大小,在调用之前,索引节点的i_size项必须被设置成预期的大小*/
        int (*permission) (struct inode *, int);
        /*该函数用来检查给低昂的inode所代表的文件是否允许特定的访问模式,如果允许特定的访问模式,返回0,否则返回负值的错误码。多数文件系统 都将此区域设置为null,使用VFS提供的通用方法进行检查,这种检查操作仅仅比较索引及诶但对象中的访问模式位是否和mask一致,比较复杂的系统, 比如支持访问控制链(ACL)的文件系统,需要使用特殊的permission()方法*/
        int (*setattr) (struct dentry *, struct iattr *);
        /*该函数被notify_change调用,在修改索引节点之后,通知发生了改变事件*/
        int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
        /*在通知索引节点需要从磁盘中更新时,VFS会调用该函数*/
        int (*setxattr) (struct dentry *, const char *,
                         const void *, size_t, int);
        /*该函数由VFS调用,向dentry指定的文件设置扩展属性,属性名为name,值为value*/
        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        /*该函数被VFS调用,向value中拷贝给定文件的扩展属性name对应的数值*/
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        /*该函数将特定文件所有属性别表拷贝到一个缓冲列表中*/
        int (*removexattr) (struct dentry *, const char *);
        /*该函数从给定文件中删除指定的属性*/
};
Copy after login

4.Linux struct file structure
The struct file structure is defined in /linux/include /linux/fs.h (Linux 2.6.11 kernel), its prototype is:

struct file {
        /*
         * fu_list becomes invalid after file_free is called and queued via
         * fu_rcuhead for RCU freeing
         */
        union {
                struct list_head        fu_list;
                struct rcu_head         fu_rcuhead;
        } f_u;
        struct path             f_path;
#define f_dentry        f_path.dentry
#define f_vfsmnt        f_path.mnt
        const struct file_operations    *f_op;
        atomic_t                f_count;
        unsigned int            f_flags;
        mode_t                  f_mode;
        loff_t                  f_pos;
        struct fown_struct      f_owner;
        unsigned int            f_uid, f_gid;
        struct file_ra_state    f_ra;
        unsigned long           f_version;
#ifdef CONFIG_SECURITY
        void                    *f_security;
#endif
        /* needed for tty driver, and maybe others */
        void                    *private_data;
#ifdef CONFIG_EPOLL
        /* Used by fs/eventpoll.c to link all the hooks to this file */
        struct list_head        f_ep_links;
        spinlock_t              f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
        struct address_space    *f_mapping;
};
Copy after login

In the system kernel space, each open file has a corresponding struct file. When a file is opened and operated on, the kernel creates a descriptor for the file and passes it to the relevant functions. The kernel releases this data structure after all instances of the file have been closed. Usually in kernel creation and driver source code, pointers to struct files are named file or filp.

The above is the detailed content of Does Linux have kernel file operation functions?. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template