溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

linux有沒有內(nèi)核文件操作函數(shù)

發(fā)布時間:2023-03-02 11:04:25 來源:億速云 閱讀:100 作者:iii 欄目:建站服務器

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

linux有內(nèi)核文件操作函數(shù),例filp_open()函數(shù)可用于打開文件、vfs_read()函數(shù)可用于讀取文件、vfs_write()函數(shù)可用于寫文件、filp_close()函數(shù)可用于關(guān)閉文件。在vfs_read和vfs_write函數(shù)中,其第二個參數(shù)指向的用戶空間的內(nèi)存地址,如果直接使用內(nèi)核空間的指針,則會返回“-EFALUT”。

1. 內(nèi)核空間文件操作

功能函數(shù)原型
打開文件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)
關(guān)閉文件int filp_close(struct file *filp, fl_owner_t id)

2. 內(nèi)核空間與用戶空間

在vfs_read和vfs_write函數(shù)中,其參數(shù)buf指向的用戶空間的內(nèi)存地址,如果我們直接使用內(nèi)核空間的指針,則會返回-EFALUT。這是因為使用的緩沖區(qū)超過了用戶空間的地址范圍。一般系統(tǒng)調(diào)用會要求你使用的緩沖區(qū)不能在內(nèi)核區(qū)。這個可以用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);

詳盡解釋:系統(tǒng)調(diào)用本來是提供給用戶空間的程序訪問的,所以,對傳遞給它的參數(shù)(比如上面的buf),它默認會認為來自用戶空間,在read或write()函數(shù)中,為了保護內(nèi)核空間,一般會用get_fs()得到的值來和USER_DS進行比較,從而防止用戶空間程序“蓄意”破壞內(nèi)核空間;而現(xiàn)在要在內(nèi)核空間使用系統(tǒng)調(diào)用,此時傳遞給read或write()的參數(shù)地址就是內(nèi)核空間的地址了,在USER_DS之上(USER_DS ~ KERNEL_DS),如果不做任何其它處理,在write()函數(shù)中,會認為該地址超過了USER_DS范圍,所以會認為是用戶空間的“蓄意破壞”,從而不允許進一步的執(zhí)行;為了解決這個問題set_fs(KERNEL_DS)將其能訪問的空間限制擴大到KERNEL_DS,這樣就可以在內(nèi)核順利使用系統(tǒng)調(diào)用了!

3.Linux struct inode結(jié)構(gòu)

/*索引節(jié)點對象由inode結(jié)構(gòu)體表示,定義文件在linux/fs.h中
*/
struct inode {
        struct hlist_node       i_hash;              /* 哈希表 */
        struct list_head        i_list;              /* 索引節(jié)點鏈表 */
        struct list_head        i_dentry;            /* 目錄項鏈表 */
        unsigned long           i_ino;               /* 節(jié)點號 */
        atomic_t                i_count;             /* 引用記數(shù) */
        umode_t                 i_mode;              /* 訪問權(quán)限控制 */
        unsigned int            i_nlink;             /* 硬鏈接數(shù) */
        uid_t                   i_uid;               /* 使用者id */
        gid_t                   i_gid;               /* 使用者id組 */
        kdev_t                  i_rdev;              /* 實設備標識符 */
        loff_t                  i_size;              /* 以字節(jié)為單位的文件大小 */
        struct timespec         i_atime;             /* 最后訪問時間 */
        struct timespec         i_mtime;             /* 最后修改(modify)時間 */
        struct timespec         i_ctime;             /* 最后改變(change)時間 */
        unsigned int            i_blkbits;           /* 以位為單位的塊大小 */
        unsigned long           i_blksize;           /* 以字節(jié)為單位的塊大小 */
        unsigned long           i_version;           /* 版本號 */
        unsigned long           i_blocks;            /* 文件的塊數(shù) */
        unsigned short          i_bytes;             /* 使用的字節(jié)數(shù) */
        spinlock_t              i_lock;              /* 自旋鎖 */
        struct rw_semaphore     i_alloc_sem;         /* 索引節(jié)點信號量 */
        struct inode_operations *i_op;               /* 索引節(jié)點操作表 */
        struct file_operations  *i_fop;              /* 默認的索引節(jié)點操作 */
        struct super_block      *i_sb;               /* 相關(guān)的超級塊 */
        struct file_lock        *i_flock;            /* 文件鎖鏈表 */
        struct address_space    *i_mapping;          /* 相關(guān)的地址映射 */
        struct address_space    i_data;              /* 設備地址映射 */
        struct dquot            *i_dquot[MAXQUOTAS]; /* 節(jié)點的磁盤限額 */
        struct list_head        i_devices;           /* 塊設備鏈表 */
        struct pipe_inode_info  *i_pipe;             /* 管道信息 */
        struct block_device     *i_bdev;             /* 塊設備驅(qū)動 */
        unsigned long           i_dnotify_mask;      /* 目錄通知掩碼 */
        struct dnotify_struct   *i_dnotify;          /* 目錄通知 */
        unsigned long           i_state;             /* 狀態(tài)標志 */
        unsigned long           dirtied_when;        /* 首次修改時間 */
        unsigned int            i_flags;             /* 文件系統(tǒng)標志 */
        unsigned char           i_sock;              /* 可能是個套接字吧 */
        atomic_t                i_writecount;        /* 寫者記數(shù) */
        void                    *i_security;         /* 安全模塊 */
        __u32                   i_generation;        /* 索引節(jié)點版本號 */
        union {
                void            *generic_ip;         /* 文件特殊信息 */
        } u;
};

