字符设备的另一种写法

发布时间:2024-08-19  

对于前面的使用register_chrdev函数注册字符设备驱动程序的方法其实是尚未升级到2.6内核版本的驱动代码。使用这种方式虽然理解起来简单(可以简单理解为一主设备号为下标将驱动的file_operations结构体放入名为chrdevs的数组中,而当应用层调用open函数时,会通过字符设备的主设备号从chrdevs数组中找出file_operations结构体的open函数调用),但是有个缺点就是对于同一个主设备号的,不同的256个次设备号都可以调用同一个open,这样造成可用的设备驱动最多只能有256个。所以在2.6内核版本之后,有一个dev_t类型,它用于保存设备编号,它是一个32位的数,其中12位被用于主设备号,其余20位用于次设备号。而且同一个主设备号,不同的此设备号可以表示不同的设备。这样的话,就可以最大有4G个设备驱动可以使用。


1、字符设备驱动的写法


在以前的字符设备编写方法是这样的:

1、确定设备号

2、分配、设置一个file_operations结构体

3、register_chrdev(设备号,名字,file_operations结构体)

4、入口函数

5、出口函数


在2.6内核中,新的字符设备的编写方法是这样的:

以主设备号和次设备号来找到file_operations结构体。

把register_chrdev展开:

1、alloc_chrdev_region/register_chrdev_region(从(主,次)到(主,次+n)都对应file_operations结构体)

2、cdev_init

3、cdev_add


2、以新的字符设备编写方法编写驱动程序并且测试


直接把驱动程序列出,下面的程序实现了2个驱动程序,分别是hello_ops、与hello2_ops 。然后hello_ops可以对应次设备号为0与1的字符设备文件,而hello2_ops对应次设备号为2的字符设备文件。


#include

#include

#include

#include

#include             //含有iomap函数iounmap函数

#include        //含有copy_from_user函数

#include       //含有类相关的处理函数

#include //含有S3C2410_GPF0等相关的

#include          //含有IRQ_HANDLEDIRQ_TYPE_EDGE_RISING

#include        //含有IRQT_BOTHEDGE触发类型

#include    //含有request_irq、free_irq函数

#include


/* 1、确定主设备号 */

static int major;


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

{

    printk('hello_openn');

    return 0;

}


static int hello2_open (struct inode * inode, struct file * file)

{

    printk('hello2_openn');

    return 0;

}

/* 2、构造file_operations */

static struct file_operations hello_ops = {

    .owner   = THIS_MODULE,

    .open    =  hello_open,

};


/* 2、构造file_operations */

static struct file_operations hello2_ops = {

    .owner   = THIS_MODULE,

    .open    =  hello2_open,

};


#define HELLO_CNT 2

static struct cdev hello_cdev;

static struct cdev hello2_cdev;


static struct class *cls;//类


static int hello_init(void)

{

    dev_t devid;

    

    /* 3、告诉内核 */

#if 0

    register_chrdev(0, 'hello', &hello_ops);/* 导致(major, 0), (major, 1), ...(major, 255)都对应hello_ops */

#else

    if (major) 

    {

        devid = MKDEV(major, 0);

        register_chrdev_region(devid, HELLO_CNT, 'hello');/* (major, 0-1)对应hello_ops,(major, 2-255)都不对应 */

    } 

    else 

    {

        alloc_chrdev_region(&devid, 0, HELLO_CNT, 'hello');/* (major, 0-1)对应hello_ops,(major, 2-255)都不对应 */

        major = MAJOR(devid);

    }

    

    cdev_init(&hello_cdev, &hello_ops);

    cdev_add(&hello_cdev, devid, HELLO_CNT);

    

    devid = MKDEV(major, 2);

    register_chrdev_region(devid, 1, 'hello2');/* (major, 2)对应hello2_ops,(major, 3-255)都不对应 */

    

    cdev_init(&hello2_cdev, &hello2_ops);

    cdev_add(&hello2_cdev, devid, 1);

        

#endif


    cls = class_create(THIS_MODULE, 'hello');//创建类

    class_device_create(cls, NULL, MKDEV(major,0), NULL,'hello0');/* /dev/hello0 */

    class_device_create(cls, NULL, MKDEV(major,1), NULL,'hello1');/* /dev/hello1 */

    class_device_create(cls, NULL, MKDEV(major,2), NULL,'hello2');/* /dev/hello2 */

    class_device_create(cls, NULL, MKDEV(major,3), NULL,'hello3');/* /dev/hello3 */

    return 0;

}


