IT貓撲網(wǎng):您身邊最放心的安全下載站! 最新更新|軟件分類|軟件專題|手機(jī)版|論壇轉(zhuǎn)貼|軟件發(fā)布

您當(dāng)前所在位置: 首頁操作系統(tǒng)LINUX → 在linux內(nèi)核中操作文件的方法

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

時間:2015-06-28 00:00:00 來源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評論(1)

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #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) })

  基本思想:

  一個是要記得編譯的時候加上-D__KERNEL_SYSCALLS__

  另外源文件里面要#include??

  如果報錯,很可能是因為使用的緩沖區(qū)超過了用戶空間的地址范圍。一般系統(tǒng)調(diào)用會要求你使用的緩沖區(qū)不能在內(nèi)核區(qū)。這個可以用set_fs()、get_fs()來解決。在讀寫文件前先得到當(dāng)前fs:

  mm_segment_t?? old_fs=get_fs();

  并設(shè)置當(dāng)前fs為內(nèi)核fs:set_fs(KERNEL_DS);

  在讀寫文件后再恢復(fù)原先fs:?? set_fs(old_fs);

  set_fs()、get_fs()等相關(guān)宏在文件include/asm/uaccess.h中定義。

  個人感覺這個辦法比較簡單。

  另外就是用flip_open函數(shù)打開文件,得到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中聲明。

  解釋一點:

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

  而現(xiàn)在要在內(nèi)核空間使用系統(tǒng)調(diào)用,此時傳遞給->write()的參數(shù)地址就是內(nèi)核空間的地址了,在USER_DS之上(USER_DS ~ KERNEL_DS),如果不做任何其它處理,在write()函數(shù)中,會認(rèn)為該地址超過了USER_DS范圍,所以會認(rèn)為是用戶空間的"蓄意破壞",從而不允許進(jìn)一步的執(zhí)行; 為了解決這個問題; set_fs(KERNEL_DS);將其能訪問的空間限制擴(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ù)要求必須來自用戶空間,所以,當(dāng)在內(nèi)核中使用系統(tǒng)調(diào)用的時候,set_fs(get_ds())改變了用戶空間的限制,即擴(kuò)大了用戶空間范圍,因此即可使用在內(nèi)核中的參數(shù)了。

關(guān)鍵詞標(biāo)簽:linux內(nèi)核

相關(guān)閱讀

文章評論
發(fā)表評論

熱門文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 多種操作系統(tǒng)NTP客戶端配置 多種操作系統(tǒng)NTP客戶端配置 Linux操作系統(tǒng)修改IP Linux操作系統(tǒng)修改IP

相關(guān)下載

    人氣排行 Linux下獲取CPUID、硬盤序列號與MAC地址 dmidecode命令查看內(nèi)存型號 linux tc實現(xiàn)ip流量限制 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 linux下解壓rar文件 lcx.exe、nc.exe、sc.exe入侵中的使用方法 Ubuntu linux 關(guān)機(jī)、重啟、注銷 命令 查看linux服務(wù)器硬盤IO讀寫負(fù)載