Sometimes people need to write “small” device drivers, to support custom hacks—either hardware or software ones. To this end, as well as to host some real drivers, the Linux kernel exports an interface to allow modules to register their own small drivers. The misc driver was designed for this purpose. The code introduced here is meant to run with version 2.0 of the Linux kernel.

In UNIX, Linux and similar operating systems, every device is identified by two numbers: a “major” number and a “minor” number. These numbers can be seen by invoking ls -l /dev. Every device driver registers its major number with the kernel and is completely responsible for managing its minor numbers. Use of any device with that major number will fall on the same device driver, regardless of the minor number. As a result, every driver needs to register a major number, even if it only deals with a single device, like a pointing tool.

Since the kernel keeps a static table of device drivers, frivolous allocation of major numbers is rather wasteful of RAM. The Linux kernel, therefore, offers a simplified interface for simple drivers—those that will register a single entry point. Note that, in general, allocating the whole name space of a major number to every device is beneficial. This allows the handling of multiple terminals, multiple serial ports and several disk partitions without any overhead in the kernel proper: a single driver takes care of all of them, and uses the minor number to differentiate.

Major number 10 is officially assigned to the misc driver. Modules can register individual minor numbers with the misc driver and take care of a small device, needing only a single entry point.

Registering a Minor Number

The misc driver exports two functions for user modules to register and unregister their own minor number:

#include <linux/miscdevice.h>
int misc_register(struct miscdevice * misc);
int misc_deregister(struct miscdevice * misc);

Each user module can use the register function to create its own entry point for a minor number, and deregister to release resources at unload time.

The miscdevice.h file also declares struct miscdevice in the following way:

struct miscdevice {
        int minor;
        const char *name;
        struct file_operations *fops;
        struct miscdevice *next, *prev;
};

The five fields have the following meaning:

·         minor is the minor number being registered. Every misc device must feature a different minor number, because such a number is the only link between the file in /dev and the driver.

·         name is the name for this device, meant for human consumption: users will find the name in the /proc/misc file.

