## Linux内核中的宏可变参数(GCC的宏可变参数)

Linux内核中的宏可变参数(GCC的宏可变参数)。

#define seclvl_printk(verb, type, fmt, arg...)			\
do {							\
if (verbosity >= verb) {			\
static unsigned long _prior;		\
unsigned long _now = jiffies;		\
if ((_now - _prior) > HZ) {		\
printk(type "%s: %s: " fmt,	\
MY_NAME, __FUNCTION__ ,	\
## arg);		\
_prior = _now;			\
}					\
}						\
} while (0)

## 使用gdb和虚拟机调试内核

＃  编译内核后， 用新内核启动系统失败，报错 “unable to mount fs ….” 之类.

＃ 对于grub2，我增加了一个自定义的grub开机启动项用来调试内核，如下：

#!/bin/sh
exec tail -n +3 $0 # This file provides an easy way to add custom menu entries. Simply type the # menu entries you want to add after this comment. Be careful not to change # the 'exec tail' line above. echo "Add Debugging entry" cat << EOF menuentry "Debian debug 3.7.4"{ set root=(hd0,1) linux /boot/vmlinuz-3.7.4 root=/dev/vda1 ro quiet kgdboc=ttyS0,115200 kgdbwait initrd /boot/initrd.img-3.7.4 } EOF ///////// the above grub configuration file resides in /etc/grub.d/ # client在虚拟机里启动后在内核调试断点处停下。这时在host机用gdb调试. # gdb vmlinux set remotebaud 115200 target remote /dev/pts/0 此时gdb输入continue命令让客户机的系统继续运行。如果想断下正在运行的client内核，在client机中使用magic SysR: echo "g" > /proc/sysrq-trigger ## Linux内核Makefiles教程(二) 接第一篇 3.3.可加载模块目标 obj-m (Loadable module goals – obj-m) obj-m指定将被构建为可加载内核模块的对象文件(object file)。 一个模块可以从一个源文件构建或者从多个源文件构建。如果模块仅仅从一个源文件构建，kbuild makefile仅仅把对象文件加到obj-m。如下： #drivers/isdn/i4l/Makefile obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

ext2-y                       := balloc.o bitmap.o

ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o 在上例中，如果$(CONFIG_EXT2_FS_XATTR)求值为y，则xattr.o是复合对象文件ext2.o的组成部分。

3.4. 导出符号的对象文件

3.5. 库文件目标(Library file goals – lib-y)

#arch/i386/lib/Makefile

lib-y    := checksum.o delay.o

lib-y的使用通常受限于 lib/ 和 arch/*/lib。

3.6. 深入遍历子目录夹

#fs/Makefile

obj-$(CONFIG_EXT2_FS) += ext2/ 如果CONFIG_EXT2_FS被求值为y（内建）或者m(模块)，那么obj-*变量就会告诉kbuild需要进入ext2/子目录继续编译。 Kbuild仅仅使用这个信息来通知是否进入某个子目录，而进入后的子目录下面是用内建方式编译还是编译成模块则是由子目录下面的Makefile文件指定。最好像上例那个使用CONFIG_*变量。这样的好处是，如果CONFIG_*变量的求值既不是y也不是m，那么kbuild就完全可以忽略掉某子目录了。 3.7. 编译选项/标识 EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS 所有的EXTRA_VARIABLES仅仅作用于它们被赋值的kbuild makefile，应用于所有该makefile文件中执行的命令。$(EXTRA_CFLAGS)指定了编译C文件的C编译器的编译选项。

Example:

# drivers/sound/emu10k1/Makefile

EXTRA_CFLAGS += -I$(obj) ifdef DEBUG EXTRA_CFLAGS += -DEMU10K1_DEBUG endif 变量$( EXTRA_CFLAGS)是必要的，因为最上级的Makefile定义的$(CFLAGS)作用于整个linux内核代码树。 而$(EXTRA_AFLAGS)的作用域则是每个文件夹下面单独的Makefile。

#arch/x86_64/kernel/Makefile

$(EXTRA_LDFLAGS) 用于当前Makefile文件中的$(LD)。

$(EXTRA_ARFLAGS) 则用于当前Makefile文件中的$(AR)。

Example:

#arch/m68k/fpsp040/Makefile

EXTRA_LDFLAGS := -x

# Linux内核Makefiles

## 1. 概述

Linux内核的Makefile包括五个部分。

 Makefile 最上层Makefile .config 内核配置文件。 arch/$(ARCH)/Makefile CPU架构相关Makefile scripts/Makefile.* 对于所有Kbuild Makefile的公共方法。. kbuild Makefiles 有将近500个kbuild Makefiles。 最上层Makefile读取.config文件。.config文件是由内核配置过程生成的。 最上级的Makefile负责生成linux的内核映象文件vmlinux和其它所有的模块。最上级Makefile递归地进入内核代码树的各级子目录分别执行子目录下的Makefile。究竟要进入哪些子目录是由内核配置阶段决定的，即配置在.cncfig文件中。最上级Makefile提定了一个路径为arch/$(ARCH)/Makefile的子目录Makefile。这个Makefile中定义了与处理器架构紧密相关的信息。

## 2. 谁使用内核Makefile

KBuild的开发者(KBuild Developers)

KBuild的开发者就是维护内核构建系统的开发者，他们需要知道内核Makefile的各个方面。

——

## 3. kbuild文件

3.1节 "目标定义"是一个快速简介，更详细的介绍会在下面的章节陆续介绍并有真实的例子。

### 3.1. 目标定义(Goal Definitions)

obj-y += foo.o

obj-$(CONFIG_FOO) += foo.o$(CONFIG_FOO)是一个makefile变量，在makefile执行时被替换为y（如果内建到内核）或者m（如果构建成模块）。如果CONFIG_FOO既不是y也不是m，那个这一行代码会被忽略，指定的文件不会被编译也不会被链接。

### 3.2 内建的对象目标(object goals) obj-y

Kbuild Makefile通过obj-y列表为linux内核映象vmlinux指定目标文件(.o)。究竟是哪些目标文件则取决于内核配置。Kbuild系统会编译所有obj-y列表中的文件。然后Kbuild系统会调用$(LD) -r把所有的这系文件合并到一个built-in.o文件。跟住呢，built-in.o被最上级Makefile链接到linux内核映象文件vmlinux。 在obj-y列表中指定的文件顺序是很重要的。列表中的重复项也是被充许的。首先出现的会被首先链接到built-in.o，后面的重复项会被忽略。 链接的顺序当然也是有重要意义的。因为一些函数调用，如module_init()，_initcall会在系统启动阶段按照他们被链接的先后顺序被调用。所以改变链接的顺序当然会造成意义重大的影响。比如：会改变SCSI控制器被内核发现的先后顺序，因此磁盘的编号则会改变。 #drivers/isdn/i4l/Makefile # Makefile for the kernel ISDN subsystem and device drivers. # Each configuration option enables a list of files. obj-$(CONFIG_ISDN)             += isdn.o

obj-\$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

(第一篇完)   第二篇

## 如何正确地提交内核补丁包

Greg Kroah-Hartman(又Greg KH)在执行一个了不起的作务：减少内核开发者，尤其是维护者的暴躁情绪。他在日本横滨举行的全球Linux大会上的讲演呼吁公众理解内核维护者的工作，内核贡献者的什么样的行为会导致内核维护者变得暴戾。但是，如果内核贡献者们能够遵守一些约束，他代表他自己做了许多承诺。

Greg Kroah Hartman把Linux内核称之为"有史以来最宏大的软件开发项目"，而且它的开发速度也是“亘古未有”。从3.0到3.4，有373个公司的2833位开发者参于了Linux内核的开发。这一年，(2011年的5月到，2012年的5月)，Linux内核在每个小时会有5.79处变动。而且这个开发速度仍然要加速，如果你看看3.4的开发过程，每小时共有7.21处变动。这里所说的变动仅仅指能够被合并到主干的补丁包，而那些被拒绝的补丁包没有被统计进来。

#### 坏的补丁包

Greg KH举例说明了一些他收到的坏的补丁包。其中一个补丁包被命名为：patch 48/48(一个有48个补丁集的最后一个)，但是其它的47个都没有。他还收到一堆补丁但没有写清楚先后顺序。如此，他要么猜测一个顺序，这毫无疑问会失败。另一个替代方案就是安全不管这个补丁了。另外还收到过有10个补丁的补丁集，但是2号补丁确丢失了。

Greg KH还着重说了编译不能通过的问题。他说，有些内核内核贡献者把不能通过编译的补丁包也发过来。或者有些补丁包集3/6失败了，在6/6修复了。我甚于收到过补丁包在5/8失败，但是作者附带了一个说明说作者在未来某个时候会发来改正方案。另外还有补丁包很明显没有正确的内核文档部分，因为在构建文档的时候会失败，很明显补丁包的创建者根本就没有运行过内核文档抽取工具。(不想译了，太多了…呜~~累死了.)

One of the patches he got "had nothing to do with me". It was an x86 core kernel patch, which is not an area of the kernel he has ever dealt with. But the patch was sent only to him. "I get odd patches" a lot, he said.

The last patch he mentioned was 450K in size, with 4500 lines added. Somebody suggested that it be broken up, but in the meantime several maintainers actually reviewed it, so the submitter didn't really learn from that mistake.

All of this occurred during a "calm two weeks", he said. These are examples of what maintainers deal with on a weekly basis and explains why they can be grumpy. That said, he did note that this is the "best job I've ever had", but that's not to say it couldn't be improved.

If someone sends him a patch and he accepts it, that means he may have to maintain it and fix bugs in it down the road. So it's in his self interest to ignore the patch, which is an interesting dynamic, he said. The way around that is to "give me no excuse to reject your patch"; it is as simple as that, really.

#### Rules

Kroah-Hartman then laid out the rules that contributors need to follow in order to avoid the kinds of problems he described. Use checkpatch.pl, he said, because he will run it on your patch and it is a waste of his time to have to forward the results back when it fails. Send the patch to the right people and there is even a script available (get_maintainer.pl) to list the proper people and mailing lists where a patch should be sent.

Send the patch with a proper subject that is "short, sweet, and descriptive" because it is going to be in the kernel changelog. It should not be something like "fix bugs in driver 1/10". In addition, the changelog comment should clearly say what the patch does, but also why it is needed.

Make small changes in patches. You don't replace the scheduler in one patch, he said, you do it over five years. Small patches make it easier for reviewers and easier for maintainers to accept. In a ten-patch series, he might accept the first three, which means that the submitter just needs to continue working on the last seven. The best thing to do is to make the patch "obviously correct", which makes it easy for a maintainer to accept it.

Echoing the problems he listed earlier, he said that patches should say what tree they are based on. In addition, the order of the patches is important, as is not breaking the build. The latter "seems like it would be obvious" but he has seen too many patches that fail that test. To the extent that you can, make sure that the patch works. It is fine to submit patches for hardware that you don't have access to, but you should test on any hardware that you do have.

Review comments should not be ignored, he said. It is simply common courtesy if he takes time to review the code that those comments should be acted upon or responded to. It's fine to disagree with review comments, but submitters need to say why they disagree. If a patch gets resent, it should be accompanied with a reason for doing so. When reviewer's comments are ignored, they are unlikely to review code the next time.

#### Maintainer's role

When you follow those rules there are certain things you can expect from him, Kroah-Hartman said, and that you should expect from the other maintainers as well. That statement may make other maintainers mad, he joked, but it is reasonable to expect certain things. For his part, he will review patches within one or two weeks. Other maintainers do an even better job than that, he said, specifically pointing to David Miller as one who often reviews code within 48 hours of its submission. If you don't get a response to a patch within a week, it is fine to ask him what the status is.

He can't promise that he will always give constructive criticism, but he will always give "semi-constructive criticism". Sometimes he is tired or grumpy, so he can't quite get to the full "constructive" level. He will also keep submitters informed of the status of their patch. He has scripts that will help him do so, and let the submitter know when the patch gets merged into his tree or accepted into the mainline. That is unlike some other maintainers, he said, where he has submitted patches that just drop into a "big black hole" before eventually popping up in the mainline three months later.

He ended by putting up a quote from Torvalds ("Publicly making fun of people is half the fun of open source programming. …") that was made as a comment on one of Kroah-Hartman's Google+ postings. The post was a rant about a driver that had been submitted, which even contained comments suggesting that it should not be submitted upstream. He felt bad about publicly posting that at first, but Torvalds's comment made him rethink that.

Because kernel development is done in the open, we are taking "personal pride in the work we do". As the code comment indicated, the driver developer didn't think it should be submitted because they realized the code was not in the proper shape to do so. It is that pride in the work that "makes Linux the best engineering project ever", he said. Sometimes public mocking is part of the process and can actually help instill that pride more widely.

## Linux内核维护者的职责

(什么，你还没有订阅过 lwn.net，为什么不订阅呢？真是为你感到羞愧啊！现在还不快去订阅？) 译者注：订阅lwn.net是要支付付用的。原作者在文章中给lwn.net做广告呵呵。

• 我会在一到两个星期内复审你的补丁包(参见下文)
• 我会对你的补丁包提出准建设性的批判意见。
• 如果你提交的补丁包被拒绝的话，我会给你被拒的理由。如果补丁包被接收，我会告诉你补丁包会被合并到哪个分支，你可以从哪里看到它以及什么时候你可以看到它最终被合并到linus的分支中。