久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

linux有沒有內核文件操作函數

187次閱讀
沒有評論

共計 6624 個字符,預計需要花費 17 分鐘才能閱讀完成。

這篇文章主要介紹“linux 有沒有內核文件操作函數”,在日常操作中,相信很多人在 linux 有沒有內核文件操作函數問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”linux 有沒有內核文件操作函數”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!

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。這是因為使用的緩沖區超過了用戶空間的地址范圍。一般系統調用會要求你使用的緩沖區不能在內核區。這個可以用 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, 這樣就可以在內核順利使用系統調用了!

3.Linux struct inode 結構

/* 索引節點對象由 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.Linux struct file 結構
struct file 結構體定義在 /linux/include/linux/fs.h(Linux 2.6.11 內核) 中,其原型是:

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;
};

文 件結構體代表一個打開的文件,系統中的每個打開的文件在內核空間都有一個關聯的 struct file。它由內核在打開文件時創建,并傳遞給在文件上進行操作的任何函數。在文件的所有實例都關閉后,內核釋放這個數據結構。在內核創建和驅動源碼 中,struct file 的指針通常被命名為 file 或 filp。

到此,關于“linux 有沒有內核文件操作函數”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-12發表,共計6624字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 旌德县| 嘉善县| 南漳县| 兴安县| 西吉县| 定安县| 阿巴嘎旗| 日照市| 玉屏| 肃宁县| 宝应县| 沁阳市| 登封市| 枣强县| 洛阳市| 襄樊市| 承德市| 读书| 巫溪县| 合肥市| 桦川县| 香港| 徐闻县| 拉萨市| 南昌市| 梅州市| 博罗县| 凤凰县| 安顺市| 介休市| 临汾市| 天台县| 金门县| 天长市| 京山县| 闻喜县| 贵港市| 吴江市| 庄河市| 伊吾县| 宝应县|