Rumah >masalah biasa >Adakah linux mempunyai fungsi operasi fail kernel?
Linux mempunyai fungsi operasi fail kernel Contohnya, fungsi filp_open() boleh digunakan untuk membuka fail, fungsi vfs_read() boleh digunakan untuk membaca fail, fungsi vfs_write() boleh digunakan untuk menulis. fail, dan fungsi filp_close() boleh digunakan untuk menutup fail . Dalam fungsi vfs_read dan vfs_write, parameter kedua menghala ke alamat memori ruang pengguna Jika penunjuk ruang kernel digunakan secara langsung, "-EFALUT" akan dikembalikan.
Persekitaran pengendalian tutorial ini: sistem linux7.3, komputer Dell G3.
1. Operasi fail ruang kernel
功能 | 函数原型 |
---|---|
打开文件 | 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 🎜>Dalam fungsi vfs_read dan vfs_write, alamat memori ruang pengguna yang ditunjuk oleh buf parameternya, jika kita terus menggunakan penunjuk ruang kernel, -EFALUT akan dikembalikan. Ini kerana penimbal yang digunakan melebihi julat alamat ruang pengguna. Panggilan sistem umum memerlukan penimbal yang anda gunakan tidak boleh berada di kawasan kernel. Ini boleh diselesaikan dengan
.set_fs()、get_fs()
Dalam
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))Jika digunakan, ia adalah seperti berikut:
mm_segment_t fs = get_fs(); set_fs(KERNEL_FS); //vfs_write(); vfs_read(); set_fs(fs);Penjelasan terperinci
: Panggilan sistem pada asalnya disediakan untuk akses program dalam ruang pengguna Oleh itu, untuk parameter yang dihantar kepadanya (seperti buf di atas), ia akan dianggap datang dari ruang pengguna secara lalai fungsi baca atau tulis(), untuk melindungi ruang kernel, nilai yang diperolehi oleh biasanya digunakan untuk membandingkannya dengan USER_DS untuk menghalang program ruang pengguna daripada "sengaja" memusnahkan ruang kernel sekarang, panggilan sistem digunakan dalam ruang kernel dan dihantar untuk membaca atau menulis(). Alamat parameter ialah alamat ruang kernel, yang berada di atas USER_DS (USER_DS ~ KERNEL_DS) jika tiada pemprosesan lain dilakukan, dalam fungsi write(). alamat akan dianggap berada di luar julat USER_DS, jadi ia akan dianggap berada dalam ruang pengguna "Pemusnahan yang disengajakan", oleh itu tidak membenarkan pelaksanaan selanjutnya untuk menyelesaikan masalah ini meluaskan had ruang yang boleh diaksesnya KERNEL_DS, supaya panggilan sistem boleh digunakan dengan lancar dalam kernel! get_fs()
set_fs(KERNEL_DS)
3.Struktur inod struct Linux
/*索引节点对象由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 *); /*该函数从给定文件中删除指定的属性*/ };
4.Struktur fail struct Linux Struktur fail struct ditakrifkan dalam /linux/include/linux/fs.h (Linux 2.6.11 kernel), dan prototaipnya ialah:
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; };
Cadangan berkaitan: "
Tutorial Video LinuxAtas ialah kandungan terperinci Adakah linux mempunyai fungsi operasi fail kernel?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!