static void hello_exit(void)

{

    class_device_destroy(cls, MKDEV(major,0));

    class_device_destroy(cls, MKDEV(major,1));

    class_device_destroy(cls, MKDEV(major,2));

    class_device_destroy(cls, MKDEV(major,3));

    class_destroy(cls);

    

    cdev_del(&hello_cdev);

    unregister_chrdev_region(MKDEV(major, 0), HELLO_CNT);

    

    cdev_del(&hello2_cdev);

    unregister_chrdev_region(MKDEV(major, 2), 1);

}



module_init(hello_init);

module_exit(hello_exit);


MODULE_LICENSE('GPL');


接着编写一个测试程序测试它,这个测试程序可以通过打开不同的字符设备文件找到相应的设备驱动。


#include

#include

#include

#include

#include

#include


/* 

 * ./hello_test

 */


void printf_usage(char *file)

{

    printf('%s n', file);

}

 

int main(int argc, char **argv)

{

    int fd;

    if(argc != 2)

    {

        printf_usage(argv[0]);

        return 0;

    }

    

    fd = open(argv[1], O_RDWR);

    

    if(fd <0)

    {

        printf('can't open %sn', argv[1]);

    }

    else

    {

        printf('can open %sn', argv[1]);

    }

    return 0;

}


测试的结果如下,从测试结果可以看出/dev/hello0~3这4个字符设备文件的主设备号都为252。其中次设备为0、1的文件对应hello_ops;次设备为2的文件对应hello2_ops。这个测试结果证明了同一个主设备,不同的次设备号可以对应不同的驱动程序。

 


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    (2,4,0xA5,8);        //二进制数值          LCD1602_ShowChar(2,13,0xDF);        //特殊符号,摄氏度     LCD1602_ShowChar......
    State Machine)的算法可以很轻松的将源代码字符序列分割成一系列的记号(Token)。 词法分析产生的记号一般可以分为如下几类:关键字、标识符、字面量(包含数字、字符串等)和特殊符号(如加号、等号......
    名称需要将自动生成取消勾选并手动输入简短不带有/*-、这类特殊符号; 5、设置EtherCAT转Profinet网关的输入输出字节数长度; 6、所有配置设置好,下载组态到PLC; 7、打开......
    需要说明的是,'启用延迟环境变量扩充'后,所有的'!'都将被视为'取变量值'的特殊符号,即使用'^!'也不能输出符号'!'。若要输出'!',则需要'停用延迟环境变量扩充',命令为:SetLocal......
    图和计算机辅助绘图包中,以确定电路中单个元件和元件的位置。 图形符号不仅标识元件的位置,还标识电气元件的类型,如电阻、电感、电容、机械等,因此在电路图和原理图中,图形符号识别......
    高通推出高通3D Sonic第二代传感器,解锁速度快50%;高通于1月12日发布了第二代超声波屏下指纹识别器3D Sonic Sensor Gen 2,几乎在所有方面都碾压初代型号。新版......
    泰雷兹推出全新多模态生物识别器 提升边境和旅行市场竞争力;• 全球边境和旅行管理专家泰雷兹推出全新的多模态生物识别解决方案,简化了当局的处理流程并改善了用户在边境的体验。• 该创新的识别器整合了虹膜和人脸识别......
    泰雷兹推出全新多模态生物识别器 提升边境和旅行市场竞争力; 全球边境和旅行管理专家泰雷兹推出全新的多模态生物识别解决方案,简化了当局的处理流程并改善了用户在边境的体验。 该创新的识别器整合了虹膜和人脸识别......
    profinet(Profinet转EtherCAT)网关设备名称要把自动生成取消勾选,重新输入新的名称,如果输入的名称包含/*_等特殊符号,配置软件的名称以转换的名称为准。 配置好IP地址......
    体行业观察在爆炸门后三星对于旗舰机种的开发设计变得更小心翼翼,先前曾经传出将搭载指纹识别屏幕的 Galaxy S8,在最新的消息中显示,由于辨识准确率仍有误差,三星可能不会在 Galaxy S8 使用此一先进技术,而是在机身背后装设一个指纹识别器。 下一......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>