【代码模板】Linux内核模块带指针的函数如何返回错误码?(ERR_PTR(-ENOMEM)、IS_ERR(ent)、PTR_ERR(ent))
背景
Linux内核模块中的函数如果返回值是指针,出现异常的时候如何返回多样的内核错误呢?
方法
通过Linux内核的ERR指针模式。然后返回后使用内核接口来判断是否有异常。
函数中:
函数定义的地方:
struct mlx5_cache_ent *
mlx5r_cache_create_ent_locked(struct mlx5_ib_dev *dev,struct mlx5r_cache_rb_key rb_key,bool persistent_entry)
{ent = kzalloc(sizeof(*ent), GFP_KERNEL);if (!ent)return ERR_PTR(-ENOMEM); //这里是ERR_to_PTR将errno转换为指针,注意有-符号。 ...
}判断返回值的地方:ent = mlx5r_cache_create_ent_locked(dev, rb_key, true);if (IS_ERR(ent)) { //这里用IS_ERR进行判断是否返回了err的指针ret = PTR_ERR(ent); //这里是PTR_to_ERR的意思,将ptr转化为errnogoto err;}
如果期望返回值是int类型的,直接返回errno,比如return -EPERM;
Linux内核中常见的错误检查模式
这两个接口可以简单理解中间有一个to,从xxx转化为xxx
ERR_PTR(-ENOMEM) 。
PTR_ERR(ent);
另外
IS_ERR()
只对ptr进行判断。
- 定义在include/linux/err.h中
- 用于检查指针是否实际上是一个错误码(负值)
- 如果指针值在内核保留的错误码范围内,则返回true
实战举例:
在Mellanox驱动中
pd = ib_alloc_pd(device);
if (IS_ERR(pd)) {err = PTR_ERR(pd);// 错误处理
}
作用:- 验证保护域创建是否成功- 如果失败,获取具体错误码并进行相应处理- 这是内核驱动中标准的错误处理模式
代码模板
struct my_struct *
my_func(struct my_struct * dev)
{struct my_struct *ent = NULL;ent = kzalloc(sizeof(*ent), GFP_KERNEL);if (!ent)return ERR_PTR(-ENOMEM); //这里是ERR_to_PTR将errno转换为指针,注意有-符号。 ...
}判断返回值的地方:
int my_upper_func(dev)
{ent = my_func(dev);if (IS_ERR(ent)) {ret = PTR_ERR(ent);goto err;}
}
综述
Linux内核模块中,当函数返回指针但需要报错时,可使用ERR_PTR()将错误码转换为指针。调用方用IS_ERR()检查返回值,PTR_ERR()获取原始错误码。这种模式是内核标准错误处理方式,如内存分配失败返回ERR_PTR(-ENOMEM)。对于返回整型的函数,直接返回负的错误码如-EPERM即可。该机制通过include/linux/err.h提供的宏实现,确保了内核错误处理的统一性和可靠性。