日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

[linux-nopage]内存映射虚拟字符设备驱动【P119】

發(fā)布時間:2025/1/21 linux 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [linux-nopage]内存映射虚拟字符设备驱动【P119】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

      • 目的:內(nèi)核空間映射到用戶空間
      • 環(huán)境:Ubuntu 20.04 linux內(nèi)核源碼5.11.0-37-generic(版本自選)
      • 實驗結(jié)果
      • 實驗知識點
      • 實驗難點
      • 實驗代碼
        • nopage.c
        • Makefile
        • np_test.c
      • 調(diào)試過程
        • make
        • sudo insmod nopage.ko
        • sudo mknod /dev/nopage c 92 0 (這里的92是你前面申請的設(shè)備號)
        • gcc np_test.c -o ntest

目的:內(nèi)核空間映射到用戶空間

一個虛擬字符設(shè)備驅(qū)動程序,將內(nèi)核空間映射到用戶空間

  • 找到內(nèi)核地址對應(yīng)的物理地址
  • 建立新的用戶表項
  • 環(huán)境:Ubuntu 20.04 linux內(nèi)核源碼5.11.0-37-generic(版本自選)

    實驗結(jié)果

  • 這是最終的實驗結(jié)果圖,中間出現(xiàn)了很多錯誤結(jié)果【錯誤過程在錯誤分析】
  • 實驗知識點

  • 加載內(nèi)核模塊是什么意思
  • 將自己編寫的驅(qū)動程序加載到內(nèi)核當(dāng)中,linux強大在一切皆文件,實現(xiàn)高類聚低耦合的特點,模塊封裝
    給linux無限可能的機會

  • 如何加載
  • 實驗難點

  • 沒接觸過linux 編譯,前期知識點
    Makefile 文件的作用

  • 類似腳本,將編譯的大部分內(nèi)容寫在Makefile文件內(nèi)(該文件要和編譯的.c文件在同一個目錄下)
    剛開是只有

    這三個文件,其他文件大部分是經(jīng)過make 編譯產(chǎn)生的

    這是教程的一張圖,解釋大部分內(nèi)容對應(yīng)我下面的Makefile 文件內(nèi)容
  • make 指令的作用

  • make 會進入Makefile 文件;根據(jù)Makefile 進行編譯
    根據(jù)Makefile文件編譯源代碼、連接、生成目標文件、可執(zhí)行文件。 簡單理解就是執(zhí)行Makefile這個腳本;
    • 向內(nèi)核添加模塊:
  • 編寫驅(qū)動程序文件

  • 將驅(qū)動文件放置到linux 內(nèi)核源碼相應(yīng)的目錄下

  • 在目錄Kconfig 文件中添加新驅(qū)動程序?qū)?yīng)的項目編譯選擇

  • 在目錄Makefile文件中添加新的驅(qū)動程序編譯語句

  • 怎么編譯進內(nèi)核

  • 根據(jù)Makefile 指定的內(nèi)核地址進入到內(nèi)核中;

    這是我調(diào)試錯誤過程的一種圖,看見執(zhí)行make先進入指定的內(nèi)核地址,內(nèi)核內(nèi)也有Makefile文件;
    定位到140行:
    中間花費了一點時間在這里調(diào)試,后期發(fā)現(xiàn)主要bug不在這里;

    主要bug 還是因為沒有安裝gcc
    這里花費時間是因為一開始我檢測系統(tǒng)發(fā)現(xiàn)已經(jīng)有g(shù)cc, 后來在編譯文件才發(fā)現(xiàn)系統(tǒng)的gcc不能用,前兩個是系統(tǒng)自帶的。才導(dǎo)致我花了大量時間
    最后一個是我后來安裝上的 sudo apt install gcc

  • 遇到錯誤怎么排錯
  • google baidu 教材

  • 課本的指令是什么意思
  • make # 編譯
    insmod xxx.ko # 根據(jù)編譯結(jié)果會產(chǎn)生.ko文件,此時會執(zhí)行module_init(xxx)函數(shù)

    通過命令 dmesg | tail 最后幾行可以發(fā)現(xiàn) 經(jīng)過insmod 之后進入init函數(shù)
    前兩句是插入的模塊未在模塊樹內(nèi),也就是外來模塊會提示這一消息,學(xué)習(xí)過程可以忽略;

    實驗代碼

    nopage.c

    #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/fcntl.h>#include <linux/vmalloc.h> //空間分配到堆 #include <linux/uaccess.h> #include <linux/io.h>#include <asm/page.h> #include <linux/mm.h> //重點學(xué)習(xí)#define MMAPNOPAGE_DEV_NAME "nopage" //字符設(shè)備名稱 #define MMAPNOPAGE_DEV_MAJOR 92 //字符設(shè)備號#define SHARE_MEM_PAGE_COUNT 4 //共享頁數(shù) #define SHARE_MEM_SIZE (PAGE_SIZE*SHARE_MEM_PAGE_COUNT)char *share_memory=NULL;vm_fault_t mmapnopage_vm_fault(struct vm_fault *vmf) //這個函數(shù)跟之前版本的函數(shù)不同,這個形參只有一個,這個要在mm.h下查看才能確定不同版本不同 {struct page *page;unsigned long offset;void *page_ptr;struct vm_area_struct *vma=vmf->vma; //早期版本該變量時形參,現(xiàn)在已經(jīng)在vm_fault 結(jié)構(gòu)體內(nèi)定義直接使用printk("\n");printk("%-25s %08x\n","1)vma->flags",vmf->flags);printk("%-25s %08lx\n","2)vmf->pgoff",vmf->pgoff);printk("%-25s %08lx\n","3)vmf->virtual_address",vmf->address); // 虛擬存儲區(qū)中斷地址變量為address 更之前也有差別,在mm.h 下可以找到對應(yīng) 變量為long unsigned int 跟之前的有區(qū)別printk("%-25s %08lx\n","4)vma->vm_start",vma->vm_start);printk("%-25s %08lx\n","5)vma->vm_end",vma->vm_end);printk("%-25s %08lx\n","6)vma->vm_pgoff",vma->vm_pgoff);/*printk("%-25s %d\n","7)PAGE_SHIFT",PAGE_SHIFT);*/page_ptr=NULL;if((NULL==vma)||(NULL==share_memory)){printk("return VM_FAULT_SIGBUS!\n");return VM_FAULT_SIGBUS;}offset=vmf->address-vma->vm_start; //偏移量if(offset>=SHARE_MEM_SIZE){printk("return VM_FAULT_SIGBUS!");return VM_FAULT_SIGBUS;}page_ptr=share_memory+offset;page=vmalloc_to_page(page_ptr);get_page(page);vmf->page=page;return 0; }struct vm_operations_struct mmapnopage_vm_ops={.fault=mmapnopage_vm_fault, //中斷 };int mmapnopage_mmap(struct file *filp,struct vm_area_struct *vma) {vma->vm_flags |= VM_NORESERVE; //缺頁映射vma->vm_ops=&mmapnopage_vm_ops;return 0; }struct file_operations mmapnopage_fops={ //文件操作.owner=THIS_MODULE, .mmap=mmapnopage_mmap, };int mmapnopage_init(void) //執(zhí)行insmod 時進入這個函數(shù) {int lp;int result;result=register_chrdev(MMAPNOPAGE_DEV_MAJOR,MMAPNOPAGE_DEV_NAME,&mmapnopage_fops);if(result<0){printk("regist fails!");return result;}share_memory=vmalloc(SHARE_MEM_SIZE);for(lp=0;lp<SHARE_MEM_PAGE_COUNT;lp++){sprintf(share_memory+PAGE_SIZE*lp,"TEST %d",lp); //向字符設(shè)備寫入信息}printk("registing...!");return 0; }void mmapnopage_exit(void) //執(zhí)行rmmod 時進入該函數(shù) {if(share_memory!=NULL){vfree(share_memory);}unregister_chrdev(MMAPNOPAGE_DEV_MAJOR,MMAPNOPAGE_DEV_NAME); }module_init(mmapnopage_init); module_exit(mmapnopage_exit);MODULE_LICENSE("Dual BSD/GPL");

    Makefile

    下面的Makefile 文件我添加了注釋可能在命令后面多了空格,make會識別錯誤

    ifeq ($(KERNELRELEASE),) //搭配上面的教程使用 CONFIG_MODULE_SIG=n //說是為了避開數(shù)字簽名,加了發(fā)現(xiàn)也沒用 PWD :=$(shell pwd) //pwd 表示當(dāng)前工作目錄 present work direction KERSRC := /lib/modules/$(shell uname -r)/build/ //unama -r 指向當(dāng)前的內(nèi)核版本modules:$(MAKE) -C $(KERSRC) M=$(PWD) modules // 執(zhí)行內(nèi)核模塊的編譯 moules_install:$(MAKE) -C $(KERSRC) M=$(PWD) modules_install // 將模塊安裝到對應(yīng)的模塊路徑只有modules_install 執(zhí)行才觸發(fā) .PHONY: modules modules_install clean //wei clean:-rm -rf *.o *.cmd.* *.ko //刪除中間標識文件 else modules-objs :=nopage.o obj-m := nopage.o //將nopage.o 編譯為nopage.koendif

    這個Makefile 和 上面是一樣的;

    ifeq ($(KERNELRELEASE),) CONFIG_MODULE_SIG=n PWD :=$(shell pwd) KERSRC := /lib/modules/$(shell uname -r)/build/modules:$(MAKE) -C $(KERSRC) M=$(PWD) modules moules_install:$(MAKE) -C $(KERSRC) M=$(PWD) modules_install .PHONY: modules modules_install clean clean:-rm -rf *.o *.cmd.* *.ko else modules-objs :=mmapnopage.o obj-m := mmapnopage.oendif

    np_test.c

    #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h>// #define DEVICE_FILENAME "/dev/mmapnopage" #define DEVICE_FILENAME "/dev/nopage"#define SHARE_MEM_PAGE_COUNT 4 #define SHARE_MEM_SIZE (4096*SHARE_MEM_PAGE_COUNT)int main() {int dev;int loop;char *ptrdata;dev=open(DEVICE_FILENAME,O_RDWR|O_NDELAY); //設(shè)備打開成功,返回句柄大于0if(dev < 0)printf("can't open nopage\n"); // return < 0 fail! if(dev>=0){printf("open file success!\n");ptrdata=(char*)mmap(0,SHARE_MEM_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,dev,0);for(loop=0;loop<SHARE_MEM_PAGE_COUNT;loop++){printf("[%-10s----%s]\n",ptrdata+4096*loop,ptrdata+4096*loop);}munmap(ptrdata,SHARE_MEM_SIZE);close(dev);}return 0; }

    調(diào)試過程

    實驗出現(xiàn)的錯誤:

  • Makefile 文件
    Makefile missing separator. Stop.
  • 這是由于Makefile 文件中的空格鍵個數(shù)和tab鍵導(dǎo)致的
    No rule to make target ‘make’, needed by ‘modules’
    解決方法:文本打開直接使用tab 鍵,不要用空格代替,Makefile以空格為命令行的分界,對符號敏感

    進入Makefile文件


    沒有進入ifeq條件
    猜想應(yīng)該是.config 文件這個變量設(shè)置問題
    找到.config 發(fā)現(xiàn)沒有找到該變量

    .config 在當(dāng)前源碼里面下
    針對這個問題查看資料源碼花費了很多時間還是沒能解決
    就進入下一個問題

  • gcc 沒有發(fā)現(xiàn),首先查找有沒有安裝
  • 發(fā)現(xiàn)有安裝(最后一個是最后安裝上的)(其實主要原因還是沒有安裝gcc)系統(tǒng)自帶的不能用;

    后面嘗試編譯一個文件gcc hello.c -o test # 這個是我用來測試用的
    發(fā)現(xiàn)這個時候找不到gcc
    于是

    sudo apt-get install gcc
    產(chǎn)生這么多錯誤的原因是沒有 sudo apt install gcc;
    在排除上面這個問題的過程中花了很多時間
    現(xiàn)在終于進入到錯誤里面

    上面是環(huán)境問題還沒進入到代碼里;

    接下來調(diào)試才真正進入調(diào)試階段;


    進入到頭文件

    這是mm.h文件下

    兩個錯誤修改地址后
    note: each undeclared identifier is reported only once for each function it appears in

    71行20列定位;

    make

    Make 編譯成功:

    sudo insmod nopage.ko

    insmod: ERROR: could not insert module mmapnopage.ko: Device or resource busy
    這是因為申請的設(shè)備號被占用了
    查看當(dāng)前字符設(shè)備號使用情況

    cat /proc/devices

    查看設(shè)備號使用情況
    將240改為 90


    重新執(zhí)行命令

    sudo mknod /dev/nopage c 92 0 (這里的92是你前面申請的設(shè)備號)

    92 可以通過命令 grep nopage /proc/devices 返回得到
    參數(shù)c 代表的是字符設(shè)

    gcc np_test.c -o ntest

    ./ntest
    出現(xiàn)錯誤


    np_test.c源碼

    查看是否加載模塊成功

    黃色代表字符設(shè)備

    后來想到是不是權(quán)限問題
    我先查看了一下權(quán)限
    在/dev 下ll
    先看mmapnopage字符設(shè)備對于普通用戶只有讀權(quán)限(nopage 是我修改過的,原本和mmapnopage一樣)
    修改為可讀可寫
    chmod 666 nopage #(666 = rw-=4+2+0)

    之后再編譯一下gcc np_test.c -o ntest
    ./ntest

    結(jié)束

    總結(jié)

    以上是生活随笔為你收集整理的[linux-nopage]内存映射虚拟字符设备驱动【P119】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产偷人妻精品一区 | 人人射人人射 | 亚洲成a人v欧美综合天堂麻豆 | 一区二区三区在线免费 | 日本午夜精品 | 女人扒开屁股让男人捅 | 色综合久久久 | 天天摸天天射 | 91免费视频入口 | 成年人黄色av | 性猛交xxxx乱大交孕妇2十 | 一二三区在线视频 | 伊人看片| 亚洲国产成人在线视频 | 欧美人与性动交ccoo | 成人一级免费视频 | 亚洲片国产一区一级在线观看 | av手机在线免费观看 | 免费人成在线 | 偷拍老头老太高潮抽搐 | 亚洲操片| jizz少妇 | 久久精品一本 | 国产伦理精品 | 欧美成人aa | 李丽珍裸体午夜理伦片 | 天天草影院 | 亚洲一区二区不卡视频 | 大白屁股一区二区视频 | 一级片免费在线播放 | 亲女禁h啪啪宫交 | 无码人妻精品一区二区三 | 欧美日韩一区二区三区四区五区 | 久久精品丝袜 | 噜噜狠狠狠狠综合久久 | 午夜影院在线播放 | 国产一区二区三区三州 | 国产一区二区精品 | 在线免费看黄网站 | 国产老熟妇精品观看 | 天天摸日日摸 | 亚洲精品粉嫩小泬 | 亚洲性综合网 | 中文字幕在线观看日本 | 亚洲综合第一页 | 欧美综合第一页 | 热久久精品 | 一区二区中文在线 | 国产成人精品国内自产拍免费看 | 18黄暴禁片在线观看 | 欧美午夜视频 | 国产成人av网站 | 玉丸(双性调教) | 日本成人片在线 | 狠狠做深爱婷婷综合一区 | 黄色av日韩 | 国产日本一区二区三区 | 免费在线国产 | 免费观看黄色小视频 | 国产精品一区二区人人爽 | 一区二区三区国产在线观看 | 黑人操亚洲女 | 国产盗摄一区二区三区在线 | 蜜臀视频一区二区三区 | 天堂在线播放 | 色婷婷综合成人av | 日本成人精品视频 | 日韩av自拍偷拍 | 欧美xxxxhd| 啪啪中文字幕 | 99精品人妻无码专区在线视频区 | 亚洲国产成人综合 | 精品福利在线观看 | 国产激情无码一区二区三区 | 国产不卡视频 | 丝袜美女啪啪 | 在线免费福利 | 国产欧美一区在线观看 | 色屋视频 | 欧美一区二区高清视频 | 精品欧美一区二区精品久久 | 女女综合网 | 99久久国| 97色伦影院 | 四川丰满妇女毛片四川话 | 影音先锋成人资源 | 久久97精品 | 久久国产精品一区二区 | 欧美日韩亚洲在线观看 | 这里只有精品免费视频 | 黄色三及| 精品国产免费av | 国产69精品久久 | 美女扒开尿口让男人捅爽 | 日韩视频在线免费播放 | 久久中文字幕人妻熟av女蜜柚m | 四色永久访问 | 92久久精品一区二区 | 少妇精品无码一区二区三区 |