天天看點

linux字元裝置驅動程式學習實驗記錄

  • 這是自己平常學習中曾經困惑的問題。

    Linux系統下的字元型裝置和塊裝置的區分?

    這裡指的區分不是說如何從定義上進行區分,從實用的角度來看。打個比方就是,如果你自己寫了個裝置的驅動,或者從網上下載下傳了一個驅動。安裝好驅動之後,你沒有相應的裝置節點,要用到這樣一條指令。mknod /dev/yourdevice  type Major Slave,這裡就牽扯到類型是字元型的還是塊裝置型的。如何從驅動裡看出來呢。傳統驅動程式注冊/登出字元型裝置時用到register_chrdev/unregiter_chrdev,而對于塊裝置則是:register_blkdev/unregiter_blkdev, 而基于devfs的驅動程式也可以看出來,指令分别對應為:字元型devfs_register()和devfs_unregister,塊裝置devfs_blkregister和devfs_blkunregister。

    注釋:在MagicArm上,上次幫同學看那個CAN總線驅動的時候要建立一個裝置節點,我看了半天驅動程式也沒有看出來是字元裝置。後來隻能試了。主要是不了解devfs_resgiter就是字元型裝置的驅動。順便說明下:平常的小型嵌入式實驗中用到的塊驅動是比較少的。

    上次虛拟機開機發現CD光牒打不開了,發現在/dev目錄下找不到cdrom了,這種問題還是有時候會碰見的,雖然不是很常見。方法就是建立一個cdrom節點就可以了,當然裝置号這些東西要去文檔目錄下看:/usr/src/linux-2.4/Documenttation/Devices.txt.

  • 關于printk

    printk(KERN_DEBUG “driver test”);

    在頭檔案<linux/kernel.h>中定義了8種可用的日志級字元串。

    KERN_EMERG 用于緊急事件,像系統崩潰等嚴重資訊

    KERN_ALERT用于警告資訊

    KERN_CRIT臨界狀态

    KERN_ERR用于錯誤資訊

    KERN_WARNING警告資訊

    KERN_NOTICE提醒

    KERN_INFO提示性資訊

    KERN_DEBUG調試資訊

    日志級别範圍0-7,沒有指定幾倍的使用DEFAULT_MESSAGE_LOGLEVEL,核心可以把消息列印到控制台,可以指定控制台為字元模式的終端或者列印機。當日志界杯小于console_loglevel時,消息才能顯示出來。如果運作了klogd和syslogd,則不論console_loglevel為什麼值,内河消息都追加到/var/log/messages中。如果klogd沒有運作,消息不會傳遞到使用者空間,隻能檢視/proc/kmsg.

    變量console_loglevel的初始值為DEFAULT_CONSOLE_LOGLEVEL,可以通過sys_syslog系統調用進行修改,調用klogd時可以同過-c選項來修改這個變量。如果要修改其目前值,需要kill klog,然後-c選項重起。

    如果要檢視調試資訊,應當提高日志級别。

    通過讀寫/proc/sys/kernel/printk可以讀取和修改控制台的日志級别。

    # cat /proc/sys/kernel/printk檢視級别 顯示如: 6 4 1 7,6是目前級别4為預設

    # echo 8 > /proc/sys/kernel/printk  修改6為8。

  • 無裝置相關的hello驅動程式 hello.c

    這部分主要參考:

    http://dev.yesky.com/154/2621154.shtml深入淺出Linux裝置驅動程式設計之核心子產品

    2006-10-17 15:36 作者: 宋寶華 出處: 天極開發 責任編輯:>方舟

    #include <linux/module.h>

    #include <linux/init.h>

    #include <linux/kernel.h>

    MODULE_LICENSE("GPL");

    static int __init hello_init ()

    {

     printk(KERN_DEBUG"Hello module init DEBUG/n");

     printk(KERN_WARNING"Hello module initWARN/n");

     printk(KERN_EMERG"Hello module initEMERG/n");

     printk("Hello module init/n");

     return 0;

    }

    static void __exit hello_exit ()

    {

     printk("Hello module exit/n");

    }

    module_init(hello_init);

    module_exit(hello_exit);

   編譯上述檔案:指令如下: 

gcc -D__KERNEL__ -DMODULE -DLINUX -I /usr/local/src/linux2.4/include -c -o hello.o hello.c

測試:

a> 測試環境為虛拟機下面的Redhat9.0,内河2.4.20-8,

b> 終端執行指令如下: telinit 3 登陸字元模式,這裡因為想看一下驅動程式的輸出,應當使用登陸終端,在X桌面下的終端一般是看不到這些輸出的。

c> 測試步驟:# cd /root/hello

# insmod hellodriver.o

# rmmod hellodriver.o

OK,這樣,就可以輕松測試驅動程式了。記錄一下,以示鼓勵。

  •  裝置相關的hello驅動程式

            源代碼hellod.c,編譯後驅動為hellod.o

            編譯方法同上:

                gcc -D__KERNEL__ -DMODULE -DLINUX -I /usr/local/src/linux2.4/include -c -o hello.o hello.c  虛拟字元裝置/dev/hello,驅動就利用上面的驅動程式。稍作修改。這部分主要參考周立功 MagicArm實驗指導書

程式如下:

#include <linux/module.h>

#include <linux/init.h>

#include <linux/kernel.h>

MODULE_LICENSE("GPL");

static int hello_open(struct inode* inode,struct file *filp)

{

return 0;

}

static struct file_operations hello_fops=

{       owner: THIS_MODULE,

        open: hello_open,

};

static int __init hello_init ()

{

  register_chrdev(236,"hell",&hello_fops); //注冊主裝置号碼

 printk("Hello module init/n");

 return 0;

}

static void __exit hello_exit ()

{

unregister_chrdev(236,"hell");

 printk("Hello module exit/n");

  }

  module_init(hello_init);

  module_exit(hello_exit);

這部分多加了一個fops結構體,主要是因為我們想通過open 打開我們的虛拟裝置而準備的,好歹要加個open操作,要不然說不過去,而且我們的這個結構體和成員函數都很簡單。隻是作為測試而已。

好了,下面開始測試:

測試程式:test.c  編譯方法: gcc test.c –o test

#include <stdio.h>

#include <unistd.h>

void main()

{

int ret=open("/dev/hello",0);

        if (ret<0)

        printf("cmknod /dev/hello c 236 0 annot oepn/n");

        else

        printf("ocmknod /dev/helll c 236 0 1pen ok/n");                                                                                              

}我們的測試程式也很簡單,編譯就是平常的編譯應用程式的指令就可以了。接下來就可以執行了。還有幾個工作要做:

首先:

:# mknod /dev/hello c 236 0        //這裡建立裝置節點hello

:  #insmod hello.o                //安裝裝置驅動

:   # ./test            //測試,可以看到打開裝置成功。你還可以進行比較,建立另一個沒有驅動的裝置号節點進行測試,例如237 0 ,然後修改測試程式并運作,發現打開失敗,進而可以驗證我們的驅動是可以應用的。

  • devfs裝置驅動方法

    上面應用的為傳統的裝置驅動方法,而沒有使用devfs驅動方法。在周立功實驗書上是用的devfs的方法。不知道什麼原因,用devfs方法,我建立的節點沒有用,更别提自動建立裝置節點了。。。。。。。

繼續閱讀