/*
*索引節(jié)點的操作inode_operations定義在linux/fs.h中
*/
struct inode_operations {
        int (*create) (struct inode *, struct dentry *,int);
        /*VFS通過系統(tǒng)調(diào)用create()和open()來調(diào)用該函數(shù),從而為dentry對象創(chuàng)建一個新的索引節(jié)點。在創(chuàng)建時使用mode制定初始模式*/
        struct dentry * (*lookup) (struct inode *, struct dentry *);
        /*該韓式在特定目錄中尋找索引節(jié)點,該索引節(jié)點要對應于dentry中給出的文件名*/
        int (*link) (struct dentry *, struct inode *, struct dentry *);
        /*該函數(shù)被系統(tǒng)調(diào)用link()電泳,用來創(chuàng)建硬連接。硬鏈接名稱由dentry參數(shù)指定,連接對象是dir目錄中l(wèi)d_dentry目錄想所代表的文件*/
        int (*unlink) (struct inode *, struct dentry *);
        /*該函數(shù)被系統(tǒng)調(diào)用unlink()調(diào)用,從目錄dir中刪除由目錄項dentry制動的索引節(jié)點對象*/
        int (*symlink) (struct inode *, struct dentry *, const char *);
        /*該函數(shù)被系統(tǒng)電泳symlik()調(diào)用,創(chuàng)建符號連接,該符號連接名稱由symname指定,連接對象是dir目錄中的dentry目錄項*/
        int (*mkdir) (struct inode *, struct dentry *, int);
        /*該函數(shù)被mkdir()調(diào)用,創(chuàng)建一個新魯姆。創(chuàng)建時使用mode制定的初始模式*/
        int (*rmdir) (struct inode *, struct dentry *);
        /*該函數(shù)被系統(tǒng)調(diào)用rmdir()調(diào)用,刪除dir目錄中的dentry目錄項代表的文件*/
        int (*mknod) (struct inode *, struct dentry *, int, dev_t);
        /*該函數(shù)被系統(tǒng)調(diào)用mknod()調(diào)用,創(chuàng)建特殊文件(設備文件、命名管道或套接字)。要創(chuàng)建的文件放在dir目錄中,其目錄項問dentry,關(guān)聯(lián)的設備為rdev,初始權(quán)限由mode指定*/
        int (*rename) (struct inode *, struct dentry *,
                       struct inode *, struct dentry *);
        /*VFS調(diào)用該函數(shù)來移動文件。文件源路徑在old_dir目錄中,源文件由old_dentry目錄項所指定,目標路徑在new_dir目錄中,目標文件由new_dentry指定*/
        int (*readlink) (struct dentry *, char *, int);
        /*該函數(shù)被系統(tǒng)調(diào)用readlink()調(diào)用,拷貝數(shù)據(jù)到特定的緩沖buffer中。拷貝的數(shù)據(jù)來自dentry指定的符號鏈接,最大拷貝大小可達到buflen字節(jié)*/
        int (*follow_link) (struct dentry *, struct nameidata *);
        /*該函數(shù)由VFS調(diào)用,從一個符號連接查找他指向的索引節(jié)點,由dentry指向的連接被解析*/
        int (*put_link) (struct dentry *, struct nameidata *);
        /*在follow_link()調(diào)用之后,該函數(shù)由vfs調(diào)用進行清楚工作*/
        void (*truncate) (struct inode *);
        /*該函數(shù)由VFS調(diào)用,修改文件的大小,在調(diào)用之前,索引節(jié)點的i_size項必須被設置成預期的大小*/
        int (*permission) (struct inode *, int);
        /*該函數(shù)用來檢查給低昂的inode所代表的文件是否允許特定的訪問模式,如果允許特定的訪問模式,返回0,否則返回負值的錯誤碼。多數(shù)文件系統(tǒng) 都將此區(qū)域設置為null,使用VFS提供的通用方法進行檢查,這種檢查操作僅僅比較索引及誒但對象中的訪問模式位是否和mask一致,比較復雜的系統(tǒng), 比如支持訪問控制鏈(ACL)的文件系統(tǒng),需要使用特殊的permission()方法*/
        int (*setattr) (struct dentry *, struct iattr *);
        /*該函數(shù)被notify_change調(diào)用,在修改索引節(jié)點之后,通知發(fā)生了改變事件*/
        int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
        /*在通知索引節(jié)點需要從磁盤中更新時,VFS會調(diào)用該函數(shù)*/
        int (*setxattr) (struct dentry *, const char *,
                         const void *, size_t, int);
        /*該函數(shù)由VFS調(diào)用,向dentry指定的文件設置擴展屬性,屬性名為name,值為value*/
        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        /*該函數(shù)被VFS調(diào)用,向value中拷貝給定文件的擴展屬性name對應的數(shù)值*/
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        /*該函數(shù)將特定文件所有屬性別表拷貝到一個緩沖列表中*/
        int (*removexattr) (struct dentry *, const char *);
        /*該函數(shù)從給定文件中刪除指定的屬性*/
};

4.Linux struct file結(jié)構(gòu)
struct file結(jié)構(gòu)體定義在/linux/include/linux/fs.h(Linux 2.6.11內(nèi)核)中,其原型是:

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

文 件結(jié)構(gòu)體代表一個打開的文件,系統(tǒng)中的每個打開的文件在內(nèi)核空間都有一個關(guān)聯(lián)的struct file。它由內(nèi)核在打開文件時創(chuàng)建,并傳遞給在文件上進行操作的任何函數(shù)。在文件的所有實例都關(guān)閉后,內(nèi)核釋放這個數(shù)據(jù)結(jié)構(gòu)。在內(nèi)核創(chuàng)建和驅(qū)動源碼 中,struct file的指針通常被命名為file或filp。

到此,關(guān)于“l(fā)inux有沒有內(nèi)核文件操作函數(shù)”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI