linux c 宏 linux用什么软件写程序
大家好,今天小编来为大家解答linux c 宏这个问题,linux用什么软件写程序很多人还不知道,现在让我们一起来看看吧!
Linux内核根目录中的配置文件.config中包含了许多宏定义,
一、Linux内核的配置系统由三个部分组成,分别是:
1、Makefile:分布在 Linux内核源代码根目录及各层目录中,定义 Linux内核的编译规则;
2、配置文件(config.in(2.4内核,2.6内核)):给用户提供配置选择的功能;
3、配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于 Ncurses图形界面以及基于 Xwindows图形界面的用户配置界面,各自对应于 Make config、Make menuconfig和 make xconfig)。这些配置工具都是使用脚本语言,如 Tcl/TK、Perl编写的(也包含一些用 C编写的代码)。本文并不是对配置系统本身进行分析,而是介绍如何使用配置系统。所以,除非是配置系统的维护者,一般的内核开发者无须了解它们的原理,只需要知道如何编写 Makefile和配置文件就可以。
二、Make menuconfig过程分析
1、scripts文件夹存放的是跟make menuconfig配置界面的图形绘制相关的文件,我们作为使用者无需关心这个文件夹的内容
2、读取arch/arch/$ARCH/Kconfig以及各子目录下的Kcondig文件,生成配置条目。
$ARCH由linux内核根目录下的makefile文件决定
ARCH?= arm
CROSS_COMPILE?= arm-linux-
Kconfig文件中为配置信息的宏定义,与我们在make menuconfig图形界面看到的信息一致。
例如:
config CPU_S3C2410_DMA
bool
depends on S3C2410_DMA&&(CPU_S3C2410|| CPU_S3C2442)
default y if CPU_S3C2410|| CPU_S3C2442
help
DMA device selection for S3C2410 and compatible CPUs
因此,Kconfig文件很重要的作用就是:定义配置宏、相关依赖关系、帮助信息
3、读取内核根目录下.config文件,生成配置选项:[*]编译进内核 [M]编译为模块 [ ]不编译
arch/arm/configs/文件夹下存放了一些配置模板
我们可以通过cp/arch/arm/configs/xx_defconfig.config来使用这些配置模板
通过图形界面变更配置选项会自动更新到.config文件中
make disclean会删除.config
4、编译过程根据.config生成 Linux内核根目录下的 include/config/auto.conf文件
CONFIG_EEPROM_93CX6=m
CONFIG_DM9000=y
根目录Makefile以及子目录的Makefile根据auto.conf生成编译条件
obj-$(CONFIG_DM9000)+= dm9000.o//obj-m+= dm9000.o
5、编译过程根据.config生成Linux内核根目录下的 include/linux/autoconf.h文件
.config或 auto.conf中定义要编译为 m模块的项,如:
CONFIG_DEBUG_NX_TEST=m
在 autoconf.h中会被定义为:
#define CONFIG_DEBUG_NX_TEST_MODULE 1
.config或auto.conf中定义为编译为 y的选项,如:
CONFIG_DM9000= y
在 autoconf.h中会被定义为:
#define CONFIG_DM9000 1
autoconf.h中是.config或者auto.conf中配置信息的另一种体现形式,它是站在源码的角度,供源码使用的C语言宏定义。
6、总结
我们在使用make menuconfig时,首先会确定架构arch,然后读取arch目录的Kconfig中的配置宏定义,生成编译条目,然后读取Linux内核根目录下的.config选项,将.config中的配置信息显示在图形界面上[*] [M] or []。我们在图形界面中更改配置选项会自动保存到.config文件中。编译过程根据.config随后生成auto.conf文件,它决定了makefile中各个文件的编译类型,静态编译进内核、编译成模块、不编译;同时生成autoconf.h,它以C语言宏定义的形式表达了各个文件是否被编译,源码中会判断某文件是否被编译进行不同的处理。
三、将自定义文件添加进内核配置系统
1、修改文件目录下Kconfig文件
添加:
config HELLO
tristate"just a test hello"
default y
---help---
This is a test
//tristate或 bool表示可选择种类数量3[*][M][ ]、2
//"just a test hello"将作为标题显示在配置的图形界面
2、修改文件目录下makefile文件
obj-$(CONFIG_HELLO)+= hello_drv.o
3、make menuconfig我们会在字符设备驱动的界面看到 ust a test hello并且默认编译进内核
4、make编译内核发现
autoconfig.h自动添加#define CONFIG_HELLO 1
auto.conf自动添加 CONFIG_HELLO=y
Linux内核中的C语言宏:常见用法和最佳实践
深入探索Linux内核中的C语言宏艺术:定义、对比与实践
在Linux内核开发中,C语言宏是一种强大的工具,它们作为预处理指令,通过文本替换提升代码复用和可维护性。让我们一起探索它们的常见用法和最佳实践。
宏与函数的差异
宏在预编译阶段展开,无需函数调用的开销,不返回值,编译时进行错误检查。相反,函数在运行时执行,有返回值,编译器会对其进行优化。尽管如此,宏的优势在于提高效率和简化代码,但可能带来代码膨胀和问题的风险,如类型不安全。
宏的优缺点
优点:提高代码执行速度,减少冗余,灵活应对复杂情况
缺点:可能导致代码难以理解和维护,易引发错误,如宏展开的副作用
Linux内核中,#define常用于定义常量,如整数、字符串和枚举,如常量MAX_NUM和MY_CHAR的定义。
const关键字与宏的比较
尽管C语言提供const关键字定义不可变常量,它具有类型安全、可读性强和维护性好的优点。相比之下,const常量在编译时检查类型,无生存期副作用,且有符号表入口,更加安全。
函数式宏的示例与使用
函数样式宏如ADD(x, y)=(x)+(y),虽然提供速度和灵活性,但调试困难,可读性较差。在内核开发中,需谨慎使用,如在处理最大值/最小值、数组长度、断言和字符串连接等场景。
条件编译的妙用
#ifdef与#ifndef控制基于宏定义的编译块
#if与#elif根据表达式选择代码段,注意控制复杂性
这些条件编译指令允许代码根据平台或配置适应性编译,但过多使用可能影响代码清晰度。
内联函数与宏的对比
内联函数如add(int a, int b),通过编译时展开提高效率,但要留意函数体大小和结构对性能的影响。使用时应权衡效率与可读性。
最佳实践与注意事项
遵循命名规范,清晰标识宏
详尽的注释,解释宏的作用和参数
适度使用,避免过度宏膨胀和可读性降低
为调试目的,可使用#define定义调试宏
总之,理解并明智地运用C语言宏在Linux内核开发中至关重要,既能提升代码效率,又能维护良好的代码结构。在实际操作中,要注重可读性、可维护性和性能优化的平衡。
c语言中的“宏”是指什么
宏是一种预处理指令,它提供了一种机制,可以用来替换源代码中的字符串。
1、条件编译:
C语言中,预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换,预处理过程还会删除程序中的注释和多余的空白符号。
预处理指令是以#开头的代码行,#必须是该行除了空白字符外的第一个字符。#后是指令关键字,在#和指令关键字之间允许存在若干空白字符。
使用宏进行条件编译的用法与使用宏防止多重引用类似。示例如下:
使用条件编译,方便程序员在调试程序的过程中,执行一些在程序发布后并不需要执行的指令。只要在需要调试的代码前加上_DEBUG的定义,就可以在调试程序的过程中输出调试信息。
这样方便查看程序在运行过程中有没有出现错误,定位错误出现的地方。而在程序发布之前,取消_DEBUG的定义就可以不再执行调试代码。
2、宏函数:
函数的调用是需要一定的时间和空间代价的。因为系统在调用函数时,需要保留"现场",即将程序要执行的指令的下一条指令的位置压入栈,然后转入调用函数去执行,调用完函数后再返回主调函数,恢复"现场",返回到栈里保存的的下一条指令的位置继续执行。
所以函数的调用需要额外的时间和空间代价。
而宏函数则不存在上述问题,宏函数在预编译时,同函数定义的代码来替换函数名,将函数代码段嵌入到当前程序,不会产生函数调用。
所以会省去普通函数保留现场恢复现场的时间,但因为要将定义的函数体嵌入到当前程序,所以不可避免的会占用额外的存储空间。
在频繁调用同一个宏的时候,该现象尤其明显。宏函数的示例定义如下:
#define MAX(a,b)((a)<(b)?(b):(a))
宏函数的优点在于避免函数调用,提高程序效率。
同时需要注意的是inline标识符。inline也将函数定义为内联的。但是使用内联函数需要注意的是:函数体必须十分简单,不能含有循环、条件、选择等复杂结构,否则就不能作为内联函数了。
事实上,有时候即便你没有将函数指定为内联函数,编译器也会将一些简单的函数作为内联函数处理,而对于一些复杂的函数,即使声明为内联函数,编译器也不会理会的。
inline函数的瓶颈就在于此,使用inline标识符将函数声明为内联的,但这只是一种提示,到底编译器有没有优化还依赖于编译器的实现,而使用宏函数则完全由代码本身控制。
但在使用宏函数的时候,需要明确的是宏函数只是简单的替换,需要注意括号的使用。
扩展资料:
宏的更多规则特性:
(1)宏名一般用大写。
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义。
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4)宏定义末尾不加分号。
(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
(6)可以用#undef命令终止宏定义的作用域。
(7)宏定义不可以嵌套。
(8)字符串""中永远不包含宏。
(9)宏定义不分配内存,变量定义分配内存。
(10)宏定义不存在类型问题,它的参数也是无类型的。
参考资料:
百度百科--宏定义