亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2675 | 回復: 1
打印 上一主題 下一主題

linux 2.6.11內核文件IO的系統調用實現分析(flseek&close) [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2005-05-23 11:40 |只看該作者 |倒序瀏覽
    本帖是《linux 2.6.11內核文件IO的系統調用實現分析》的第三個部分,主要說明lseek函數和close的系統調用。前面兩部分說明如下:
    a)《linux 2.6.11內核文件IO的系統調用實現分析(open&creat)》,主要說明open和creat兩個文件IO的系統調用實現。
    b) 《linux 2.6.11內核文件IO的系統調用實現分析(read&write)》,主要說明read和write兩個文件IO的系統調用實現。

    8.        lseek函數
    8.1.        原型與參數
    off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
    每個打開文件都有一個與其相關聯的“當前文件位移量”。它是一個非負整數,用以度量從文件開始處計算的字節(jié)數。(本節(jié)稍后將對“非負”這一修飾詞的某些例外進行說明。)通常,讀、寫操作都從當前文件位移量處開始,并使位移量增加所讀或寫的字節(jié)數。按系統默認,當打開一個文件時,除非指定O_APPEND選擇項,否則該位移量被設置為0?梢哉{用lseek顯式地定位一個打開文件。
    對參數offset 的解釋與參數origin的值有關。
    • 若origin是SEEK_SET,則將該文件的位移量設置為距文件開始處offset 個字節(jié)。
    • 若origin是SEEK_CUR,則將該文件的位移量設置為其當前值加offset, offset可為正或負。
    • 若origin是SEEK_END,則將該文件的位移量設置為文件長度加offset, offset可為正或負。
    若lseek成功執(zhí)行,則返回新的文件位移量,為此可以用下列方式確定一個打開文件的當前位移量。這種方法也可用來確定所涉及的文件是否可以設置位移量。如果文件描述符引用的是一個管道或FIFO,則lseek返回-1,并將errno設置為EPIPE。
    以下文字引用《UNIX高級編程》,在以前的內核版本,origin參數名為whence:
    三個符號常數SEEK_SET,SEEK_CUR和SEEK_END是由系統V引進的。在系統V之前, whence被指定為0 (絕對位移量),1 ( 相對于當前位置的位移量)或2 (相對文件尾端的位移量)。很多軟件仍直接使用這些數字進行編碼。在lseek中的字符l表示長整型。在引入off_t數據類型之前, offset參數和返回值是長整型的。lseek是由V7引進的,當時C語言中增加了長整型。(在V6中,用函數seek和tell提供類似功能。)
    8.2.        實現分析
    8.2.1.        主要函數調用關系圖
    sys_lseek (參見8.2.2 )
    | ------------- vfs_llseek (參見8.2.3)
            |                         | ------------ default_llseek (參見8.2.4)
    8.2.2.        主調用函數sys_lseek
    asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
    {
            off_t retval;
            struct file * file;
            int fput_needed;

            retval = -EBADF;
    // 從進程文件鏈表中根據fd獲取file文件表,如果沒有這個文件表,則返回EBADF錯誤
            file = fget_light(fd, &fput_needed); // fput_needed標識是否需要更新file結構的使用計數器
            if (!file)
                    goto bad;

            retval = -EINVAL;
            if (origin <= 2) {
                    loff_t res = vfs_llseek(file, offset, origin); // 底層文件偏移操作,見8.2.3描述
                    retval = res;
                    if (res != (loff_t)retval)
                            retval = -EOVERFLOW;        /* LFS: should only happen on 32 bit platforms */
            }
            // 如果origin不是0.1.2,則釋放標識,返回EINVAL
            fput_light(file, fput_needed);
    bad:
            return retval; // 返回錯誤代碼
    }

    8.2.3.        sys_lseek子函數vfs_llseek
    loff_t vfs_llseek(struct file *file, loff_t offset, int origin)
    {
            loff_t (*fn)(struct file *, loff_t, int); // 文件系統統一的底層lseek函數接口

            fn = no_llseek; // 如果操作權限不夠或者驅動沒有實現該接口,則返回ESPIPE錯誤
            if (file->;f_mode & FMODE_LSEEK) {// 檢測是否有LSEEK的操作權限
                    fn = default_llseek; // 默認的LSEEK實現函數,見8.2.4描述
                    if (file->;f_op && file->;f_op->;llseek)
                            fn = file->;f_op->;llseek; // 文件模塊實現的LSEEK函數
            }
            return fn(file, offset, origin); // 按照前面的接口函數執(zhí)行LSEEK操作并返回結果。
    }

    8.2.4.        vfs_llseek子函數default_llseek
    loff_t default_llseek(struct file *file, loff_t offset, int origin)
    {
            long long retval;

            lock_kernel();
            switch (origin) {
                    case 2: // 文件結尾向后偏移offset個字節(jié)
                            offset += i_size_read(file->;f_dentry->;d_inode);
                            break;
                    case 1: // 當前位置向后偏移offset個字節(jié)
                            offset += file->;f_pos;
            }
            retval = -EINVAL;
            if (offset >;= 0) {
                    if (offset != file->;f_pos) {
                            file->;f_pos = offset; // 刷新文件當前位置記錄
                            file->;f_version = 0; // 更新文件version記錄
                    }
                    retval = offset;
            }
            unlock_kernel();
            return retval;
    }

    9.        close函數
    9.1.        函數原型與參數
    int close (int f i l e d e s)
    關閉一個文件時也釋放該進程加在該文件上的所有記錄鎖。當一個進程終止時,它所有的打開文件都由內核自動關閉。很多程序都使用這一功能而不顯式地用c l o s e關閉打開的文件。對于對個任務同時操作該文件時,需要先釋放該句柄,才能關閉。
    9.2.        實現分析
    9.2.1.        主要函數調用關系圖
    sys_close (參見9.2.2 )
    | ------------- filp_close (參見9.2.3)
    9.2.2.        主調用函數sys_close
    asmlinkage long sys_close(unsigned int fd)
    {
            struct file * filp;
            struct files_struct *files = current->;files; // 進程的文件指針向量表

            spin_lock(&files->;file_lock);
            if (fd >;= files->;max_fds) // 超過進程最大句柄數,則返回EBADF
                    goto out_unlock;
            filp = files->;fd[fd];  // 從向量表中獲取當前文件句柄對應的文件結構
            if (!filp) // 不存在,則返回EBADF
                    goto out_unlock;
            files->;fd[fd] = NULL; // 從句柄列表中清除該fd記錄
            FD_CLR(fd, files->;close_on_exec); // 從關閉隊列中清除該記錄
            __put_unused_fd(files, fd); // 刷新進程文件指針向量表
            spin_unlock(&files->;file_lock);
            return filp_close(filp, files); // 調用子函數關閉,參見9.2.3說明

    out_unlock:
            spin_unlock(&files->;file_lock);
            return -EBADF;
    }

    9.2.3.        sys_clsoe子函數filp_close
    int filp_close(struct file *filp, fl_owner_t id)
    {
            int retval;

            retval = filp->;f_error; //清除出錯標識
            if (retval)
                    filp->;f_error = 0;

            if (!file_count(filp)) {// 獲取當前使用文件句柄的任務數目,如果有其他任務占用,則返回
                    printk(KERN_ERR "VFS: Close: file count is 0\n";
                    return retval;
            }

            if (filp->;f_op && filp->;f_op->;flush) {
                    int err = filp->;f_op->;flush(filp); //調用文件模塊函數執(zhí)行flush操作。
                    if (!retval)
                            retval = err;
            }

            dnotify_flush(filp, id); // 釋放內核緩存
            locks_remove_posix(filp, id); // 釋放該文件結構實例的posix同步鎖
            fput(filp);
            return retval;
    }

    9.3.        小結
    主調用函數主要實現進程文件指針向量表的刷新。而filp_close則實現了內核和具體的文件驅動模塊對文件結構的關閉操作。

論壇徽章:
0
2 [報告]
發(fā)表于 2005-05-31 17:09 |只看該作者

linux 2.6.11內核文件IO的系統調用實現分析(flseek&close)

看來lseek函數的實現要簡單一點,大致是從管理層更改文件結構中對應的位置指針標識啊。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯網協會會員  聯系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP