簡單的LINUX字符設備驅動及編譯進Linux內核…

驅動代碼:

 

#include <linux/init.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/uaccess.h>


#ifndef MODULE
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif


#define MAJOR_NUM 253

MODULE_LICENSE("GPL");

 

int dev_test_open(struct inode *, struct file *);
ssize_t dev_test_read(struct file *, char *, size_t, loff_t*);
ssize_t dev_test_write(struct file *, const char *, size_t, loff_t*);
int dev_test_release(struct inode *, struct file *);

struct file_operations hello_fops =
{
       open:dev_test_open,
       read:dev_test_read,
       write:dev_test_write,
       release:dev_test_release,
};

char *pBuff;

 

static int __init dev_test_init(void)
{
   printk("<1>hello devtest\r\n");
   
    if(register_chrdev(MAJOR_NUM, "dev_test",&hello_fops))
      printk("<1>registerfailed\r\n");

    return0;
}

static void __exit dev_test_exit(void)
{
   printk("<1>bye dev_test\r\n");
   
    if(unregister_chrdev(MAJOR_NUM, "dev_test"))
      printk("<1>unregiterfailed\r\n");
}

int dev_test_open(struct inode *pInode, struct file *pFile)
{
    pBuff =(char*)kmalloc(128, GFP_KERNEL);

    if (pBuff ==NULL)
      printk("<1>kmalloc memoryfailed\r\n");

    return0;
}

int dev_test_release(struct inode *pInode, struct file*pFile)
{
   kfree(pBuff);
    return0;
}

ssize_t dev_test_read(struct file *pFile, char *buff, size_t len,loff_t *pOff)
{
    if(copy_to_user(buff, pBuff, len))
    {

      printk("<1>copy_from_userfailed\r\n");
       return-EFAULT;
    }

    returnlen;
}

ssize_t dev_test_write(struct file *pFile, const char *buff, size_tlen, loff_t *pOff)
{
    int i =0;

    if(copy_from_user(pBuff, buff, len))
    {
      printk("<1>copy_to_userfailed\r\n");
       return-EFAULT;
    }
   
    while(pBuff[i] != '\0')
    {
       if (pBuff[i]> 0x40 && pBuff[i]< 0x60)
          pBuff[i] +=0x20;
       else if(pBuff[i] > 0x60 &&pBuff[i] < 0x80)
          pBuff[i] -=0x20;

       i++;
    }

    returnlen;
}


module_init(dev_test_init);


module_exit(dev_test_exit);

=========================================================

把該代碼保存爲/usr/local/src/linux-2.x.x/driver/char/dev_test.c

(假設內核代碼的目錄爲/usr/local/src/linux-2.x.x)

=========================================================

下面就是編譯模塊,按動態加載和靜態加載進內核分爲兩種編譯模式.

(1) 動態加載到內核模式,這個比較簡單, 但是uClinux不支持這種方式, 所以以linux爲例.

    A. 用 gcc-D__KERNEL__ -DMODULE -DLINUX -I /usr/local/src/linux-2.x.x/include-c -o dev_test.o dev_test.c

    B.在/usr/local/src/linux-2.x.x/driver/char/上用shell 輸入 insmoddev_test.o

    C.在shell上使用 mknod /dev/dev_test c 253 0 創建設備文件

到這裏就搞定了, 用戶就可以在用戶層使用open read write 等函數對"/dev/dev_test"這個文件進行操作,內核就會調用相應的函數處理用戶層的請求.

當用戶不需要使用這個驅動模塊時,可以用rmmod dev_test進行卸載.

--------------------------------------------------------------------------------------------------------

(2) 靜態編入內核,通過 這種方法編譯的,只要內核一啓動,模塊就會自動加載到內核

    A.在/usr/local/src/linux-2.x.x/driver/char/下的Makefile文件中加入以下代碼

       ifeq ($(CONFIG_DEV_TEST),y)
           obj-y += dev_test.o

       endif

    B.在/usr/local/src/linux-2.x.x/driver/char/下的Makefile文件中加入以下代碼

       bool 'support for dev_test' CONFIG_DEV_TEST y

       如果沒有該文件,就在/usr/local/src/linux-2.x.x/arch/xxxnommu/目錄下的config.in文件中的字符驅動部分加入.

    C.在shell上使用mknod /dev/dev_test c 253 0 創建設備文件

       (如果是uClinux, 則使用mknod /xxx/romdist/dev/dev_test c 253 0,/xxx/romdist爲嵌入式文件系統的目錄)

    D.編譯固件和文件系統鏡像後燒到目標版上就可以了.

===========================================================

下面是用戶層的應用程序代碼, 它使用open, read, write等函數來調用內核實現的驅動代碼.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
       int fd;
       char buff[128];

       fd = open("/dev/dev_test", O_RDWR);

       while(1)
       {
               printf("enter the string:");
               scanf("%s", buff);

               write(fd, buff, 128);

               memset(buff, 0, 128);

               read(fd, buff, 128);

               printf("%s\r\n", buff);
       }
       return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章