·         fops is a pointer to the file operations which must be used to act on the device. File operations have been described in a previous “Kernel Korner” in April 1996. (That article is available on the web at http://www.linuxjournal.com/issue24/kk24.html.) Anyway, the topic is refreshed later in this article.

·         next and prev are used to manage a circularly-linked list of registered drivers.

The code calling misc_register is expected to clear prev and next before invoking the function and to fill the first three fields with sensible values.

The real question with the misc device driver is “what is a sensible value for the minor field?” Assignment of minor numbers is performed in two ways: either you can use an “officially assigned” number, or you can resort to dynamic assignment. In the latter case, your driver asks for a free minor number, and the kernel returns one.

The typical code sequence for assigning a dynamic minor number is as follows:

static struct miscdevice my_dev;
int init_module(void)
{
    int retval;
    my_dev.minor = MISC_DYNAMIC_MINOR;
    my_dev.name = "my";
    my_dev.fops = &my_fops;
    retval = misc_register(&my_dev);
    if (retval) return retval;
    printk("my: got minor %i\n",my_dev.minor);
    return 0;
}

Needless to say, a real module will perform some other tasks within init_module. After successful registration, the new misc device will appear in /proc/misc. This informative file reports which misc drivers are available and their minor numbers. After loading my, the file will include the following line:

63 my

This shows that 63 is the minor number returned. If you want to create an entry point in /dev for your misc module, you can use a script like the one shown in Listing 1. The script takes care of creating the device node and giving it the desired permission and ownership.

You might choose to find an unused minor number and hardwire it in your driver. This would save invoking a script to load the module, but the practice is strongly discouraged. To keep the code compact, drivers/char/misc.c doesn't check for duplication of minor numbers. If the number you chose is later assigned to an official driver, you'll be in trouble when you try to access both your module and the official one.

If the same minor number is registered twice, only the first one will be accessible from user space. Although seemingly unfair, this can't be considered a kernel bug, as no data structure is corrupted. If you wish to register a safe minor number, you should use dynamic allocation.

The file Documentation/devices.txt in the kernel source tree lists all of the official device numbers, including all the minor numbers for the misc driver.

Kernel Configuration

If you have tried to write your own misc driver but insmod returned unresolved symbol misc_register, you have a problem in your kernel configuration.

Originally, the misc driver was designed as a wrapper for all the “busmouse” drivers—the kernel drivers for every non-serial pointer device. The driver was only compiled if the current configuration included at least one such mouse driver. Just before version 2.0, the generality of the implementation was widely accepted, and the driver was renamed from “mouse” to “misc”. It is still true, however, that the driver is not available unless you chose to compile at least one of the misc devices as either a module or a native driver.

If you don't have any such devices installed on your system, you can still load your custom misc modules, provided you reply affirmatively, while configuring your kernel, to the question:

Support for user misc device modules (CONFIG_UMISC)

This option indicates that the misc driver is to be compiled even if no misc device has been selected, thus allowing run-time insertion of third-party modules. The file /proc/misc and support for dynamic minor numbers were implemented when this option was introduced, as there's little point in having custom modules unless the allocation of a minor number is safe.

Note that if your kernel is configured to load busmice only as modules, everything will work with the exception of /proc/misc. The /proc file is created only if miscdevice.c is directly linked in the kernel. CONFIG_UMISC takes care of this situation as well.

How Operations are Dispatched

Every time a process interacts with a device driver, the implementation of the system call gives control to the correct driver by means of the file_operations structure. This structure is carried around by struct file: every open file descriptor is associated to one such structure, and file.f_op points to its own file_operations structure.

This setup is similar to object-oriented languages: every object (here, every file) declares how to act on itself, so that high-level code is independent of the actual file being accessed. The Linux kernel is full of object-oriented programming in its implementations, and several “operations” structures exist in it, one for each different “object” (inodes, memory regions, etc.).

Back to the misc driver. How does my_dev.fops participate in the game? At open time, the kernel allocates a new file structure to describe the object being opened, and initializes its operations structure according to what the file is. Sockets, FIFOs, disk files and devices get their own, different, operations. When a device is opened, its operations are looked up according to the major device number by referencing an array. The open method within the driver is then called. Any other system call that acts on a file will then use file.f_op without checking any other source of information. As a result, a driver can replace the value of file.f_op to tailor the behaviour of a struct file to some inner feature, even if that feature is at a finer grain than the major number, and thus is not visible from the kernel proper.

The open method of the misc driver is able to dispatch operations to the actual low-level driver by modifying file.f_op; the assigned value is the one in my_dev.f_op. After the operations have been overridden, the method calls file.f_op->open(), so that the low-level driver can perform its own initialization. Every other system call invoked on the file will use the new value of file.f_op, and the low-level driver keeps complete control over its device.

如果是非标准设备则使用 misc_register,即一些字符设备不符合预先确定的字符设备范畴,就用这种方式,它固定使用主设备号10注册,如果多个设备次设备号不同。

转载于:https://my.oschina.net/fuyajun1983cn/blog/263825

Miscellaneous Character Drivers相关推荐

  1. Linux 内核中的数据结构:双链表,基数树,位图

    Linux 内核中的数据结构 rtoax 2021年3月 1. 双向链表 Linux 内核自己实现了双向链表,可以在 include/linux/list.h 找到定义.我们将会从双向链表数据结构开始 ...

  2. Linux Miscellaneous Device

    参考原文:http://www.tldp.org/HOWTO/text/Module-HOWTO 15.7. Miscellaneous Device Driver15.7.1. misc: devi ...

  3. 推荐《Essential Linux Device Drivers》

    可能绝大多数linux驱动程序员都读过ldd(linux device driver)一书.从第1版到第2.第3版.毕竟这类书少的可怜.虽然近两年国产的驱动开发书籍也日益增多,但是国外引进的书总感觉要 ...

  4. Ubuntu下的Linux内核的编译及安装

    推荐群:C/C++大学技术协会:145655849 Linux中的模块(Modules) Linux的module其实可以看作是内核的插件. 在Linux系统中,可以通过文件 cat /proc/mo ...

  5. CSDN内核模块编译讨论(总结)

    我按照下面的程序和方法试了下,很不错,开始是放在driver/char目录下的,但由于内核文件不全,编译不成功,所以把该程序拷贝到其他目录,然后新建Makefile文件.不过先要在user/src的源 ...

  6. passwd_pro

    前言 要在passwd源码上增加点功能, 先加了一个口令中不能包含用户名,增加了安全性. 试验目的 工程可以改,可以找到修改点.试验环境都留着,以后还可以接着玩. 找修改点时,先用SI建立工程,大致看 ...

  7. 《网蜂A8实战演练》——1.LED驱动

    LED 原理图都网蜂科技的 Webee210 核心板上,如下: 由以上两个图可知,LED1~LED4 对应的 GPIO 口为 GPJ2_0 ~ GPJ2_3,如果要让 LED1 亮,则设置 GPJ2C ...

  8. STM32 之十一 LL 库(low-layer drivers)详解 及 移植说明

      最新项目中需要使用 STM32L476 的片子.在选择片子时,资源的多少成为了一个比较重要的考量.在斟酌一番之后,我决定采用 LL 库来实现本次的功能.下面就以 STM32L476 为例来介绍一下 ...

  9. Unicode® Character Name Index

    [0]README 0.1) there are unicodes for varients of alphabet a, for that of b, c, or d and so on, plea ...

最新文章

  1. java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 解决方法 java.lang.ClassNotFoundException: com.
  2. 如何操作提升手机端网站的排名优化?
  3. BaaS后端即服务 - 分析篇
  4. [Medical Image Processing] 2. GrayScale Histogram and Threshold-【Isodata Algorithm】
  5. QT的QCache类的使用
  6. 内存溢出与内存泄漏区别
  7. python使用rabbitMQ介绍五(话题模式)
  8. 原创:MD5 32位加密软件
  9. matplotlib plt.plot
  10. java二叉树转换为链表_leetcode刷题笔记-114. 二叉树展开为链表(java实现)
  11. docker:安装mysql多个
  12. Django内置权限扩展案例
  13. 照片打印预览正常打印空白_小米发布口袋照片打印机,可无墨打印3寸背胶照片...
  14. 机器学习实战:PCA降维 样本协方差
  15. 游戏测试与一般的软件测试的区别在哪里?
  16. 机器学习之使用Python完成逻辑回归
  17. GitKraken 比较好用的 Git 可视化工具
  18. VS2013官方下载地址
  19. 大家一起学电脑之硬件版
  20. 国家职业资格:计算机网络管理员

热门文章

  1. 克隆Calibrui Module
  2. 今天收到了学校给出的退学警告
  3. Codeforces Round #232 Editorial Div2-B
  4. C++基础8【难】 回顾:数组指针,函数指针,函数指针做函数参数 C语言多态
  5. SQL Server 监控系列(文章索引)
  6. ios 如何对UITableView中的内容进行排序
  7. 文件上传--Smartupload上传组件【上】
  8. centos 5.3 配置sendmail服务器
  9. POJ 1703 Find them, Catch them【并查集】
  10. golang net/http 超时机制完全手册