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

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
12345下一頁(yè)
最近訪問(wèn)板塊 發(fā)新帖
查看: 42567 | 回復(fù): 40
打印 上一主題 下一主題

內(nèi)核模塊中對(duì)文件的讀寫 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2009-12-12 14:42 |只看該作者 |倒序?yàn)g覽
平時(shí)網(wǎng)絡(luò)部分的東西碰的多些,這塊一開始還真不知道怎么寫,因?yàn)榭隙ê驮谟脩艨臻g下是不同的。google過(guò)后,得到以下答案。一般可以用兩種方法:第一種是用系統(tǒng)調(diào)用。第二種方法是filp->open()等函數(shù)。下面分別來(lái)說(shuō)下這兩種方法。


1 利用系統(tǒng)調(diào)用:
sys_open,sys_write,sys_read等。
其實(shí)分析過(guò)sys_open可以知道,最后調(diào)用的也是filp->open。
sys_open ==> do_sys_open ==> filp->open
在linuxsir上的一個(gè)帖子,上面一個(gè)版主說(shuō):sys_open和進(jìn)程緊密相關(guān),往往不在內(nèi)核中使用。
而其實(shí)sys_open最后也是調(diào)用了filp->open。
其實(shí)好像Linux2.6.20后面就不推薦使用sys_open,那我們這里就就后者進(jìn)行詳細(xì)的介紹

2 filp->open等函數(shù)。
在模塊中,用戶空間的open,read,write,llseek等函數(shù)都是不可以使用的。應(yīng)該使用其在內(nèi)核中對(duì)應(yīng)的函數(shù)?梢允褂胒ilp->open配合struct file里的read/write來(lái)進(jìn)行對(duì)文件的讀寫操作。


例子1:
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <asm/uaccess.h>
  5. #include <linux/mm.h>

  6. MODULE_AUTHOR("Kenthy@163.com.");
  7. MODULE_DESCRIPTION("Kernel study and test.");


  8. void fileread(const char * filename)
  9. {
  10.   struct file *filp;
  11.   struct inode *inode;
  12.   mm_segment_t fs;
  13.   off_t fsize;
  14.   char *buf;
  15.   unsigned long magic;
  16.   printk("<1>start....\n");
  17.   filp=filp_open(filename,O_RDONLY,0);
  18.   inode=filp->f_dentry->d_inode;  
  19.   
  20.   magic=inode->i_sb->s_magic;
  21.   printk("<1>file system magic:%li \n",magic);
  22.   printk("<1>super blocksize:%li \n",inode->i_sb->s_blocksize);
  23.   printk("<1>inode %li \n",inode->i_ino);
  24.   fsize=inode->i_size;
  25.   printk("<1>file size:%i \n",(int)fsize);
  26.   buf=(char *) kmalloc(fsize+1,GFP_ATOMIC);

  27.   fs=get_fs();
  28.   set_fs(KERNEL_DS);
  29.   filp->f_op->read(filp,buf,fsize,&(filp->f_pos));
  30.   set_fs(fs);

  31.   buf[fsize]='\0';
  32.   printk("<1>The File Content is:\n");
  33.   printk("<1>%s",buf);


  34.   filp_close(filp,NULL);
  35. }

  36. void filewrite(char* filename, char* data)
  37. {
  38.   struct file *filp;
  39. mm_segment_t fs;
  40. filp = filp_open(filename, O_RDWR|O_APPEND, 0644);
  41. if(IS_ERR(filp))
  42.     {
  43.       printk("open error...\n");
  44.       return;
  45.         }   

  46.   fs=get_fs();
  47.   set_fs(KERNEL_DS);
  48.   filp->f_op->write(filp, data, strlen(data),&filp->f_pos);
  49.   set_fs(fs);
  50.   filp_close(filp,NULL);
  51. }

  52. int init_module()
  53. {
  54.   char *filename="/root/test1.c";

  55.   printk("<1>Read File from Kernel.\n");
  56.   fileread(filename);
  57.   filewrite(filename, "kernel write test\n");
  58.   return 0;
  59. }

  60. void cleanup_module()
  61. {
  62.   printk("<1>Good,Bye!\n");
  63. }
復(fù)制代碼




