函数1、Linux下的打印函数printk
来源:互联网 发布:大数据 微盘 编辑:程序博客网 时间:2024/06/01 10:23
从今天开始好好看看Linux的内核代码,听说学习代码最好的老师就是看内核中的代码,学习内核中代码的编写习惯,我打算整理一些学习笔记来督促自己学习,可恨自己太懒,呵呵呵。只打算学习内核代码,所以从源码的start_kernel函数看起,遇见不错的函数就记录两笔。至于详尽的函数代码分析这里不是重点,这里我们只分析函数用法中的亮点。
第一个函数:printk
源码:重点分析多参数函数用法。
asmlinkage int printk(const char *fmt, ...)
{
va_list args; //分析1
unsigned long flags;
int printed_len;
char *p;
static char printk_buf[1024];
static int log_level_unknown = 1;
if (unlikely(oops_in_progress))//oops_in_progress指示进程发生错误
zap_locks();
/* This stops the holder of console_sem just where we want him */
spin_lock_irqsave(&logbuf_lock, flags);//一般spin_lock在单cpu中无效的,所以spin_lock_irqsave真正的作用是关中断 和保存状态寄存器。
/* Emit the output into the temporary buffer */
va_start(args, fmt);//分析2
printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);分析3
va_end(args);//分析4
........省略一大段代码.
}
/*********************************************分析可变参数函数*************************************************/
可变参数函数学习
分析1:
va_list args;
va_list是一个宏,由va_start和va_end界定。
定义如下:
#ifdef _M_ALPHA
typedef struct {
char *a0; /* pointer to first homed integer argument */
int offset; /* byte offset of next parameter */
} va_list;
#else
typedef char * va_list;
#endif
_M_ALPHA是指DEC ALPHA(Alpha AXP)架构。所以一般情况下va_list所定义变量为字符指针。
在printk(const char *fmt, ...)函数中,va_list是一个字符指针,是指向当前参数的一个指针。
调用参数表之前,先定义一个va_list类型的变量,以供后用(如va_list类型变量被定义为args),接着对args进行初始化,让它指向可变参数表里面的第一个参数。这是通过va_start来实现的,它的第一个参数是args本身,第二个参数是在变参表前面紧挨着的一个变量。获取参数调用va_arg它的第一个参数是args,第二个参数是要获取的参数的指定类型,并返回这个指定类型的值同时把args的位置指向变参表的下一个变量位置。获取所有参数之后,我们需要将这个args指针关掉,以避免发生危险,方法是调用va_end。它将输入的参数args置为NULL。
这里我们也应该学习一下va_start和va_end这两个宏写法:
1、#define va_start(ap,t) (args = (va_list)&v) + INTSIZEOF(v))
ap是类型va_list的指针,v是可变参数最左边的参数。
2、#define va_arg(ap,t) (*(t*)((ap +=_INTSIZEOF(t)) - _INTSIZEOF(t)))
va_arg(ap,t)宏获取可变参数的当前参数,返回指定类型并将指针指向下一个参数(t参数描述了当前参数的类型)
3,define va_end(ap) (ap = (va_list)0)
va_end宏用于清空va_list可变参数列表。
注:_INTSIZEOF宏是获取类型占用的空间长度,最小占用长度为int的整数倍。宏函数如下:
#define _INTSIZEOF(N) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
这里,移动指针使其指向下一个参数,偏移量是多少是个关键的问题。这里涉及到内存对齐问题,内存对齐与具体的硬件平台有关。va机制中用宏_INTSIZEOF(N)解决了这个问题。用_INTSIZEOF(N)宏求出变量占用内存空间大小是va实现的基础。
有了这些分析我们举一个使用可变参数的例子:
int max(int n, ...) // 定参 n 表示后面变参数量,定界用,输入时切勿搞错
{va_list ap; // 定义一个 va_list 指针来访问参数表
va_start(ap, n); // 初始化 ap,让它指向第一个变参
int maximum = -0x7FFFFFFF; // 这是一个最小的整数
int temp;
for(int i = 0; i < n; i++)
{
temp = va_arg(ap, int); // 获取一个 int 型参数,并且 ap 指向下一个参数
if (maximum < temp)
maximum = temp;
}
va_end(ap); // 善后工作,关闭 ap
return maximum;
}
// 在主函数中测试 max 函数的行为(C++ 格式)
int main()
{
cout << max(3, 10, 20, 30) << endl;
cout << max(6, 20, 40, 10, 50, 30, 40) << endl;
}
(PS:参考了别人的代码)
像printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);分析3列出一些源码方便自己以后慢慢分析。
- 函数1、Linux下的打印函数printk
- Linux内核打印函数printk的使用说明
- Linux内核打印函数printk的使用说明 .
- 内核打印函数printk
- linux printk函数
- 用函数printk打印内核信息的方法
- 用函数printk打印内核信息的方法
- printk()函数的总结
- printk()函数的使用
- printk()函数的总结
- printk函数的使用
- printk()函数的总结
- printk()函数的总结
- printk()函数的总结
- printk()函数的使用
- printk()函数的使用
- printk()函数的使用
- printk()函数的总结
- AJAX中文乱码总结
- C++ 异常
- jxcx_Hermes(Mdrill)安装-1
- 信用卡还款
- 三层问题—“系统找不到指定的文件”
- 函数1、Linux下的打印函数printk
- .NET开发者必备的工具箱
- Android布局管理器介绍
- 写paper 心得
- Handler消息传递学习笔记
- CreateProcess failure, error 2
- 啊哈C——学习4.5练习
- LINUX编程下自定义库的生成与动静态链接
- pojPOJ 2411--Mondriaan's Dream+状态压缩dp