看printk引发的一点思考

在源码位置

kernel/printk/

函数原型

asmlinkage __visible int printk(const char *fmt, ...)
{printk_func_t vprintk_func;va_list args;int r;va_start(args, fmt);/** If a caller overrides the per_cpu printk_func, then it needs* to disable preemption when calling printk(). Otherwise* the printk_func should be set to the default. No need to* disable preemption here.*/vprintk_func = this_cpu_read(printk_func);r = vprintk_func(fmt, args);va_end(args);return r;
}
EXPORT_SYMBOL(printk);

fmt,...用法举个例子

#include "stdio.h"void tfunc(const int fmt,...)
{printf("tfunc...\n");
} int main(void)
{tfunc(12);tfunc(12,13);tfunc(12,13,14);return 0;
} 

输出

tfunc...
tfunc...
tfunc...--------------------------------
Process exited after 0.04347 seconds with return value 0
请按任意键继续. . .

再举个例子

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
int maxof(int, ...);
void f(void);/*主函数*/
int main()
{f();exit(EXIT_SUCCESS);
}int maxof(int n_args, ...)
{register int i;int max=0, a=0;va_list ap;va_start(ap, n_args);max = va_arg(ap, int);printf("max:%d a:%d n_args:%d\n",max,a,n_args);for(i = 1; i < n_args; i++){if((a = va_arg(ap, int)) > max){max = a;}printf("[%d] max:%d a:%d\n",i,max,a);}va_end(ap);return max;
}void f(void) 
{int i = 5;int j = 26;printf("\nmax:%d\n",maxof(3,i,j,13));
}

输出

max:5 a:0 n_args:3
[1] max:26 a:26
[2] max:26 a:13max:26--------------------------------
Process exited after 0.0439 seconds with return value 0
请按任意键继续. . .

说点自己的理解

作为初学者,第一次看到

fmt,...

这样的写法,心里就会有点懵逼,但是实际上,你把它作为C语言的一个知识点,记下来了,就没有那么困难了。既然作为可变参数标识,那么函数体里面,自然也需要解析的方法,我上面写的那个例子,就是解析的方法。

不管是Linux 内核里面的printk函数,还是我们平时调试打印的printf函数,他们都是一样的原理。

解析可变参数

解析就离不开这三个宏

va_list ap;
va_start(ap, n_args);
va_end(ap);

这里面需要涉及到一些技巧,这篇文章里面就不解析说明了,printf 和printk里面使用的还有些差异,无非就是C语言的奇淫异巧,把这种普通人理解不了的东西形容为降龙十八掌,九阴真经,我觉得并不为过。

Linux 驱动打印日志加上自己的TAG

好了,直接上代码就好了,我们平时打印的时候都是直接用一个printk,也没有经过封装,代码这种东西,你要是把它看作是一个艺术品也并不为过,所以很多人谈到一个词,叫做技艺,你自己把这种知识点都掌握了,自己的技艺也就会得到提升了。

#define LOG_TAG "[ES7243]: %s() line: %d " 
#define Log(fmt, args...)  printk(KERN_INFO LOG_TAG fmt, __FUNCTION__, __LINE__,  ##args)

## 这个符号的作用

在C语言里面,## 有两个作用

  • 在函数里面和可变参数一起使用,如果可变参数没有传参,这个符号就把前面的 「,」去掉,这样编译就不会出错。

  • 如果是宏里面使用,就起到一个拼接字符的作用

举个例子

#include<stdio.h>#define LOG_TAG "[ES7243]: %s() line: %d " 
#define func(fmt, ...) printf(LOG_TAG fmt, __FUNCTION__, __LINE__,  ##__VA_ARGS__)
#define acpi_handle_debug( fmt, ...) printf( fmt, ##__VA_ARGS__)
#define debug(...) printf(__VA_ARGS__)#define _TEST_(x) x##2
int main()
{int i = 23;func("adf:%d\n",++i);debug("123:%d\n",++i);acpi_handle_debug("4444\n");func("%d\n",_TEST_(1));return (0);
}

