久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

在linux內(nèi)核中操作文件的方法

 womking 2009-04-15

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/syscalls.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>

#define MY_FILE "/root/LogFile"

char buf[128];
struct file *file = NULL;



static int __init init(void)
{
        mm_segment_t old_fs;
        printk("Hello, I'm the module that intends to write messages to file.\n");


        if(file == NULL)
                file = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0644);
        if (IS_ERR(file)) {
                printk("error occured while opening file %s, exiting...\n", MY_FILE);
                return 0;
        }

        sprintf(buf,"%s", "The Messages.");

        old_fs = get_fs();
        set_fs(KERNEL_DS);
        file->f_op->write(file, (char *)buf, sizeof(buf), &file->f_pos);
        set_fs(old_fs);


        return 0;
}

static void __exit fini(void)
{
        if(file != NULL)
                filp_close(file, NULL);
}

module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");

其中:
   
typedef struct {
         unsigned long seg;
    } mm_segment_t;

    #define KERNEL_DS    MAKE_MM_SEG(0xFFFFFFFFUL)

    #define MAKE_MM_SEG(s)    ((mm_segment_t) { (s) })

基本思想:
  
一個(gè)是要記得編譯的時(shí)候加上-D__KERNEL_SYSCALLS__  
  另外源文件里面要#include   <linux/unistd.h>  
  如果報(bào)錯(cuò),,很可能是因?yàn)槭褂玫木彌_區(qū)超過(guò)了用戶空間的地址范圍。一般系統(tǒng)調(diào)用會(huì)要求你使用的緩沖區(qū)不能在內(nèi)核區(qū),。這個(gè)可以用set_fs(),、get_fs()來(lái)解決。在讀寫(xiě)文件前先得到當(dāng)前fs:  
  mm_segment_t   old_fs=get_fs();  
  并設(shè)置當(dāng)前fs為內(nèi)核fs:set_fs(KERNEL_DS);  
  在讀寫(xiě)文件后再恢復(fù)原先f(wàn)s:   set_fs(old_fs);  
  set_fs(),、get_fs()等相關(guān)宏在文件include/asm/uaccess.h中定義,。  
  個(gè)人感覺(jué)這個(gè)辦法比較簡(jiǎn)單。  
   
  另外就是用flip_open函數(shù)打開(kāi)文件,,得到struct file *的指針fp,。使用指針fp進(jìn)行相應(yīng)操作,如讀文件可以用fp->f_ops->read,。最后用filp_close()函數(shù)關(guān)閉文件,。 filp_open()、filp_close()函數(shù)在fs/open.c定義,,在include/linux/fs.h中聲明,。 

解釋一點(diǎn):
   
系統(tǒng)調(diào)用本來(lái)是提供給用戶空間的程序訪問(wèn)的,所以,,對(duì)傳遞給它的參數(shù)(比如上面的buf),,它默認(rèn)會(huì)認(rèn)為來(lái)自用戶空間,,在->write()函數(shù)中,為了保護(hù)內(nèi)核空間,,一般會(huì)用get_fs()得到的值來(lái)和USER_DS進(jìn)行比較,,從而防止用戶空間程序“蓄意”破壞內(nèi)核空間;

   而現(xiàn)在要在內(nèi)核空間使用系統(tǒng)調(diào)用,,此時(shí)傳遞給->write()的參數(shù)地址就是內(nèi)核空間的地址了,,在USER_DS之上(USER_DS ~ KERNEL_DS),如果不做任何其它處理,,在write()函數(shù)中,,會(huì)認(rèn)為該地址超過(guò)了USER_DS范圍,所以會(huì)認(rèn)為是用戶空間的“蓄意破壞”,,從而不允許進(jìn)一步的執(zhí)行,; 為了解決這個(gè)問(wèn)題; set_fs(KERNEL_DS);將其能訪問(wèn)的空間限制擴(kuò)大到KERNEL_DS,這樣就可以在內(nèi)核順利使用系統(tǒng)調(diào)用了,!

補(bǔ)充:
    我看了一下源碼,,在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))

而它的注釋也很清楚:
/*
* The fs value determines whether argument validity checking should be
* performed or not. If get_fs() == USER_DS, checking is performed, with
* get_fs() == KERNEL_DS, checking is bypassed.
*
* For historical reasons, these macros are grossly misnamed.
*/

因此可以看到,,fs的值是作為是否進(jìn)行參數(shù)檢查的標(biāo)志,。系統(tǒng)調(diào)用的參數(shù)要求必須來(lái)自用戶空間,所以,,當(dāng)在內(nèi)核中使用系統(tǒng)調(diào)用的時(shí)候,,set_fs(get_ds())改變了用戶空間的限制,即擴(kuò)大了用戶空間范圍,,因此即可使用在內(nèi)核中的參數(shù)了,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多