printf到printk的转变

从printf到printk:深入解析C语言与Linux内核的打印函数原理与应用 在C语言和Linux系统开发中,格式化输出函数是调试和日志记录的基础工具。其核心原理基于可变参数机制和缓冲区管理,通过系统调用实现用户空间与硬件的交互。在Linux内核开发中,printk函数则面临更复杂的环境约束,如无阻塞要求、内存分配限制和多核并发处理,其设计采用了环形缓冲区和优先级机制来确保系统稳定性。理解这些底层机制对于开发高性能、高可靠性的系统软件至关重要,特别是在驱动开发和内核调试场景中。掌握printf的缓冲区优化与printk的日志级别控制,能有效提升调试效率和系统可维护性。 阅读详情

昨天下午stepbystep的为其他同学演示了内核模块编程hello,kernel!在陈老师的指导下,先为大家演示了最基本的C程序hello,world。然后又一步步的转换成内核模块程序。在这一步步的转变过程中,我也发现了自己在学习内核模块中的不足,下面将下午遇到的一些问题总结如下。

一个简单的hello,world程序如下:

#include <\stdio.h\>
int main()
{
	printf("hello,world\n");
	return 0;
}

对于上面的程序,我们通常一步到位进行编译:

gcc hello.c -o hello

这样的命令简单方便,不过通常会让我们忽略从.c文件到可执行文件的整个编译过程。通常在使用gcc编译程序时,编译过程通常会分为4个阶段,即预处理(pre-processing),编译(compiling),汇编(assembling),链接(linking)。

在预处理阶段,一般输入的是.c文件,而输出的是.i文件。在此阶段中通常会处理源文件中的预处理命令,比如#define,#include,#ifdef等命令。如果想要生成这种.i中间文件,那么可以使用下面命令:

gcc -E hello.c -o hello.i

在编译阶段,输入的是.i中间文件,输出的是.s汇编语言文件。可以使用下面的命令:

gcc -S hello.i -o test.s

在汇编阶段,输入的是上一步产生的.s文件,产生的是二进制机器代码.o文件。此阶段对应的命令如下:

gcc -c test.s -o test.o

在链接阶段,输入的是.o二进制机器代码文件,连同其他的(如果有的话)机器代码文件和库文件一起汇集成一个可执行的二进制代码文件。

gcc test.o -o test

以上是一个程序编译完整的四个阶段。一般来说我们会将前三个阶段一步搞定,那么整个编译过程可以用下面两条命令就完成:

gcc -c test.c -o test.o
gcc test.o -o test

也就是先生成目标文件,再将目标文件连接成可执行文件。当你熟悉了整个编译过程后,可以用一开始我们说的一条命令来完成。

了解普通文件的编译过程,我们现在就将hello.c中的代码转换成模块编程中的.c代码。首先我们要更改头文件:

#include <\linux/kernel.h\>
#include <\linux/module.h\>

这与我们一般的头文件不同。一般我们在用户态下编写C程序,头文件会放在:/usr/include/下,而我们模块编程时,它使用的是内核中的头文件,一般在:cd /usr/src/linux-headers-2.6.32-21/include/。特别的我们这里使用的是include/目录下linux/这个子目录中的头文件,因此模块编译的时候会自动在内核中的include/目录下找linux/kernel.h这样的头文件。

其次,printf到printk是一个典型的用户态下编程与内核模块编程的不同。可能我们一开始会比较奇怪,为什么我make成功,加载也成功,但是就是不能显示printk里面的语句呢?我们可以这么想printk就是专门为内核“服务”。它一般输出的语句都在内核的日志文件当中。


Linux:printk与printf的区别 内核层使用printk打印,应用层调用C库的printf打印。在内核层是调用不了文件系统中C库的printf只能用printk。  两者之间的一个显著区别在于printk允许通过指定一个标志来设置优先级(在include/linux/kern_levels.h中定义),不写则默认为级别4(MESSAGE_LOGLEVEL_DEFAULT),级别高于设定的输出级别才可以显示(可在include/linux/printk.h修改宏CONSOLE_LOGLEVEL_DEFAULT设定输出级别,默认为7): 定义 级别 含义 KERN_EMERG 0 最高级别,紧急事件 KERN_A 立即下载

相关推荐

MTK平台 MT6789 烧录 efuse 3.0 Configuration SOP

=====================生成cert1和cert2 key===============================================生成efuse key相关文件===========================================签名DA==========================================================正常编译。=====================Security3.0 的SOP 说明。

a785722173的博客 2334

printk()和printf()的比较

printk()

weixin_42031299的博客 4135

STM32F103串口接收中断:USART_IT_IDLE和USART_IT_RXNE区别

2:如果是大于1个byte的数据,在不用DMA的情况下,同时使能USART_IT_RXNE,USART_IT_IDLE中断,每收到一个字节在中断中把数据存到缓存中,待收到USART_IT_IDLE中断时,收完整帧数据,然后再解析处理数据。比如:如上图在初始化时,同时开启了两个中断,如果传送8个字节的数据,就会产生8个USART_IT_RXNE,和1个USART_IT_IDLE中断。(如果接收到数据,在1个byte的时间内,没有收到新数据,就认为是数据传送完成,产生空闲USART_IT_IDLE中断)

