乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      linux驅動程序開發(fā)詳細介紹

       ldjsld 2015-11-20

      第一個內核模塊(Hello World模塊)


      代碼如下:
      View Code
      #include<linux/init.h>
      #include<linux/module.h>
      MODULE_LICENSE("Dual BSD/GPL");
      static __init int hello_init(void)
      {
      //printk函數在內核中定義對模塊可用,內核需要自已的打印涵數
      //因為它靠自已運行,而沒有相應的庫函數。
      //模塊能夠調用printk是因為insmod加載了之后,模塊被鏈接到內核
      //因些可調用內核的公用符號,KERN_ALERT是消息的優(yōu)先級
      printk(KERN_ALERT"HELLO WORLD\n");
      return 0;
      }
      static __exit void hello_exit(void)
      {
      printk(KERN_ALERT"GoodBye\n");
      }
      module_init(hello_init);
      module_exit(hello_exit);

      在這個模塊中定義了兩個函數,一個在模塊加載到內核時調用(hello_init),另一個在從內核將模塊移出時調用(hello_exit);在上面的代碼中,module_init與module_exit是兩個內核宏定義,用于告訴內核從哪里啟動,從哪里退出,MODULE_LICENSE宏用于聲明模塊是遵守某個自由許可證的,否則內核加載時會出現警告。
      好了,現在可以對上面這個程序進行相應的測試,在測試之前必須要編寫相應的Makefile文件,模塊的編譯與普通程序的編譯是不同的

      Makefile文件

      代碼如下:
      View Code
      #makefile for hello world
      # KERNELRELEASE是在內核源碼中定義的第一個變量
      ifneq ($(KERNELRELEASE),) #判斷變量是否為空(第一次執(zhí)行時沒有定義)
      #沒定義時執(zhí)行else語句
      obj-m := HelloWorld.o#表明有一個模塊要從目錄文件HelloWorld.o建立,建立之后將其
      #命名為HelloWorld.ko
      #如果有一個模塊名為module.ko,來自于兩個源文件,假設為file1.c與file2.c
      #則應該這樣 obj-m := module.o
      # module-objs:=file1.o file2.o
      else
      KDIR:=/lib/modules/$(shell uname -r)/build
      all:
      #當make的目標為all時,-C $(KDIR)跳到內核源碼目錄下讀取Makefile
      #M=$(PWD)表示返回當前目錄繼續(xù)讀取,執(zhí)行當前的Makefile,當再次執(zhí)行時
      #$(KERNELRELEASE)已經定義,make將讀取else之前的內容
      make -C $(KDIR) M=$(PWD) modules
      clean:
      rm -rf *.ko *.o *.mod.o *.mod.c *.symvers
      endif

      相應的解釋如上?
       
      開如編譯內核:必須要是超級用戶
      在當前路徑下輸入make
      編譯完成后,輸入insmd HelloWorld.ko進行內核的加載,使用dmesg |tail可以查看內核的輸出信息。
      移除內核采用rmmod HelloWorld 相應的使用dmesg|tail可以看到打印出GoodBye
      Printk可能沒有輸出到屏幕上,這與KERN_ALERT的優(yōu)先級有關,說明還不夠高,內核輸出的內容實際在/var/log/kern.log中,可以vim /var/log/kern.log查看。
      內核模塊與應用程序的不同:
      1:應用程序運行后就會處理相應的任務,而內核模塊注冊后是用來服務于將來請求,并且初始化函數加了__init之后,調用完后,內存空間立即釋放。
      2:應用程序終止時可以不用負責回收資源,由操作系統來維護,但內核模塊在除時必須釋放資源。
      3:應用程序可以調用相應的庫函數,而內核模塊能夠調用的則只要內核中輸入的那些函數。在內核模塊的編程中,源文件不應當包括通常的頭文件,但也有例外,如<stdarg.h>等少部分頭文件是僅有的例外。
      4:錯誤的處理方式不同,在應用程序中段錯誤,可以由相應的調試程序進行檢查更改,但內核模塊中,段錯誤,如果不終止整個系統的話,就會終止當前進程。
      用戶空間與內核空間:
      應用程序在用戶空間運行,而內核模塊是在內核空間內運行的。每種模式都有它自已的內存映射,它自已的地址空間。
      內核與當前進程的關系:
      內核模塊做的大部份動作是代表一個特定進程的,內核代碼可以引用當前進程,通過存取全局項current,它在<asm/cuurent.h>定義:
      #define current get_current()//通過這個宏定義可以獲取指向task_struct的任務指針
      內核代碼可以通過current來使用進程特定的信息。

      內核符號表:

      內核模塊在加載時通過查找內核符號表來解決未定義的符號,內核符號表包涵了全局內核項的地址,當加載一個模塊時,模塊中輸出的符號也將成為內核符號表的一部分。
      模塊的輸入符號通常采用以下兩種形式:
      EXPORT_SYMBOL(name)
      EXPORT_SYMBOL_GPL(name)
      上面的宏定義中的任何一個使得給定的符號在模塊外使用,_GPL版本的宏定義只能使符號對_GPL許可的模塊可用。
      版本依賴:
      模塊代碼一定要為每個它要連接的內核版本重新編譯,在模塊編譯的過程中,其中一步是到當前的內核對讀取Makefile文件,在編譯的過程中會采用內核樹中的文件(vermagic.o)連接你的模塊,在這個文件里面有許多有關內核的信息,包括版本...
      模塊參數:
      模塊參數由insmod與modprobe在加載時指定。
      對前面的HelloWorld.c進行修改如下:
      在終端上輸入


      代碼如下:
      Make
      Insmod HelloWorld.ko who=”test” num=10
      Dmesg|tail -3

      即可以看到。
      聲明數組參數時采用module_param_array(name,type,num,perm)
      Name是數組的名字,type是數組元素的類型,num是數組無數的個數,perm是權限
      附:insmod
      Insmod將內核模塊加載到內存中,它依賴一個在kernel/module.c中定義的系統調用,函數sys_init_module分配內核內存來存放模塊,它接著copy模塊的代碼段到這塊內存區(qū),借助內核符號表來解決模塊中的內核引用,并且調用模塊的初始經函數來啟動所有的東西。
      Modprobe工具也用來加載一個內核模塊到內存,與insmod不同的是,它會查看要加載的模塊,看看是否引用了當前內核沒有定義的符號。如要有,它會在當前搜索路徑下尋找其他模塊,看是否這個符號的定義,如果有,則將這個模塊也加載進內核。
      Rmmod用來去除內核模塊,如果內核認為模塊還在使用,或者內核配置了不允許去除模塊,則模塊的卸載會失敗。
      Lsmod例舉出當前系統中加載的所有模塊列表。
      內核模塊編程中函數通常聲明為靜態(tài)的,是因為它們不會在文件之外可見。

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多