您的位置:首页 > 其它

模块API之print_symbol

2017-11-20 10:29 253 查看
inline void print_symbol(const char *fmt, unsigned long addr) 由于根据客户给定的格式将addr
对应的symbol打印出来。
其使用的例子如下:例如这里就将dev_attr->show地址中保存的symbol 用%s打印出来.
static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct device_attribute *dev_attr = to_dev_attr(attr);
struct device *dev = kobj_to_dev(kobj);
ssize_t ret = -EIO;

if (dev_attr->show)
ret = dev_attr->show(dev, dev_attr, buf);
if (ret >= (ssize_t)PAGE_SIZE) {
print_symbol("dev_attr_show: %s returned bad count\n",
(unsigned long)dev_attr->show);
}
return ret;
}

其源码分析如下:
static inline void print_symbol(const char *fmt, unsigned long addr)
{
__check_printsym_format(fmt, "");
__print_symbol(fmt, (unsigned long)
__builtin_extract_return_addr((void *)addr));
}
可以看到print_symbol 中首先调用sprint_symbol 找到address 对应的symbol,并将其保存在buffer中
然后通过printk将字符串buffer中的字符串打印出来。

void __print_symbol(const char *fmt, unsigned long address)
{
char buffer[KSYM_SYMBOL_LEN];

sprint_symbol(buffer, address);

printk(fmt, buffer);
}
从这里可以看出kernel中对变量的name的长度的限制就是KSYM_SYMBOL_LEN。其算法如下:
#define KSYM_NAME_LEN 128
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)

关于__builtin_extract_return_addr 函数的作用可以在http://gcc.gnu.org/ 这个网站上查
关于这个函数的查询的网址为https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html#index-_005f_005fbuiltin_005fextract_005freturn_005faddr
Built-in Function: void * __builtin_extract_return_addr (void *addr)
The address as returned by __builtin_return_address may have to be fed through this function to get the actual encoded address. For example, on the 31-bit S/390 platform the highest bit has to be masked out, or on SPARC platforms an offset has to be added for the true next instruction to be executed.

If no fixup is needed, this function simply passes through addr.
可见这个函数主要是修复bug的,如果对应的平台没有bug的话,则相当如下定义:
#define __builtin_extract_return_addr((void *)addr) (addr)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: