(七) 字符设备号申请

1.模块传参

  在应用程序中,可以通过main函数向其中传参数,实际上对于加载模块的时候还可以通过insmod命令传参数。在linux根目录,使用命令”vim include/linux/moduleparam.h” 中包含了向模块传参数的函数,这个功能是集成的,在任何linux系统中都可以使用。参数传递有两个函数,分别是函数module_param和module_param_array。函数module_param支持单个参数传递,在头文件中,如下所示:

#define module_param(name, type, perm)              
    module_param_named(name, name, type,perm)

name,模块参数名;type,模块参数数据类型(支持int long short uint ulong ushort类型);perm,模块参数的访问权限(S_IRUSR参数表示所有文件所有者可读)。

#define module_param_array(name, type,nump, perm)              
    module_param_array_named(name, name, type,nump,perm)

nump,保存参数的数量。参数perm表示此参数在sysfs文件系统中所对应的文件节点的属性,其权限在“include/linux/stat.h“中。对于常用的参数:

#define S_IRUSR  00400 文件所有者可读
#define S_IWUSR  00200 文件所有者可写
#define S_IXUSR  00100 文件所有者可执行
#define S_IRGRP  00040 与文件所有者同组的用户可读
#define S_IROTH  00004 与文件所有者不同组的用户可读

2.静态申请

  字符设备的注册需要申请设备号-设备注册-生成设备节点;申请设备号分为静态申请(register_chrdev_region)以及动态申请(alloc_chrdev_region)。
  静态申请就是主设备号是程序员手动分配了,动态申请是系统给分配的。对于静态申请register_chrdev_region()是提前知道设备的主次设备号,再去申请设备号。在linux目录,使用命令”vim include/linux/fs.h”查找extern int register_chrdev_region(dev_t, unsigned, const char *),对于参数dev_t有几个参数以及函数为它服务。在“include/linux/cdev.h”中,在cdev结构体重有一个专门的参数dev_t dev,cdev类型是字符设备的描述结构,其中设备号必须用dev_t类型来描述,高12位为主设备号,低20位为次设备号。在”include/linux/kdev_t.h”中,有一些专门用来处理dev_t数据类型的宏定义:

 MAJOR(dev),是对dev 操作,提取高12 位主设备号;
 MINOR(dev),是对dev 操作,提取低20 位数次设备号;
 MKDEV(ma,mi),就是对主设备号和低设备号操作,合并为dev 类型。

3.动态申请

  在linux根目录,使用命令”vim include/linux/fs.h”查找动态申请函数extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *) dev,存放返回的设备号;参数unsigned,一般为0;参数unsigned,次设备号连续编号范围;参数const char ,设备名称;函数调用成功则返回0,反之返回-1。

4.程序清单

#include <linux/init.h>
#include <linux/module.h>
/*定义module_param module_param_array的头文件*/
#include <linux/moduleparam.h>
/*定义module_param module_param_array中perm的头文件*/
#include <linux/stat.h>
/*三个字符设备函数*/
#include <linux/fs.h>
/*MKDEV转换设备号数据类型的宏定义*/
#include <linux/kdev_t.h>
/*定义字符设备的结构体*/
#include <linux/cdev.h>

#define DEVICE_NAME "test"
#define DEVICE_MINOR_NUM 2
#define DEV_MAJOR 0
#define DEV_MINOR 0

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("flywang");

int numdev_major = DEV_MAJOR;
int numdev_minor = DEV_MINOR;

/*输入主设备号*/
module_param(numdev_major,int,S_IRUSR);
/*输入次设备号*/
module_param(numdev_minor,int,S_IRUSR);


static int test_init(void)
{
    int ret = 0;
    dev_t num_dev;


    printk(KERN_EMERG "numdev_major is %d!\n",numdev_major);
    printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor);

    if(numdev_major){
        num_dev = MKDEV(numdev_major,numdev_minor);
        /*静态注册设备号*/
        ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);
    }
    else{
        /*动态注册设备号*/
        ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);
        /*获得主设备号*/
        numdev_major = MAJOR(num_dev);
        printk(KERN_EMERG "adev_region req %d !\n",numdev_major);
    }

    if(ret<0){
        printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major);       
    }

    printk(KERN_EMERG "test_init!\n");
    return 0;
}

static void test_exit(void)
{
    printk(KERN_EMERG "test_exit!\n");
    unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
}

module_init(test_init);
module_exit(test_exit);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值