第三章字符设备驱动(1)--分配和释放设备号

本文介绍Linux系统中设备号的管理方法,包括主设备号和次设备号的概念、宏定义及其转换,以及如何通过内核提供的函数进行设备号的分配与释放。

一.主设备号和次设备号
    主设备号表示设备对应的驱动程序;次设备号由内核使用,用于正确确定设备文件所指的设备。
内核用dev_t类型(<linux/types.h>)来保存设备编号,dev_t是一个32位的数,12位表示主设备号,20为表示次设备号。
在实际使用中,是通过<linux/kdev_t.h>中定义的宏来转换格式。

 


(dev_t)-->主设备号、次设备号                   MAJOR(dev_t dev)   

(dev_t)-->主设备号、次设备号                   MINOR(dev_t dev)     

 主设备号、次设备号-->(dev_t)                        MKDEV(int major,int minor)



二.分配和释放设备号

 

   建立一个字符设备之前,驱动程序首先要做的事情就是获得设备编号。其这主要函数在<linux/fs.h>中声明:


//指定设备编号
int register_chrdev_region(dev_t first, unsigned int count,char*name);
//动态生成设备编号
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,
unsigned int count, char *name);
//释放设备编号
void unregister_chrdev_region(dev_t first, unsigned int count);


分配之设备号的最佳方式是:默认采用动态分配,同时保留在加载甚至是编译时指定主设备号的余地。在scull中分配的方式是:


if (scull_major) {
    dev = MKDEV(scull_major, scull_minor);
    result = register_chrdev_region(dev, scull_nr_devs, "scull");
} else {
    result = alloc_chrdev_region(&dev, scull_minor,                                                                    scull_nr_devs,"scull");
    scull_major = MAJOR(dev);
}
if (result < 0) {
    printk(KERN_WARNING "scull: can't get major %d/n", scull_major);
    return result;
}



可以通过以下例子来学习这三个函数:
头文件scull.h如下:如果major不为0,则为指定的major号码,如果为0,则采用系统自行动态分配的方式。我们的模块包括4个设备,minor号码从0-3。


#ifndef _WEI_SCULL_H
#define _WEI_SCULL_H

#define SCULL_MAJOR         0
#define SCULL_MINOR_MIN     0
#define SCULL_DEV_NUM         4

#endif


源文件scull.c如下:


#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include "scull.h"

MODULE_LICENSE("Dual BSD/GPL");

dev_t   dev;
int     is_get_dev = -1;

int scull_major = SCULL_MAJOR;
int scull_minor = SCULL_MINOR;
int scull_nr_devs = SCULL_NR_DEVS;
static int __init scull_init(void)
{
    printk("Scull module init enter/n");
    if(scull_major){ /* 根据major和minor号码获得dev */
        dev = MKDEV(scull_major,scull_minor );
        is_get_dev = register_chrdev_region (dev,scull_nr_devs,"scull");//注册
    }else{  /* 系统动态分配 */
        is_get_dev = alloc_chrdev_region (&dev,scull_minor,    scull_nr_devs,"scull");
        scull_major = MAJOR(dev ); //获取主号码,MINOR()可获取minor号码
    }
    if(is_get_dev < 0){
        printk(KERN_WARNING "scull: can't get device major number %d/n",scull_major);
    }
    return is_get_dev;
}

/*  在模块结束的时候,应该释放注册的资源*/
static void __exit scull_exit(void)
{
    if(is_get_dev < 0){
        return ;
    }else{
        unregister_chrdev_region(dev,scull_nr_devs );
        printk("Scull module exit/n");
    }
}

module_init(scull_init);
module_exit(scull_exit);


 

 

在上边编译完成之后,要通过加载模块,建立设备等过程,此处,书中例子给出了一个脚本scull_load,这里大概解释一下:


#!/bin/sh
module="scull"
device="scull"
mode="644"
#安装scull模块
/sbin/insmod ./$module.ko $* || exit 1
#删除原来的设备
rm -f /dev/${device}[0-3]
#在/proc/devices中找到第二个字段等于scull的行,
#打印该行的第一个字段即主设备号
major=$(awk "/$2==/"$module/" {print /$1}" /proc/devices)
#在/dev下创建4个字符设备
mknod /dev/${device}0 c $major 0
mknod /dev/${device}1 c $major 1
mknod /dev/${device}2 c $major 2
mknod /dev/${device}3 c $major 3



scull_unload


#!/bin/sh
module="scull"
device="scull"

#如果没有加载该模块结束,否则卸载模块,并删除相关的节点。
/sbin/lsmod | grep $module || exit 1

/sbin/rmmod $module
rm -f /dev/${device}[0-3]


Makefile:


ifneq    ($(KERNELRELEASE),)
obj-m    :=scull.o

else
KDIR    :=/lib/modules/$(shell uname -r)/build
PWD    := $(shell pwd)

default:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
    rm -r -f .tmp_versions *.mod.c .*.cmd *.o Modules.symvers
endif


实验过程:


root@xhy-desktop:/home/xhy/MyCode/work-ldd/ch3# make
root@xhy-desktop:/home/xhy/MyCode/work-ldd/ch3# ./scull_load
root@xhy-desktop:/home/xhy/MyCode/work-ldd/ch3# cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
。。。
226 drm
250 scull   //说明已经有scull设备
251 heci
252 hidraw
253 usbmon
254 rtc
root@xhy-desktop:/home/xhy/MyCode/work-ldd/ch3# ls -l /dev/scull*
crw-r--r-- 1 root root 250, 0 2009-12-07 20:45 /dev/scull0
crw-r--r-- 1 root root 250, 1 2009-12-07 20:45 /dev/scull1
crw-r--r-- 1 root root 250, 2 2009-12-07 20:45 /dev/scull2
crw-r--r-- 1 root root 250, 3 2009-12-07 20:45 /dev/scull3


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值