函数idr_alloc(...)有时会因错误-EINVAL(-22)

时间:2019-05-27 07:58:02

标签: c linux-kernel linux-device-driver

我正在尝试用于IDR(整数ID管理)的内核API。这是一个ID获取与指针相关联的地图。 API已更改,因此我发现的旧示例无法正常工作。 所以我做了我自己的例子,它仅部分起作用。 有时,函数idr_alloc失败,结果为-22(-EINVAL)。

当我查看实现源代码(https://elixir.bootlin.com/linux/latest/source)时,发现唯一的错误是-ENOMEM,没有内存和-ENOSPC(没有更多ID)。 我将代码编译为:Linux ubuntu 4.15.0-33-generic。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/idr.h>

struct idr map;

char *cptr1 = "Chennai";
char *cptr2 = "Lockheed Martin";
char *cptr3 = "Libary";

int deleter (int id, void *ptr, void *data ) {
    idr_remove( &map, id );
    return 0;
}

int showKeyValuePair( int id, void *ptr, void *data ) {
    printk("Key : %d | Value : %s\n", id, (char *)ptr );
    return 0;
}

static int __init mod_init(void)        
{                                                                   
    int id[3];
    char *ptr;

    printk("IDR\n");    
    idr_init( &map );       

    id[0] = idr_alloc( &map, (void *)cptr1, 0, 0, GFP_KERNEL );
    id[1] = idr_alloc( &map, (void *)cptr2, 0, 0, GFP_KERNEL );
    id[2] = idr_alloc( &map, (void *)cptr3, 0, 0, GFP_KERNEL );

    printk("Reserved ID's : {%d, %d, %d}\n", id[0], id[1], id[2] );

    ptr = idr_find( &map, id[0] );
    printk("Find for ID %d = %s\n", id[0], (ptr != NULL) ? ptr : "not found" );


    idr_for_each( &map, showKeyValuePair, NULL );

    return 0;
}

static void __exit mod_exit(void) 
{
    idr_for_each( &map, deleter, NULL );    
    idr_destroy( &map );        // void idr_destroy (struct idr *)
}

module_init(mod_init);  
module_exit(mod_exit);
MODULE_LICENSE("GPL");

1 个答案:

答案 0 :(得分:1)

好吧,我发现Linux ubuntu 4.15.0-33-generic中的实现存在错误。我针对内核源代码树4.9.0-8-amd64版本编译了代码,结果成功了。 启动时返回代码-EINVAL,idr_alloc的第三个参数小于0,但是不是这种情况,但是idr_alloc在旧版本中调用idr_alloc_cmn,这可能返回了-EINVAL。我找不到idr_alloc_cmn的实现,但最重要的是:现在可以使用。