weixin_66299220的博客 2403

c语言中printk用法,printk和printf的区别

&&&大部分常用的C库函数在Linux内核中都已经得到了实现。在所有没有实现的函数中,最著名的就数printf()函数了。内核代码虽然无法调用printf()函数,但它可以调用printk()函数。printk()函数负责把格式化好的字符串拷贝到内核日志缓冲上,这样syslog程序就可以通过读取该缓冲区来获取内核信息。printk()的用法很像printf():&p...

weixin_30391353的博客 3222

图形学基础知识:着色(三)Rendering Pipeline与Shader

管线(Pipeline) 什么是管线? 管线我们可以理解为流水线,流水线大家都懂,就是工厂里面生产东西的一整套流程。例如饮料厂要生产饮料,需要洗瓶子,倒饮料,加盖,包装等等,这一整套过程就是流水线。那么我们要把一个三维场景渲染成一幅二维的图像,同样需要一个先干嘛再干嘛然后干嘛最后干嘛的过程,这个过程或流水线,我们就称之为管线。 实时渲染管线(Real-time Rendering Pipeline) 通过前面几篇的学习,我们知道了要把一个三维场景渲染成一幅二维的图像大致分为以下几个步骤: M.

王王王渣渣的博客 2533

Hyper-V创建Ubuntu虚拟机设置固定IP

本文记录使用hyper-v创建ubuntu虚拟机,为虚拟设置固定IP且通过物理机可访问。

2623

printf和printk

printk 的输出通常会发送到内核日志,可以通过 dmesg 命令或者在 /var/log/messages(或其它系统日志文件)中查看。4.性能:printk 的设计考虑了在内核态下的性能和安全性,因此它比 printf 更为轻量级,并且在某些情况下它的行为可能会有所不同。3.输出位置:printf 的输出通常直接显示在控制台或命令行界面,而 printk 的输出会进入内核日志。printf 和 printk 都是用于打印信息的函数,但它们应用在不同的编程环境和操作系统层面。

读书 行路 做人 成事 833

ADRC自抗扰控制:工程抗扰“黑科技”,附C代码实战!

自抗扰控制(ADRC)是一种革新性的强鲁棒控制策略,通过主动估计和补偿系统扰动,无需精确数学模型即可实现优异控制性能。本文详细解析ADRC三大核心组件:跟踪微分器(TD)实现指令柔化,扩张状态观测器(ESO)实时估计总扰动,非线性状态反馈(NLSEF)完成动态补偿。针对二阶系统,文章提供完整的参数设计方法和C语言实现框架,包括关键函数fhan和fal的代码实现。ADRC将复杂对象"线性化"为积分器串联系统,显著提升抗扰能力,特别适用于电机控制、飞行器姿态等存在模型不确定性和强干扰的场景。

技术工作者 1737