eg2:
  1. #include<linux/module.h>
  2. #include<linux/kernel.h>
  3. #include<linux/init.h>

  4. #include<linux/types.h>

  5. #include<linux/fs.h>
  6. #include<linux/string.h>
  7. #include<asm/uaccess.h> /* get_fs(),set_fs(),get_ds() */

  8. #define FILE_DIR "/root/test.txt"

  9. MODULE_LICENSE("GPL");
  10. MODULE_AUTHOR("kenthy@163.com");

  11. char *buff = "module read/write test";
  12. char tmp[100];

  13. static struct file *filp = NULL;

  14. static int __init wr_test_init(void)
  15. {
  16.     mm_segment_t old_fs;
  17.     ssize_t ret;
  18.    
  19.     filp = filp_open(FILE_DIR, O_RDWR | O_CREAT, 0644);
  20.    
  21.     //    if(!filp)

  22.     if(IS_ERR(filp))
  23.         printk("open error...\n");
  24.    
  25.     old_fs = get_fs();
  26.     set_fs(get_ds());
  27.    
  28.     filp->f_op->write(filp, buff, strlen(buff), &filp->f_pos);
  29.    
  30.     filp->f_op->llseek(filp,0,0);
  31.     ret = filp->f_op->read(filp, tmp, strlen(buff), &filp->f_pos);
  32.    
  33.     set_fs(old_fs);
  34.    
  35.     if(ret > 0)
  36.         printk("%s\n",tmp);
  37.     else if(ret == 0)
  38.         printk("read nothing.............\n");
  39.     else
  40.         {
  41.             printk("read error\n");
  42.             return -1;
  43.         }

  44.     return 0;
  45. }

  46. static void __exit wr_test_exit(void)
  47. {
  48.     if(filp)
  49.         filp_close(filp,NULL);
  50. }

  51. module_init(wr_test_init);
  52. module_exit(wr_test_exit);
復(fù)制代碼




3.Makefile

  1. obj-m := os_attack.o

  2. KDIR := /lib/modules/$(uname -r)/build/
  3. PWD := $(shell pwd)

  4. all:module

  5. module:
  6.         $(MAKE) -C $(KDIR) M=$(PWD) modules


  7. clean:
  8.         rm -rf *.ko *.mod.c *.o Module.* modules.* .*.cmd .tmp_versions
復(fù)制代碼




注意:
在調(diào)用filp->f_op->read和filp->f_op->write等對(duì)文件的操作之前,應(yīng)該先設(shè)置FS。
默認(rèn)情況下,filp->f_op->read或者filp->f_op->write會(huì)對(duì)傳進(jìn)來(lái)的參數(shù)buff進(jìn)行指針檢查。如果不是在用戶空間會(huì)拒絕訪問(wèn)。因?yàn)槭窃趦?nèi)核模塊中,所以buff肯定不在用戶空間,所以要增大其尋址范圍。

拿filp->f_op->write為例來(lái)說(shuō)明:
filp->f_op->write最終會(huì)調(diào)用access_ok ==> range_ok.
而range_ok會(huì)判斷訪問(wèn)的地址是否在0 ~ addr_limit之間。如果在,則ok,繼續(xù)。如果不在,則禁止訪問(wèn)。而內(nèi)核空間傳過(guò)來(lái)的buff肯定大于addr_limit。所以要set_fs(get_ds())。
這些函數(shù)在asm/uaccess.h中定義。以下是這個(gè)頭文件中的部分內(nèi)容:

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

#define KERNEL_DS    MAKE_MM_SEG(-1UL)
#define USER_DS        MAKE_MM_SEG(PAGE_OFFSET)

#define get_ds()    (KERNEL_DS)
#define get_fs()    (current_thread_info()->addr_limit)
#define set_fs(x)    (current_thread_info()->addr_limit = (x))

#define segment_eq(a, b)    ((a).seg == (b).seg)


可以看到set_fs(get_ds())改變了addr_limit的值。這樣就使得從模塊中傳遞進(jìn)去的參數(shù)也可以正常使用了。

在寫測(cè)試模塊的時(shí)候,要實(shí)現(xiàn)的功能是寫進(jìn)去什么,然后讀出來(lái)放在tmp數(shù)組中。但寫完了以后filp->f_ops已經(jīng)在末尾了,這個(gè)時(shí)候讀是什么也讀不到的,如果想要讀到數(shù)據(jù),則應(yīng)該改變filp->f-ops的值,這就要用到filp->f_op->llseek函數(shù)了。上網(wǎng)查了下,其中的參數(shù)需要記下筆記:


