Linux Device Drivers

Device Number

 

裝置的存取,是透過它們在檔案系統裡的名稱;這些名稱可成為特殊檔(special file)、裝置檔(device file)或檔案系統是的節點(node),但不管哪些說法意義都一樣。裝置檔一般來說都集中在/dev/目錄下。字元裝置會出現c字樣而區塊裝置則被標示為b

在日期欄位之前兩個以逗號隔開的數值,由左而右,依序是裝置檔的(major number)(minor number)

[root@localhost ldd3]# ls -l /dev/

?? 0

crw-rw----+ 1 root root          14, 12     2012-01-30 09:17 adsp

crw------- 1 root root           10,    175   2012-01-30 09:17 agpgart

crw-rw----+ 1 root root          14, 4       2012-01-30 09:17 audio

crw------- 1 root root          5,   1        2012-01-30 09:18 console

crw-rw---- 1 root root         10, 63      2012-01-30 09:17 cpu_dma_latency

brw-rw---- 1 root disk           253,    0       2012-01-30 09:17 dm-0

brw-rw---- 1 root disk           253, 1       2012-01-30 09:17 dm-1

 

裝置編號有以下幾個要點:

  1. 主編號與次編號兩者合稱「裝置編號」
  2. dev_t型別來表示裝置編號
  3. dev_t是一個32-bit無號數,其中12bits是主編號,其餘20bits留給次編號
  4. MAJOR(dev_t dev) 取得主編號
  5. MINOR(dev_t dev) 取得次編號
  6. MKDEV(int major, int minor) 將主次編號合併
  7. 可在【/proc/devices】中看到建立的裝置編號

 

建立裝置編號的方法主要可以分為兩個,

  1. 靜態登記法(kernel 2.4的傳統方法, 2.6也有某些驅動程式用之)
  2. 動態登記法(kernel 2.6開始建議採用)

 

範例如下:

 

  1. 靜態登記法

dev_num_sta.c

#include <linux/init.h>         /* modules */

#include <linux/module.h>       /* module */

#include <linux/types.h>         /* dev_t type */

#include <linux/fs.h>           /* chrdev allocation */

 

#include "dev_num_sta.h"

 

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("Emil Chen");

MODULE_DESCRIPTION("Static set MAJOR/MINOR number");

 

dev_t dev;

int major_num=222, minor_num=1;

 

static int __init_dev(void)

{

           printk(KERN_INFO "Static setting major and minor number...\n");

          

           int alloc_ret = 0;

          

           dev = MKDEV(major_num, minor_num);

          

           // alloc_chrdev_region return 0 on success

           alloc_ret = register_chrdev_region(dev, DEVNUM_COUNT, DEVNUM_NAME);

          

           if(alloc_ret){

                     printk(KERN_WARNING "%s : could not get major %d\n", __func__, major_num);

           }

           else{

                     printk(KERN_WARNING "%s : registered with major number:%i, minor number:%i\n",

                                __func__, MAJOR(dev), MINOR(dev));

           }

           return alloc_ret;

          

           return 0;

}

 

static void __exit_dev(void)

{

           printk(KERN_INFO "dev_num Module removed.\n");

           /* Free the devices */

           unregister_chrdev_region(dev,DEVNUM_COUNT);

}

 

module_init(__init_dev);

module_exit(__exit_dev);

 

dev_num_sta.h

#ifndef __DEVNUM1_H_

#define __DEVNUM1_H_

 

// Number of devices

#define DEVNUM_COUNT 4

 

// Name of the driver

#define DEVNUM_NAME "dev_num_sta"

 

// First minor number

#define DEVNUM_MINOR_START 0

 

#endif /* dev_num.h included */

 

Makefile

APP= dev_num_sta

KERNELDIR ?= $(shell pwd)/../../..

PWD := $(shell pwd)

 

obj-m := $(APP).o

 

default:

           $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

 

clean:

           $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

 

  1. 動態登記法

 

dev_num_dyn.c

#include <linux/init.h>         /* modules */

#include <linux/module.h>       /* module */

#include <linux/types.h>         /* dev_t type */

#include <linux/fs.h>           /* chrdev allocation */

 

#include "dev_num_dyn.h"

 

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("Emil Chen");

MODULE_DESCRIPTION("20120306");

 

dev_t dev;

 

static int __init_dev(void)

{

           printk(KERN_INFO "Dynamic allocate major and minor number...\n");

          

           int alloc_ret = 0;

                    

           // alloc_chrdev_region return 0 on success

           alloc_ret = alloc_chrdev_region(&dev, DEVNUM_MINOR_START, DEVNUM_COUNT, DEVNUM_NAME);

          

           if(alloc_ret){

                     printk(KERN_WARNING "%s : could not allocate device\n", __func__);

           }

           else{

                     printk(KERN_WARNING "%s : registered with major number:%i, minor number:%i\n",

                                __func__, MAJOR(dev), MINOR(dev));

           }

           return alloc_ret;

          

           return 0;

}

 

static void __exit_dev(void)

{

           printk(KERN_INFO "dev_num Module removed.\n");

           /* Free the devices */

           unregister_chrdev_region(dev,DEVNUM_COUNT);

}

 

module_init(__init_dev);

module_exit(__exit_dev);

 

dev_num_dyn.h

#ifndef __DEVNUM1_H_

#define __DEVNUM1_H_

 

// Number of devices

#define DEVNUM_COUNT 4

 

// Name of the driver

#define DEVNUM_NAME "dev_num_dyn"

 

// First minor number

#define DEVNUM_MINOR_START 0

 

#endif /* dev_num.h included */

 

Makefile

APP= dev_num_dyn

KERNELDIR ?= $(shell pwd)/../../..

PWD := $(shell pwd)

 

obj-$(CONFIG_EMIL_LDD) := $(APP).o

 

default:

           $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

 

clean:

           $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

 

 

arrow
arrow

    flykof 發表在 痞客邦 留言(0) 人氣()