输出

[ES7243]: main() line: 12 adf:24
123:25
4444
[ES7243]: main() line: 16 12--------------------------------
Process exited after 0.03505 seconds with return value 0
请按任意键继续. . .

推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467542.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

寄语

寄语&#xff1a; 前面漆黑一片&#xff0c;什么都看不到。 也不是&#xff0c;天亮后就会很美的。转载于:https://www.cnblogs.com/doudou-taste/p/7660997.html

我毕业时候写的简历

写简历这个事情&#xff0c;一直是一个非常让人头疼的&#xff0c;在我看来&#xff0c;写简历并不是一件简单的事情&#xff0c;所以&#xff0c;现在是晚上一点钟&#xff0c;我倒腾了一个晚上&#xff0c;才有了这篇文章。我认为写简历有几个需要注意的地方&#xff0c;不啰…

idea java 非法字符_解决IDEA显示非法字符 \ufeff 的问题

一、问题在txt文本中复制代码进入IDEA报错Error:(1, 1) java: 非法字符: ‘\ufeffError:(1, 10) java: 需要class, interface或enum二、解决办法用IDEA转换&#xff0c;先转换为GBK&#xff0c;再转回UTF-8()补充知识&#xff1a;Eurake问题Failed to bind properties under eu…

css 单行/多行文字垂直居中问题

例子可以直接看这里 http://www.zhangxinxu.com/study/200911/line-height-text-v-center.html 这篇文章中有一点点解释 http://blog.csdn.net/hdchangchang/article/details/47086565 这一篇提出了一个新想法 http://caibaojian.com/css-vertical-middle.html 总的来说&#x…

Linux 内核完成接口

Linux 内核里面有一个函数wait_for_completion&#xff0c;这是一个内核同步机制的函数&#xff0c;同步机制如果是早期的读者应该看过我发的文章&#xff0c;如果没有看过的可以看看Linux 专辑文章里面找找。既然是同步机制&#xff0c;主要的工作就是调用了这个函数&#xff…

java 换行符 常量_6.java常量

Java中常量的分类&#xff1a;整数常量 &#xff1a; 所有整数小数常量 &#xff1a; 所有小数布尔常量 &#xff1a; 只有true和false字符常量 &#xff1a;使用’’引起来的单个字符字符串常量 &#xff1a;使用“”引起来的字符序列&#xff0c;“” 、“a” 、” ”null常…

关于测试

这是5月份和公司同仁做的分享&#xff0c;分享主题是关于测试&#xff0c;是我自己对于测试的一些认知&#xff0c;以及态度的转变。 目录 以怎样的心态面对测试 安全测试贯穿整个软件生命周期 总结 以怎样的心态面对测试 提问大家几个小问题&#xff1a; 你喜欢测试吗&#…

涨疯了,历史总是如此相似

2015年的股市&#xff0c;如果你经历过&#xff0c;那你一定会记忆犹新。最近的股市太猛了&#xff0c;写一篇文章纪念一下~mark上周五&#xff0c;在一个炎热的晚上&#xff0c;我跟4个股神在深圳坪洲的某个火锅店相遇&#xff0c;虽然他们都是富甲一方的富豪&#xff0c;虽然…

java基础语句_【Java基础-Java语言基础】

知识点&#xff1a;1.关键字  2.标识符  3.变量和常量一、关键字1.Java中的关键字有很多一共53个关键字有两个是保留字(java的关键字都是小写的&#xff01;&#xff01;)2.Java中的保留字(1)const  常量&#xff0c;数量(2)goto   转到3.Java的关键字(1)访问修饰符的关…

【BZOJ3514】Codechef MARCH14 GERALD07加强版 LCT+主席树

【BZOJ3514】Codechef MARCH14 GERALD07加强版 Description N个点M条边的无向图&#xff0c;询问保留图中编号在[l,r]的边的时候图中的联通块个数。 Input 第一行四个整数N、M、K、type&#xff0c;代表点数、边数、询问数以及询问是否加密。接下来M行&#xff0c;代表图中的每…

