首页 > 编程语言 >kernel module编程(三):获取(分配或注册)设备号

kernel module编程(三):获取(分配或注册)设备号

时间:2023-05-08 18:31:37浏览次数:32  
标签:kernel major SCULL 编程 dev module device scull


《Linux Device Drivers》一书第三章Char Drivers的读书笔记之一。

  我们在/dev中可以查看设备节点,每个设备有一个主号码(major)以及一个副号码(minor),通常一个major号码对应某一种设备,虽然linux允许多种设备共享一个major号码。minor号码用于kernel具体进行设备的对应,kernel并不了解对应在minor后面设备具体的应用。

  在一个kenrel module的程序中,我们需要将我们的程序和某个或某组设备节点对应起来。在这个scull的例子中,使用的是char型的设备节点,他是内存中的某一个部分(这样无需特别的设备)。这些设备可能已经有固定的主号码,也可能没有而采用系统自动分配的方式。通过下面的例子来学习。

   头文件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如下,我们学习三个函数:

int register_chrdev_region(dev_t first,unsigned int count,char *name);

int alloc_chrdev_region(dev_t * dev, unsigned int firstminor, unisgned int count ,char *name);

void unregister_chrdev_region(dev_t first, unsigned int count);

#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;

 static int      scull_major = SCULL_MAJOR;

 static int __init scull_init(void)
 {
         printk("Scull module init enter/n");
         if(scull_major){ /* 根据major和minor号码获得dev */ 
                dev = MKDEV(scull_major,SCULL_MINOR_MIN ); 
                 is_get_dev = register_chrdev_region (dev, SCULL_DEV_NUM,"scull");//注册 
         }else{  /* 系统动态分配 */ 
                is_get_dev = alloc_chrdev_region (&dev,SCULL_MINOR_MIN, SCULL_DEV_NUM,"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_DEV_NUM ); 
                 printk("Scull module exit/n");
         }
 }

 module_init(scull_init);
 module_exit(scull_exit);

  如果这些设备节点已经存在于系统中,可以在/dev中查看,也可以在/proc/devices中查看major号码和设备名称的对应。我们手动去mknod我们的设备节点,这种情况,major号码为我们手动配置的主号码,在scull.h的宏定义中去定义,或者我们也可以在加载模块的时候作为参数带入。如果我们由系统进行动态分配,那么需等待系统分配后,知道主号码,才能创建设备节点。我们可以利用脚本来完成这个工作,下面是加载模块,并自动创建节点的脚本scull_load

[wei@wei ~]$ cat scull_load
 #!/bin/sh
 module="scull"
 device="scull"
 mode="644"#加载节点,如果加载不成功(可能已经load过),则退出 
/sbin/insmod ./$module.ko $* || exit 1 
#如果/dev中含有以前创建的节点,删除它们,当然我们也可以判断major号是否和分配的一直,来决定保留或者删除 
rm -f /dev/${device}[0-3]
 
#这是获取major号的过程,awk的使用,可以参考文档:http://www.ibm.com/developerworks/cn/linux/shell/awk/awk-1/    将/proc/devices作为输入,按行输入,如果第二个参数匹配$module,这打印第一个参数,也即赋值给major 
major=$(awk "/$2==/"$module/" {print /$1}" /proc/devices)
 echo major=${major} 
 
#mknod四个设备节点 
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#一般而言,kernel模块的操作权限都是root,但是有时候我们希望某些用户也可以有读取的权限需要修改设备节点的权限。下面允许组wei的操作,如果组wei不存在,则为组moblin。 
group="wei"
 grep -q '^wei:' /etc/group|| group="moblin"
 chgrp $group /dev/${device}[0-3]
 chmod $mode /dev/${device}[0-3]

  下面是卸载是的脚本scull_unload,我们需要删除创建的设备节点。

[wei@wei ~]$ cat scull_unload 
 #!/bin/sh
 module="scull"
 device="scull"#如果没有加载该模块结束,否则卸载模块,并删除相关的节点。 
/sbin/lsmod | grep $module || exit 1 /sbin/rmmod $module 
 rm -f /dev/${device}[0-3]

标签:kernel,major,SCULL,编程,dev,module,device,scull
From: https://blog.51cto.com/u_9877302/6255401

相关文章

  • ThreadLocal让你的多线程编程更简单【Java多线程必备】
    一、介绍ThreadLocal是Java中的一个线程局部变量,该变量在多线程并发执行时,为每个线程都提供了一个独立的副本。简单来说,ThreadLocal提供了一种在多线程环境中,使每个线程绑定自己独立的变量的方法,每个线程可以独立地改变自己的副本,而不会影响其他线程所对应的副本。二、特性1.......
  • Javascript异步编程的4种方法
    你可能知道,Javascript语言的执行环境是"单线程"(singlethread)。所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须......
  • 【编程入门】应用市场(NodeJS版)
    背景前面已输出多个系列:《十余种编程语言做个计算器》《十余种编程语言写2048小游戏》《17种编程语言+10种排序算法》《十余种编程语言写博客系统》《十余种编程语言写云笔记》《N种编程语言做个记事本》目标为编程初学者打造入门学习项目,使用各种主流编程语言来实现。让想学......
  • MFC-GetModuleHandle获取动态链接库的模块句柄
     HMODULEhmodule=::GetModuleHandle(_T("kernel32.dll"));//获取动态链接库的模块句柄/*参数:LPCTSTR指向含有模块名称字符串的指针返回值:HMODULE,如执行成功成功,则返回模块句柄。零表示失败。获取错误信息*/     ......
  • c#中使用 async 和 await 的异步编程
    什么是异步编程异步编程是对线程的一种应用方式。类似于人跑步时戴着耳机听歌,这两个行为可以同时进行,而不是先跑完步再听歌。异步编程就是同一时间做多件事,通常异步编程就是在继续运行原有逻辑的同时,把耗时的操作放进一个单独的线程中进行并行处理,以重复利用CPU资源以及节省总的......
  • 网络编程
    一.楔子你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运行,你就会发现,这两个python的文件分别运行的很好。但是如果这两个程序之间想要传递一个数据,你要怎么做呢?这个问题以你现在的知识就可以解决了,我们可以创建一个文件,把a.py想要传递的内容写到文件中......
  • 面向对象编程
    对象的概念”面向对象“的核心是“对象”二字,而对象的精髓在于“整合“,什么意思?所有的程序都是由”数据”与“功能“组成,因而编写程序的本质就是定义出一系列的数据,然后定义出一系列的功能来对数据进行操作。在学习”对象“之前,程序中的数据与功能是分离开的,如下#数据:name、ag......
  • 2023.5.7编程一小时打卡
    一、问题描述:编写程序提示用户输入一个班级中的学生人数n,再依次提示用户输入n个人在课程A中的考试成绩,然后计算出平均成绩显示出来。二、解题思路:首先,定义一个vector类型的成员,通过用户输入的人数进行对vector的数据添加,最后进行加和求其平均值。 三、代码实现:1#include......
  • ERROR: All flavors must now belong to a named flavor dimension. Affected
    在ijkplayer-example的build.gradle中  添加flavorDimensions"800800",其中的800800为project:build.gradle中的versionCode=800800值一样。 3.   AGPBI:{"kind":"error","text":"error:\u0027@@array/pref_entries_player\u0027......
  • NOI / 1.8编程基础之多维数组
    13:图像模糊处理 1.描述给定n行m列的图像各像素点的灰度值,要求用如下方法对其进行模糊化处理:1.四周最外侧的像素点灰度值不变;2.中间各像素点新灰度值为该像素点及其上下左右相邻四个像素点原灰度值的平均(舍入到最接近的整数)。2.输入第一行包含两个整数n和m,表示图像包含......