printk( )函数

  printk()函数的总结我们在使用printk()函数中使用日志级别为的是使编程人员在编程过程中自定义地进行信息的输出,更加容易地掌握系统当前的状况。对程序的调试起到了很重要的作用。(下文中的日志级别和控制台日志控制级别是一个意思)printk(日志级别 "消息文本");这里的日志级别通俗的说指的是对文本信息的一种输出范围上的指定。日志级别一共有8个级别,printk的日志级别定义如下(

雨云轩 1249

手把手教你用RTL8306MB搭建小型网络交换机:从原理到实战

本文详细介绍了如何使用RTL8306MB交换芯片从零搭建小型网络交换机的全过程。内容涵盖芯片原理分析、核心硬件电路设计(包括电源、时钟、RMII接口连接要点)、驱动开发与SMI通信实现,以及从物理链路到交换功能的系统调试实战。重点解析了将MAC5配置为RMII PHY模式与CPU对接的关键步骤和常见错误,帮助嵌入式开发者深入理解网络交换原理并完成实践。

weixin_29274969的博客 193

基于STM32、HAL库的MPX5500DP气压传感器 驱动程序设计

define MPX5500DP_MIN_VOLTAGE 0.2f // 最小输出电压(V)#define MPX5500DP_MAX_VOLTAGE 4.7f // 最大输出电压(V)#define MPX5500DP_MIN_PRESSURE 0.0f // 最小压力(kPa)#define MPX5500DP_MAX_PRESSURE 500.0f // 最大压力(kPa)* @brief 读取压力值(kPa)// 计算压力值 (线性转换)

corlin6688的博客 196

(转).c文件到可执行文件的整个编译过程

printf到printk的转变出处:                          2010年9月15日 由 edsionte 留言 ? 昨天下午stepbystep的为其他同学演示了内核模块编程hello,kernel!在陈老师的指导下,先为大家演示了最基本的C程序 hello,world。然后又一步步的转换成内

技术札记 725

Unreal使用nDisplay制作裸眼3D(9宫格)

摘要: nDisplay是虚幻引擎的分布式实时渲染技术,可将内容同步输出到多个显示设备(如LED墙、投影仪等),构建沉浸式可视化系统。其核心功能包括:分布式渲染(支持多台设备协同处理高分辨率内容)、空间透视校正(通过追踪观众动态调整画面几何关系)以及虚拟拍摄应用。配置时需设置集群组件(Cluster、Host、Node、Viewport)定义渲染逻辑,空间组件(nDisplayScreen、ViewPoint)确定投影关系。文中以9宫格配置为例,详细演示了从工程创建到影片渲染合成的全流程,最终通过多视口合成

TxNet 609

3_Linux内核模块介绍

Linux内核模块的插入和删除 系统版本为:Ubuntu 18.04.1 LTS 内核版本为:4.15.0-43-generic 为什么Linux系统会提供模块? 随着OS的演化,功能越来越多,就会有一个问题:Linux本身是一个单内核,它的效率高但是它的可扩展性和可维护性差,如果把所有的功能都放到OS的内核中,那么内核就会非常庞大并且笨拙,如果不放在内核中,那么这些功能要么不能运行,要么运行...

weixin_42885923的博客 175

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Linux:printk与printf的区别、echo 0 > /proc/sys/kernel/printk

1、printk与printf的区别 内核层使用printk打印,应用层调用C库的printf打印。在内核层是调用不了文件系统中C库的printf只能用printk。两者之间的一个显著区别在于printk允许通过指定一个标志来设置优先级(在include/linux/kern_levels.h中定义),不写则默认为级别4(MESSAGE_LOGLEVEL_DEFAULT),级别高于设定的输出级别才可以显示(可在include/linux/printk.h修改宏CONSOLE_LOGLEVEL_DEFAULT

weixin_44498318的博客 2959

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

printf()、printk()、消息级别、日志级别

文章目录1. printf() 与 printk()2. printk() 的消息级别3. 控制台的日志级别(console_loglevel)4. /proc/sys/kernel/printk 1. printf() 与 printk() 用户空间有 printf(),内核空间有 printk(),他们就如代表善与恶得命运双生子,即使长相功能如何的接近,都不能在代码中共存。 对于我们来说,最容易犯的错误是,在需要 printk() 的地方误用了 printf(),而在需要 printf() 的地方又误用

lyndon 1万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【转】printk和printf 实现完全不一样

这两个函数是经常用到的函数,闲暇之余,剖析下这两个函数的原理。这两个函数都是把字符串打印到终端上。其最终所要做的就是把存放在缓存区里的内容输出到串口。 printk   printk函数在kernel/printk.c中,其把主要工作交给了vprintk。vprintk经过vscnprintf把要打印的数据格式化 后存放到printk_buf缓存区中,然后通过emit_log_char把要打印

务实的理想主义者 2306

Printf and Printk

对于做嵌入式或者熟悉linux内核的人来说,对printk这个函数一定不会感到陌生。printk相当于printf的孪生姐妹,她们一个运行在用户态,另一个则在内核态被人们所熟知。   printk是在内核中运行的向控制台输出显示的函数,Linux内核首先在内核空间分配一个静态缓冲区,作为显示用的空间,然后调用sprintf,格式化显示字符串,最后调用tty_write向终端进行信息的显示。

438

【转】Linux内核中printf的实现(printk与vprintk)

大家应该都在找printf的实现,其实linux内核中就有,我本来想查一下,既然linux覆盖了中断向量表,那么怎么输出文字?就查printk的代码,发现原来printk就是printf。代码在printk.c #printk asmlinkage int printk( const c...

chuchanshe7949的博客 1052

printk和printf的区别

大部分常用的C库函数在Linux内核中都已经得到了实现。在所有没有实现的函数中,最著名的就数printf()函数了。内核代码虽然无法调用 printf()函数,但它可以调用printk()函数。printk()函数负责把格式化好的字符串拷贝到内核日志缓冲上,这样syslog程序就可 以通过读取该缓冲区来获取内核信息。printk()的用法很像printf(): printk("Hell

tianfengw的专栏 8970

内核态的printk函数-printf

printk简介 在Linux内核中没有printf函数,那么内核是怎么打印调试信息的呢,这里我们用到的是printk函数,在内核中想要向控制台输出或者显示一些内容,必须需要printk函数,这个函数。不同之处在于, printk可以根据日志级别对消息进行分类,一共有 8个消息级别,这 8个消息级别定义在文件 include/linux/kern_levels.h里面,定 义如下: #define KERN_SOH "\001" #define KERN_EMERG KERN_SOH "0" /* 紧急事

weixin_43824344的博客 1362
上一篇: 对Makefile、Kconfig与.config文件的再次理解
下一篇: 将m个相同的球全部放到n个相同的盒子里面有几种放法,盒子不能为空
AstrayLinux
博客等级 码龄15年 55粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值