安卓9.0Sensor框架

前言本来如果只是给传感器写个驱动并提供能读取温湿度数据的节点&#xff0c;是一件比较轻松的事情&#xff0c;但是最近上层应用的同事要求我们按照安卓标准的流程来&#xff0c;这样他们就能通过注册一个服务直接读取传感器事件数据了。这样做的好处就是第三方的应用也能正常…

java ognl表达式_java -------ognl表达式入门

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼------------------------------------------------------------------------------------ognl:对象表达式语言&#xff0c;可以用一个表达式快速地访问一个对象的属性&#xff0c;还可以调用对象的方法--------------------------…

Theano 更多示例

Logistic函数 logistic函数的图&#xff0c;其中x在x轴上&#xff0c;s(x)在y轴上。 如果你想对双精度矩阵上的每个元素计算这个函数&#xff0c;这表示你想将这个函数应用到矩阵的每个元素上。 嗯&#xff0c;你是这样做的&#xff1a; xT.dmatrix(x) s1/(1T.exp(-x)) logisti…

SensorKernel层框架分析

接上文安卓9.0Sensor框架前言前面我们已经讲解了sensor框架中的framework到vendor层&#xff0c;这篇文章我们将会讲解kernel层的内容。不过不同的芯片平台&#xff0c;kernel层中的sensor框架是不同的&#xff0c;这里针对的是mt8167s平台。不过这里提醒一下&#xff0c;MTK平…

【习题 5-8 UVA - 230】Borrowers

【链接】 我是链接,点我呀:) 【题意】 在这里输入题意 【题解】 用mapset写个模拟就好。 3个区域 书架、桌子、别人的手上。 其中前两个区域的书都能借出去。 【代码】 #include <bits/stdc.h> using namespace std;set <pair<string, string> > mset1,mse…

java requestparams_java – 如何验证@RequestParams不为空?

我有一个计算器服务,从用户获取操作类型num1和num2.我需要验证用户是否实际输入了这些值,而不是将其留空.RequestMapping(value "/calculate")ResponseBodypublic CalculationResult calculate(RequestParam(name "op") String operation, RequestParam(…

Linux内核LED子系统、请务必看

前言LED子系统你要是说很难嘛&#xff0c;但是它就是控制一些简单的GPIO口&#xff0c;但是你要是说它很简单嘛&#xff0c;但是我也不见得一个初学者很快就能掌握&#xff0c;你如果是刚入门这部分的话&#xff0c;我觉得你还是要去仔细研究下这些驱动。前两天在网上看到一句话…

UVALive 4394 String painter

题目大意&#xff1a;有两个字符串A,B&#xff0c;一次刷可以把A串一段刷成同一个字母&#xff0c;问至少要刷几次才能把A串变成B串。串长≤100。 本来以为是个很简单的区间DP&#xff0c;后来发现直接区间DP是不行的&#xff0c;这玩意有后效性&#xff1a;刷完一整块之后这一…

centos 6.5 安装 lamp 后mysql不能启动_CentOS 6.5 系统 LAMP(Apache+MySQL+PHP)安装步骤

先来解释一下&#xff0c;什么是 LAMP。正如标题所言&#xff0c;LAMP 实际上就是 Linux、Apache、MySQL、PHP 四个名称的缩写&#xff0c;当然最后一个 “P” 还有其他说法是 Perl 或者 Python。不用多说了&#xff0c;本文讲解的就是 Linux、Apache、MySQL、PHP 这四个东西&a…

Redis连接实例

ECS Windows服务器 如果您本地需要通过公网访问 云数据库 Redis&#xff0c;可以在 ECS Windows 云服务器中通过 netsh 进行端口映射实现。 1. 登录 ECS Windows 服务器&#xff0c;在 CMD 执行以下命令。&#xff08;公网地址与 连接地址 请替换 为您的实际地址。&#xff09;…