系統(tǒng)調(diào)用:
off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
offset是偏移量。
若origin是SEEK_SET(0),則將該文件的位移量設(shè)置為距文件開始處offset 個(gè)字節(jié)。
若origin是SEEK_CUR(1),則將該文件的位移量設(shè)置為其當(dāng)前值加offset, offset可為正或負(fù)。
若origin是SEEK_END(2),則將該文件的位移量設(shè)置為文件長(zhǎng)度加offset, offset可為正或負(fù)。

ok,that's all.

評(píng)分

參與人數(shù) 3可用積分 +90 收起 理由
dreamice + 30 原創(chuàng)內(nèi)容
scutan + 30 精品文章
T-Bagwell + 30 精品文章

查看全部評(píng)分

論壇徽章:
0
2 [報(bào)告]
發(fā)表于 2009-12-12 15:01 |只看該作者

論壇徽章:
0
3 [報(bào)告]
發(fā)表于 2009-12-12 19:03 |只看該作者

論壇徽章:
36
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
4 [報(bào)告]
發(fā)表于 2009-12-12 21:18 |只看該作者
好文章啊。加精:wink:

論壇徽章:
36
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
5 [報(bào)告]
發(fā)表于 2009-12-12 21:20 |只看該作者
實(shí)際的開發(fā)中,確實(shí)有不少的情況需要在內(nèi)核態(tài)去讀寫文件的。

可以考慮調(diào)用sys_*系列的函數(shù),也可以直接調(diào)用內(nèi)核態(tài)中的文件操作的相關(guān)函數(shù)指針。

論壇徽章:
0
6 [報(bào)告]
發(fā)表于 2009-12-12 22:59 |只看該作者
以前干過(guò)類似的活,用的方法是LZ的方法1;

linux下很多東東抽象成了文件,這個(gè)東東用處可以擴(kuò)展到單純的讀寫文件以外的很多地方;

比如:
1、內(nèi)核態(tài)下使用socket;
2、struct task_struct中可以找到當(dāng)前進(jìn)程打開的文件,然后………………;
3、struct task_struct中還有當(dāng)前進(jìn)程控制臺(tái)的設(shè)備文件,活用一下狠容易就能在內(nèi)核態(tài)實(shí)現(xiàn)printf。

PS:個(gè)人認(rèn)為最有用的是第三條。

[ 本帖最后由 zyr-linux 于 2009-12-12 23:12 編輯 ]

論壇徽章:
0
7 [報(bào)告]
發(fā)表于 2009-12-13 13:42 |只看該作者
不錯(cuò),我以前是直接使用sys_open來(lái)做的。不過(guò)這種方式需要宏定義一下。

論壇徽章:
36
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
8 [報(bào)告]
發(fā)表于 2009-12-13 14:37 |只看該作者
原帖由 scutan 于 2009-12-13 13:42 發(fā)表
不錯(cuò),我以前是直接使用sys_open來(lái)做的。不過(guò)這種方式需要宏定義一下。

宏定義?

我記得使用的時(shí)候是得確保sys_open被EXPORT出來(lái)吧

論壇徽章:
36
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
9 [報(bào)告]
發(fā)表于 2009-12-13 14:38 |只看該作者
3、struct task_struct中還有當(dāng)前進(jìn)程控制臺(tái)的設(shè)備文件,活用一下狠容易就能在內(nèi)核態(tài)實(shí)現(xiàn)printf。

內(nèi)核態(tài)已經(jīng)有了printk,不知道這里內(nèi)核態(tài)實(shí)現(xiàn)printf指的那個(gè)方面?

論壇徽章:
0
10 [報(bào)告]
發(fā)表于 2009-12-13 20:36 |只看該作者
原帖由 Godbach 于 2009-12-13 14:38 發(fā)表

內(nèi)核態(tài)已經(jīng)有了printk,不知道這里內(nèi)核態(tài)實(shí)現(xiàn)printf指的那個(gè)方面?


要看printk打出來(lái)的東東,要么dmesg,要么kmsg,要么直接去翻message文件,總之不能直接看到;

printf倒是直接打到控制臺(tái)(串口,網(wǎng)口,顯示器等)上,隨打隨看,不過(guò)這是用戶態(tài)的東東;

通過(guò)task_struct中控制臺(tái)設(shè)備文件加上sys_open、sys_write等,可以在內(nèi)核態(tài)下直接向控制臺(tái)打印信息,

姑且稱為kprintf,對(duì)內(nèi)核態(tài)下交互式調(diào)試很有用。

[ 本帖最后由 zyr-linux 于 2009-12-13 20:39 編輯 ]
您需要登錄后才可以回帖 登錄 | 注冊(cè)

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

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP