Linux register_chrdev_region 和 alloc_chrdev_region 分配设备号有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9835850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:21:23  来源:igfitidea点击:

What is the difference between register_chrdev_region and alloc_chrdev_region to allocate device numbers?

linuxlinux-kernelkerneldevicedrivers

提问by user1287763

I want to know the difference between these two functions:

我想知道这两个函数的区别:

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

回答by paxdiablo

See herefor details on these two functions.

有关这两个功能的详细信息,请参见此处

Registration is only really useful if you know in advance which major number you want to start with. With registration, you tellthe kernel what device numbers you want (the start major/minor number and count) and it either gives them to you or not (depending on availability).

如果您事先知道要从哪个主要编号开始,注册才真正有用。通过注册,你告诉内核你想要什么设备号(开始主/次号和计数),它要么给你,要么不给(取决于可用性)。

With allocation, you tell the kernel how many device numbers you need (the starting minor number and count) and it will find a starting major number for you, if one is available, of course.

通过分配,您告诉内核您需要多少个设备号(起始次要编号和计数),当然,如果有可用的,它会为您找到一个起始主要编号。

Partially to avoid conflict with other device drivers, it's considered preferable to use the allocation function, which will dynamicallyallocate the device numbers for you.

部分是为了避免与其他设备驱动程序发生冲突,最好使用分配函数,它会为您动态分配设备编号。

From the link given above:

从上面给出的链接:

Some major device numbers are statically assigned to the most common devices. A list of those devices can be found in Documentation/devices.txtwithin the kernel source tree. The chances of a static number having already been assigned for the use of your new driver are small, however, and new numbers are not being assigned. So, as a driver writer, you have a choice: you can simply pick a number that appears to be unused, or you can allocate major numbers in a dynamic manner.

Picking a number may work as long as the only user of your driver is you; once your driver is more widely deployed, a randomly picked major number will lead to conflicts and trouble.

Thus, for new drivers, we strongly suggest that you use dynamic allocation to obtain your major device number, rather than choosing a number randomly from the ones that are currently free. In other words, your drivers should almost certainly be using alloc_chrdev_regionrather than register_chrdev_region.

The disadvantage of dynamic assignment is that you can't create the device nodes in advance, because the major number assigned to your module will vary. For normal use of the driver, this is hardly a problem, because once the number has been assigned, you can read it from /proc/devices.

一些主要设备编号被静态分配给最常见的设备。可以Documentation/devices.txt在内核源代码树中找到这些设备的列表。然而,已经为您的新司机分配了静态号码的可能性很小,并且没有分配新号码。因此,作为驱动程序编写者,您有一个选择:您可以简单地选择一个似乎未使用的编号,或者您可以以动态方式分配主编号。

只要您的驱动程序的唯一用户是您,选择一个号码就可以工作;一旦您的驱动程序被更广泛地部署,随机选择的主编号将导致冲突和麻烦。

因此,对于新驱动程序,我们强烈建议您使用动态分配来获取您的主设备号,而不是从当前空闲的设备中随机选择一个号码。换句话说,您的驱动程序几乎肯定应该使用alloc_chrdev_region而不是register_chrdev_region.

动态分配的缺点是您不能提前创建设备节点,因为分配给您的模块的主编号会有所不同。对于驱动程序的正常使用来说,这几乎不是问题,因为一旦分配了编号,您就可以从/proc/devices.

There's a related, but not technically duplicate, question here.

有一个相关的,但不是技术上的重复,问题在这里

回答by nullbyte91

As per the LDD3 Document,

根据 LDD3 文档,

When setting up a character device is to obtain one or more device numbers to work with. The necessary function for this task is,

设置字符设备时是为了获得一个或多个设备号来使用。此任务的必要功能是,

int register_chrdev_region(dev_t first, unsigned int count, char *name);
(or)
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);

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

Note that,register_chrdev_region works well if you know ahead of time exactly which device numbers you want. Often, however, you will not know which major numbers your device will use; there is a constant effort within the Linux kernel development community to move over to the use of dynamicly-allocated device numbers. The kernel will happily allocate a major number for you on the fly, but you must request this allocation by using a alloc_chrdev_region. Basically its a dynamic Allocation of the Major number.

请注意,如果您提前确切知道所需的设备编号,则register_chrdev_region 可以很好地工作。然而,您通常不知道您的设备将使用哪些主要号码;Linux 内核开发社区一直在努力转向使用动态分配的设备号。内核很乐意动态地为您分配一个主编号,但您必须使用alloc_chrdev_region请求此分配。基本上它是主编号的动态分配。

Thus, for new drivers, we strongly suggest that you use dynamic allocation to obtain your major device number, rather than choosing a number randomly from the ones that are currently free. In other words, your drivers should almost certainly be using alloc_chrdev_region rather than register_chrdev_region.

因此,对于新驱动程序,我们强烈建议您使用动态分配来获取您的主设备号,而不是从当前空闲的设备中随机选择一个号码。换句话说,您的驱动程序几乎肯定应该使用 alloc_chrdev_region 而不是 register_chrdev_region。

回答by Albert

To put in simple terms: You use register_chrdev_region when you have the device ID for your character driver with you and you want to inform the VFS that reserve this device ID (basically the Major Number) for your driver.

简而言之:当您拥有字符驱动程序的设备 ID 并且您想通知 VFS 为您的驱动程序保留此设备 ID(基本上是主编号)时,您可以使用 register_chrdev_region。

dev_t mydev;
mydev = MKDEV(MAJORNO, MINORNO);//you have already decided on a static majorno and minorno
register_chrdev_region(mydev, count, CHAR_DEV_NAME)
//**here you are supplying the device ID in mydev**

You use alloc_chrdev_region when you are asking the VFS to give you a free device ID (which is basically the major number) for your character driver.

当您要求 VFS 为您的字符驱动程序提供一个免费的设备 ID(基本上是主编号)时,您可以使用 alloc_chrdev_region。

dev_t mydev;
//you are asking VFS for the device ID
alloc_chrdev_region(&mydev, start_minor_no, count, CHAR_DEV_NAME)
//**Here you get the device ID in mydev**.