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

Linux内核中的宏可变参数(GCC的宏可变参数)。
写内核模块的时候为了调试方便,经常需要wrap一下printk函数。下面的宏定义非常有实用价值。
注意两个井号~~
记到博客里~~

#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 ….” 之类.

需要用 update-initramfs 生成initram。

# 对于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

在这个例子中,$(CONFIG_ISDN_PPP_BSDCOMP)被求值为m.

If a kernel module is built from several source files, you specify that you want to build a module in the same way as above.

如果一个内核模块需要从多个源文件构建,你也是按照刚才提到的那一行指定。不过,除此之外,还要额外地指定,你的内核模块需要哪些对象文件。所以还需要设置<模块名>-objs变量。如下:

       #drivers/isdn/i4l/Makefile

        obj-$(CONFIG_ISDN) += isdn.o

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

在这个例子中,模块名是 isdn 。Kbuild将编译isdn-objs列出的所有对象文件,然后运行$(LD) –r把这些对象文件链接成一个文件isdn.o。

Kbuild用-objs后缀或者-y后缀识别构成复合对象文件(composite objects)的对象文件。这样,Makefile就可以使用CONFIG_* 符号来确定一个对象文件是不是一个复合对象文件的一部分。如下:

       #fs/ext2/Makefile

        obj-$(CONFIG_EXT2_FS)        += ext2.o

        ext2-y                       := balloc.o bitmap.o

        ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

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

当然,如果你要把对象文件编译进入内核映象文件。也可以应用上述语法。比如,如果CONFIG_EXT2_FS=y,kbuild就会构建一个ext2.o文件,如你所想,再把这个文件链接到build-in.o。

3.4. 导出符号的对象文件

并不需要在Makefile中为模块使用特殊的标记来导出符号。

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

在obj-*中指定的对象文件列表或者被用来构建内核模块,或者被内建到内核映象文件之中。Makefile还能指定创建库文件的对象文件。所有在lib-y中指定的对象文件会被用来在对应文件夹下创建一个库文件。注意已经在obj-y中列出过的对象文件,如果再在lib-y中列出,则不会被用来创建库文件,因为这些对象文件将是全局可见的。为了一致性,lib-m中列出的对象文件会被包含到lib.a。

注意,同一个kbuild makefile会同时指定被内建到内核映象中的对象文件,也会指定用来创建库文件的对象文件。因此,在同一个文件夹下面有可能同时存在built-in.o和lib.a文件。

       #arch/i386/lib/Makefile

        lib-y    := checksum.o delay.o

上例中,会基于checksum.o和delay.o创建一个库文件lib.a。为了让kbuild意识到该目录下有lib.a库文件被创建,这个目录需要被列入到libs-y。本教程将在6.3节”列出需要遍历的路径”中详述。

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

3.6. 深入遍历子目录夹

每个Makefile文件只负则在当前文件夹下面构建对象。在子目录下面的构建则由子目录下面的对象Makefile负责。不过你需要使用使用obj-y或者obj-m告诉kbuild系统将进入哪些子目录。比如话:当前目录是fs/,ext2/是当前目录下面的一个子目录,为了告诉kbuild进入ext2/目录,使用以下的语句:

        #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_AFLAGS := -traditional

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

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

Example:

        #arch/m68k/fpsp040/Makefile

        EXTRA_LDFLAGS := -x

未完待续

copyright ykyi.net

Linux内核Makefiles教程(一)

 

Linux内核Makefiles

本教程描述了了Linux内核的Makefile是如何工作的。

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中定义了与处理器架构紧密相关的信息。

每一个子目录下面都有一个kbuild Makefile,这里都定义了一些makefile命令和变量可以被更下级的Makefile继承。Kbuild Makefile使用来自.config配置的信息生成各种文件列表用来构建内建的或者模块化的目标文件。Scripts/Makefile.*包括了很多被其它Makefile使用定义和规则。

2. 谁使用内核Makefile

内核Makefile的使用者可以大致分为四种。

用户(Userse)

这类使用者仅仅敲入一些命令,如“make menuconfig”或者“make”。他们很少会阅读甚修改内核Makefile和源代码文件。

一般开发者(Normal Developers)

一般开发者一般编写一些设备驱动程序,文件系统,网络协议。他们需要维护他们编写的代码涉及的子系统的kbuild Makefiles。为了工作地更有效率,他们甚至还需要对整个内核的Makefile有全局的把握,包括对kbuild的公共接口的详尽了解。

处理器架构开发者(Arch Developers)

这部分开发者关心与某个处理器架构紧密相关的代码部分,比如PC上最广泛使用的x86,以及IA64,还有ARM,Sparc,PowerPC,Alpha,s390,MIPS。Linux支持几百种处理器架构。从内核2.6.24开始,i386和x86_64合并为x86。

KBuild的开发者(KBuild Developers)

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

——

本篇教程主要面向第二类开发者和第三类开发者。即一般开发者和处理器体系架构开发者。

3. kbuild文件

大多数内核Makefile文件是kbuild Makefile文件,它们使用不同于一般make文件的kbuild语法。下面会介绍kbuild makefile的语法。Kbuild文件一般被命名为Mafile,但是也可以使用Kbuild名字。如果已经存在一个Makefile文件了,那么就只好用Kbuild名字了。

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

3.1. 目标定义(Goal Definitions)

目标定义是kbuild Makefile的最重要的部分。它们定义了哪些文件会被构建,并指定一些特殊的选项组合以及将递归进入到哪些子目录。

最最简单的makefile只有一行代码,如:

       obj-y += foo.o

这行代码告诉kbuild系统当前目录下有一个目标要构建,它的名字是foo.o。foo.o将从foo.c或者foo.S生成。

 

如果foo.o需要被构建成一个内核模块,那么应该使用obj-m。因此一般使用下面的模式:

       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

(第一篇完)   第二篇

copyright ykyi.net

 

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

原文:https://lwn.net/Articles/500443/

翻译:ykyi.net 

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处变动。这里所说的变动仅仅指能够被合并到主干的补丁包,而那些被拒绝的补丁包没有被统计进来。

补丁包修改了哪些文件,内核开发者就把补丁包发给负责这些文件的维护者。所以的内核维护者,现在大概有700人。他们把改变应用到130个子系统的维护者那里。再从子系统的维护者到Linus的Linux内核代码分支。最后并必Linux内核的主干。如果提交的补丁包一路通过的话。

因此,来看看为什么一些补丁包不会被接受呢?Greg Kroah Hartman以刚过去的两个星期收到的补丁包为例,这两个星期刚好处于3.5版本的Merge Window时间。Merge Window是一个他确不应该接收到许多补丁包的时间段。他应该在Merge Window开始前收到所以有可能会在Merge Window其间被发往Linux Torvalds的补丁包。不过,他说他在这两个星期的时间里收到487个补丁包。其中的大多数都有很多问题,有些补丁包来自那些本应该对内核有更好理解的内核开发者们。

坏的补丁包

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

另外有一个通过邮件发送来的补丁包被声明“机密”。Greg KH说他经常收到此类方式的补丁。对于此类补丁,你无能为力。因为Linux是在开放的生态中开发的,你不能够给邮件列表发送一个机密邮件偷偷就合并一个补丁。很明显,这种方式发来的补丁是因为在处理邮件阶段的模板造成的,但是'机密'必须被去掉。

还有不良排版的补丁包。比如所有的Tab符都被转成了空格,Microsoft Exchange常常这么做。如果对于你,开发环境是个问题的话,那可以像IBM,Microsoft或者还有其它公司那样,在角落里再放一台Linux机器给开发者用来发送邮件。有时候diff的输出的行前空格都被剥去了,或者diff的输出并不是unified格式(见另一篇博文,讲述如何用diff生成linux内核补丁包)。虽然久经考验的Linux开发者们可以熟练的编辑原始diff输出格式,但是diff的原始输出本身是件很令人恐怖的事情,他们本不应该被如此对待编辑它们。

有些补丁包是在错误的目录下被创建的,比如在一个驱动器目录下。有个补丁包在/usr/src/linux-2.6.32目录下被创建,但是这个补丁包里面有好些错误,包括源代码树的年龄,而且它隐含假设它是在root上构建。在root上构建是相当之危险,如果linux的构建过程中出现一个bug,就有可以把整个文件系统都删除。没有一个内核核心开发者留意到了这个情况,因为他们没有使用root。有建议说把这种bug留下来当成一种威慑力(原作者开玩笑),自然不会被采纳,不过那么极端的危险情况是真的有可能发生啊。

还有离谱的,有些补丁包是针对一个本来与这个补丁包毫无关系的代码树。Greg KH说他曾经收到一个补丁包针对SCSI代码树,实在想不通这个与SCSI毫无关系的补丁关怎么会针对SCSI代码树创建。

然后还有代码风格的问题。有些补丁包没有使用Linux内核的代码风格。提交补丁包的开发者也知晓这个问题,但是他们似乎在说“我不管,让我的代码通过吧!”Greg KH说,现有一些工具可以帮助定位到有这些问题的代码并修复它们。所以,没有任何借口发送不符合代码风格的补丁包。

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内核维护者的职责

原文: http://www.linuxfoundation.org/news-media/blogs/browse/2012/06/role-linux-kernel-maintainer

翻译: ykyi.net

几个星期前在日本举行的Linux大会(LinuxCon)上,我做了一个演讲,题目是"Linux内核维护者,他们在做什么,如何能够帮到他们"。

这个演讲的视频可以通过这个链接看到。如果你想要幻灯片,和我的讲演稿,可以在这个地址获得。

如果你之前觉得为什么一个开源工程的维护者对发给他/她的东西总是如此古怪乖戾,那我强烈推荐你去看看我为这个演讲写的笔记,或者幻灯片,里面包含了所有的笔记。

另外,如果你想要知道如何才能令你的内核补丁包得到通过,请先看看上文提到的幻灯片,我不想过多重复了。

嗯,有一个例外!

首先,看起来我的这个演讲引发了一连串热烈的讨论。最最开始是因为Jake Edge在lwn.net上一篇精彩的总结(这篇文章我有翻译前半部分,点击这里),引来了大量评论各有大量围观群众。这些人中的绝大部分应该没有看过上面提到的幻灯片,也应该看到我的演讲的视频,无论如何还是激起了大家的兴趣。普罗大众总是会因为某些人在大吵的时候兴奋地在一旁围观。

接着,Jon Corbet撰文加入了争论。他做了一个非常非常好的总结:开源工程的维护者们总是被海量的低质量提交沦陷,总是要日复一日地不停地回复已经被回答过好多次的同样问题。人们看起来从不去阅读文档,而通常在文档里就能找到答案。再一次,强烈建议你看看上文提到的幻灯片或者笔记或者视频。刚才提到的两篇文章也值得一读,包括下面的精彩评论。

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

后来, Linux内核峰会的召集期限已过,收到的很多提议都是关于内核维护者的。他们的工作量,如何解决已经出现的棘手问题。如果你有兴趣的话,可以在 这里 了解到到底我们在为什么抓狂。 

对于我演讲里所讲述过的内容,在这里我还想重复的是:身为一个内核子系统的维护者,对于那些给我发送关于我负责的内核部分的内核补丁包的开发者,我如下承诺:

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

就这样。对于提交者,我希望看到格式良好,文档丰富,可以整洁地应用到代码树的补丁包,而且做了真正有用的事情。这样的话,你我都会很开心,是吗?

对意下一到两周的回复时间:

当然了, 如果我生病了,或者我正在这个星球上某个地方旅行。我的回复就会适当延迟。你绝对可以随时发邮件给我询问你的patch的状态。我很乐意回复这些邮件。我宁可一一处理好所有这些询问邮件,而不是让等待了几周的开发者发疯。

另外,要注意一下合并窗口(Merge Window)的问题。在整个Merge Window阶段,我不能接受任何在我的分支Release上还没有修正所有已知bug的补丁包。所以这意味着,通常在Linus的Release前一周开始,一共三周的时间内,我不会处理你提交的补丁包。在这段时间内,上百份补丁包会堆积起来,所以请给我一些时间让我从补丁海里面脱身出来。一般到-rc3的时候,我就赶上了,但如果没有呢,人可以写邮件给我咨询。

copyright ykyi.net

 

使用Cscope阅读大型工程Linux内核的源代码教程

Cscope是一个非常有用的工具,可以用来方便地阅读很大型工程的源代码。较之使用传统的Unix工具grep,使用Cscope可以省下你一大笔时间,大大提高阅读代码的效率。

 

通过本教程,我会教给你如何使用Cscope阅读Linux内核的源代码。毫无疑问,你可以举一反三,用同样的方法阅读其它的大型工程的源代码,不仅仅是C语言写的工程,也可以是Java或者C++或者C#开发的工程。

 

STEP 1 获得源代码:

去到Linux内核的网站http://www.kernel.org下载随便一个版本的Linux内核源代码压缩包。然后解压缩,把源代码释放到某个目录。本文假设你把源代码释放到 /home/code/linux-2.6.26。

 

STEP 2 选择一个目录存放Cscope所需要的数据库文件。

本文假设选择用/home/cscope目录存放cscope的数据库文件和其它一些相关文件。

 

STEP 3 生成文件 cscope.files

在最简单的情况下,工程目录下的所有源代码都是我要关心的,于是可以跳过下面所述,简单地在工程的根目录下运行'cscope -R'命令,这样Cscope就会在工程目录下所有源代码中处理相关工作。

但是你关心的代码并必工程目录下所有的代码,你还需要排除很多目录下的大量代码该如何做呢?在这种情况下,你需要生成一个文件cscope.files,这个文件包含 了所有cscope将要扫描的文件的文件名,每个名字占一行。最好使用绝对路径,这样你就可以在其它目录下,而不是现在创建cscope.files文件的目录下使用这个刚创建的数据库。下面的代码将完成这个任务(假设我要所有的java文件):

$ cd /   

$ find /my/project/dir -name "*.java" > /my/cscope/dir/cscope.files

对于Linux内核来讲,情况还要稍微复杂一点。因为我们还要排除好些文件夹,这些文件夹有存放文档的文件夹,存放脚本的文件夹,与处理器架构相关的汇编代码的目录夹,与处理器架构相关的C代码除了x86(大多数人已经仅仅对x86感兴趣),另外还会排除所有的驱动文件目录夹,因为驱动占了内核很大一部分,但驱动代码通常不是我们要关心的。如果不排除这些目录的话,cscope当然也能工作,但是却给我们增加了麻烦,因为大大增加了重复的定义出现的概率。下面看我怎么做:

 

    $ LNX=/home/linux-2.6.26

    $ cd /    

    find  LNX                                                                \

    -path "LNX/arch/*" ! -path "LNX/arch/i386*" -prune -o               \

    -path "LNX/include/asm-*" ! -path "LNX/include/asm-i386*" -prune -o \

    -path "$LNX/tmp*" -prune -o                                           \

    -path "$LNX/Documentation*" -prune -o                                 \

    -path "$LNX/scripts*" -prune -o                                       \

    -path "$LNX/drivers*" -prune -o                                       \

    -name "*.[chxsS]" -print >/home/jru/cscope/cscope.files

如果对Unix常用工具find熟悉的话,看懂上面的这个复杂命令应该不是问题。但是我想有必要稍微说明一下。

比如 -path “LNX/include/asm-*” ! -path “LNX/include/asm-i386*” -prune -o \  表示排除 $LNX/include/asm-目录下的所有但是又不排该目录下的 asm-i386 目录。

-prune是排除的意思。那 -o 又是什么呢? -o表示逻辑或,如果逻辑或前面的表达式为真(即文件满足被排除的条件),根据or表达式的”短路语法“,-o后面的命令就不会再执行。如果文件名不满足-o前面的排除条件就会再应用-o后面的条件。我们可以看来后面用好几个 -o 把好几个排除条件连在一起。如果你不需要排除其它某些文件,就可以把相应的行去掉。题外话,古老的Unix工具链虽然看上去晦涩难懂,但是一但掌握却是可以受益终生。你想想那么多常用的Unix工具自从70年代发明后就一直广泛使用。已经快40年了!仍然在开源世界广泛使用,想想微软的技术,刚开完发布的新闻发布会,马上又宣布将废除使用了。这方面的思想可以参见《unix编程艺术》一书相关部分的阐述。

STEP 4 下面生成cscope的数据库文件。

$ cd /home/cscope    #上一步生成的 cscope.files放在这个目录夹下面.

$ cscope -b -q -k

-b 选项告诉cscope仅仅创建数据库文件,不要在之后启动cscope的介面。 -q选项使得生成数据库的时间增加,但是明显降低之后使用数据库文件时的搜索速度。对于大型工程建议使用这个选项,对于小工程则可不必。-k选项使得cscope不会去/usr/include中处理你的源代码中#include的文件。

STEP 5 

到此,就可以执行cscope了。如:

$ cscope -d

注意 -d 选项。加上这个选项则cscope不会在启动时重新检查所有有没有文件更新,有更新还会重建数据库,即使没有更新对于大型工程也要花费一些时间。如果有文件更改,你又想反映这个变化,那就不能加上-d选项。如果有新的文件加入,则需要从STEP 3重新开始,或者手动把增加的文件加入 escope.files,每个文件一行!如果你喜欢cscope,那么再参看man page,多多学习吧!

 

总结,Linux下的很多开发工具和成熟的GUI丰富的商业开发环境比较起来真的非常不方便呀。打字辛苦,转载请注明出处 ykyi.net  !谢谢~

 

KVM你问我答 FAQ (四)

KVMXen有什么区别?

Xen是一个外部虚拟机管理程序(External hypervisor),它承担了管理物理机器的任务并把物理机器的各种资源分配给客户机。与Xen不同,KVM本身是Linux内核的一部分,它使用Linux自己的进程调度和内存管理。这就天然决定了KVM易于使用并于体积会很小。仅管体积小,但KVM的功能确不少。比如,KVM可以把客户机从内存中兑换到物理磁盘上,如同swap普通进程一样释放RAMKVM目前只在提供支持硬件虚拟化的x86机器上运行(如vt/svm指令集)。从这这方面讲,Xen通过修改客户机操作系统,充许虚拟机运行在没有硬件虚拟化技术的x86平台上运行。这种虚拟化技术称之为准虚拟化paravirtualization,参见另一贴:Linux的虚拟化技术KVMCPU级别不支持paravirtualization,但为了指高I/O性能,会对设备驱动程序支持准虚拟化。

KVMVmware有什么区别呢?

VMware是一个商用专用虚拟化产品,KVM是在GPL许可证下发布的自由软件。

KVMQEMU有什么区别?

QEMU是模拟器。参见Linux的虚拟化技术 KVM & QEMU 。

KVMwindows下的移移植版本吗?

没有官方的移植。Kazushi Takahashi发起了一个项目,把KVM移植到windows操作系统,这个项目名为WinKVM,这是他的官方网站WinKVM

可参见另一篇文章 http://ykyi.net/2012/06/595/

需要怎样的Linux内核版本才能运行KVM呢?

这取决于你要运行哪个版本的KVM。最近发布的KVM应该可以在任何2.6.17以后的kernel版本下运行。但很旧版本的KVM只能在一些旧的内核下运行。

需要多少内存运行KVM呢?

最小应该1GB。嗯,你应该有足够多的内存运行你将要运行的客户机,另外当然还需要内存运行host机。

是否支持对客户机动态分配内存?

这个问题有点大!
1. KVM在客户机尝试申请内存时分配内存给它们。一但内存分配结束之后,KVM则认为内存分给某客户机了。有一些操作系统,比如Microsoft Windows会在启动阶段把所有的内存都清零。这些操作系统会立即使有或管理所有的内存。
2. 而另一些操作系统,实际上目前只有Linux,它们有一个称为balloon driver的东东,如果host分配了一些内存但客户机将来不再使用了,它就会让host把它们释放掉。Ballooning是通过balloon monitor commandhost机中被控制的。
3. 有一些host机,(目前只有RHEL5.4/CentOS 5.4)有一种特性称为KSM(Kernel Sharedpage Merging)。这种特性可以把完全相面的内存页面合并,这需要host机的支持,另外KVM的版本要足够新。而有一些操作系统,如windows,会把释放的内存清零,这些页面自然就会合并了(such pages are trivially collapsed不知道有没有译对)。Ksmctl命令用来开启KSM。另外一种方法是,Fedora 12中的ksmtuned服务可以根据可用的空闲内存动态的调整KSM的合并策略是否积极还是保守。

我可以在KVM虚拟机中安装哪些操作系统呢?

支持很多种操作系统,你可以参看Guest Support Status 页面。请注意已经有一些Linux发行版在Intel处理器上会在启动阶段死机,解决办法是在grub里禁用启动画面。

KVM支持虚拟机实时迁移(Live Migration)吗?

支持!参看Migration。KVM支持从AMD的主机往INTEL主机实时迁移(Live Migration)吗?
支持!对于32位不支持NX或者XD的主机,可能会有一些问题。但是对于64位的客户机,应该没有一点问题的。在32位主机和64位主机之间实时迁移(Live Migration)32位虚拟机也应该没有问题。如果其中一台主机不支持NX,你要考虑在支持NX的那台机启动虚拟机之前禁用NX。你可以在启动客户机时加入-cpu qemu64, -nx参数。

可以在64位的主机上运行32位的客户机吗?可以用PAE吗?

KVM支持在64位主机上运行32位的客户机,不管主机是否使用PAE,客户机都可以选择使用PAE或者不使用PAEKVM不支持在32位的主机上运行64位的虚拟客户机。

可以在基于KVM的虚拟机上使用USB设备吗?

当然可以,请参照QEMU的做法,是一样的。

我可以让KVM使用更高的屏幕分辨率吗?

在启动VM之前使和 -vga std 参数可以充许你设置更多的分辨率和屏幕尺寸。
如果不能调到你想要的分辨率,你可以尝试安装一个补丁包,请参考http://article.gmane.org/gmane.comp.emulators.kvm.devel/13557 。
当你使用windows作为客户机操作系统的时候,你可以使用VBEMP x86项目中开发的驱动,这个项目是基于ReactOS开源项目的,请注意不要违反GPL许可证。

KVM支持对称多处理器(SMP)host机吗?

支持!

KVM支持对称多处理器(SMP)的客户机吗?

Yes. Up to 16 CPUs can be specified using the -smp option.
是的!目前一共最多16cpu,要使用-smp选项。

KVM已经被注册为商标了吗?

没有!

转帖请注明出处: http://ykyi.net/2012/06/kvm%E4%BD%A0%E9%97%AE%E6%88%91%E7%AD%94-faq-%E5%9B%9B/

—– KVM FAQ 全剧终 —–

 

KVM你问我答 FAQ (三)

我在使用QEMU,如何知道我有没有启用KVM的硬件加速功能?

如果你怀疑你没有启用KVM提供的硬件加速功能。你可以按照下面的步骤做检查。首先,看看你有没有得到下面的提示信息:

qemu-system-x86_64 -hda myvm.qcow2
open /dev/kvm: No such file or directory
Could not initialize KVM, will disable KVM support

如果是这种情况,请再检查:
1. kvm模块被正确载入了吗? lsmod | grep kvm.
2. 查看 dmesg 的输出,保证没有这个提示信息: “KVM, disabled by BIOS”.
3. 请确保/dev/kvm 确实存在,而且你有权限使用它。

其它诊断方式:
1. 如果你能使用 QEMU monitor ( ctrl-alt-2, 再 ctrl-alt-1 回到 VM 的显示屏 ),敲入 info kvm 命令。如果正常的话,应该有“KVM support: enabled”这条信息输出。
2. 在host机上敲 lsmod | grep kvm 命令,看看输出的最右栏。如果kvm在正常运行的话,这个数字不能是0。这行的数字与架构相关的模块(一般指的是kvm_intel,或kvm_amd)有联系,它显示了有多少个VM正在使用这个模块。举例说明,如果你有两个虚拟机正在使用KVM模块,host机的CPU使用的是vt技术,那么就会得到:

# lsmod | grep kvm
kvm_intel              44896  2
kvm                   159656  1 kvm_intel

 

使用VNC显示终端时出现“rect too big”是怎么回事

当连接VNC终端的时候,出现“rect too big”提示信息,这时VNC的会话也结束了。

这是因为当前VNC协议的一个缺陷,在处理即时象素格式变化时出现,可参看 这个贴子。如果你在使用TigerVNC,通过禁用即时象素编码选项,vncviewer的命令行选项选定为-AutoSelect=0,你就可以避免这个问题。你还可以查阅vncviewer的man帮助,根据连接速度禁用自动选择编码方式。


 

如果我的客户机是从远程访问的你该如何设置我的网络呢?以及:我的客户机网络出问题了我该怎么办?

KVM使用QEMU作为设备的模拟器。请参看QEMU的网络相关wiki (QEMU network wiki page)。
你应该会对Root Networking Mode和网络桥接感兴趣。客户机端的网络锁定有可能会因为tun/tap桥接host机端配置的出错的MAC地址时发生。参看RHEL bug #571991。

 


 

我的VM客户机的时间总出错,怎么办?

这常常发生在使用网络系统的时候,比如透过NFS或Samba。 不管是系统时钟还是RTC,保证稳定可靠的时机非常重要。Tell-tale signs of related trouble in VMs (apparently qemu/KVM/VMWare etc. are all affected) are e.g. "make[2]: Warning: File `XXXXX/cmakelists_rebuilder.stamp' has modification time 0.37 s in the future" "Clock skew detected. Your build may be incomplete."
Maemo docs state that it's important to disable UTC and set the correct time zone, however I don't really see how that would help in case of diverging host/guest clocks. IMHO much more useful and important is to configure properly working NTP server (chrony recommended, or ntpd) on both host and guest. The single most decisive trick IMHO is to specify the host NTP server as the main entry within guest VM instead of "foreign" NTP servers, to make sure to achieve the most precise coupling between these two related systems (timing drift vs. other systems does not matter nearly as much as a tight time precision for inner host/guest system interaction e.g. in the case of NFS/Samba shares etc.). For verification, see chronyc "sources -v", "tracking" ("System time" row) commands.
After having applied this very tight NTP coupling, this seems to finally have gotten rid of make's time drift warnings.
Perhaps qemu's -tdf (timing drift fix) option magically manages to help in your case, too.
See also Faqs: I received a message about "clock skew".


 

出现“rtc interrupts lost”出错信息,而且客户机应该慢,怎么办?

你可以试试把host机的.config文件中的 CONFIG_HPET_EMULATE_RTC 选项设成y。即 CONFIG_HPET_EMULATE_RTC=y


 从Intel主机上启动虚拟客户机时出现“Exception 13” 或 “Exception 12”出错信息,怎么办?

请参 模拟Intel的实模式的问题


 

我还安装了VMware/Paralles/VirtualBox,当我执行modprobe KVM时,系统死机了。

Intel VT和AMD-V都没有提供一个判断当前有没有软件在使用硬件虚拟扩展的机制。这就意味着,如果有两个内核模块同时尝试使用硬件虚拟扩展功能,非常悲惨的事情就发生了。如果死机情况发生在你同时使用另一种虚拟机的时候,你要确保另一种虚拟机没有使用硬件虚拟扩展,你再报告bug给KVM开发组。


 

QEMU/KVM屏幕上什么都没有,但是系统没有死机。我正准备在客户机上安装Kubuntu。怎么回事?

试试用 -std-vga 选项加载kvm。如果客户操作系统使用framebuffer模式,比如Kubuntu/Ubuntu。

 

当我点击客户操作系统的窗口时,鼠票就像被夺走一样。怎么做才能避免这种情况?有时鼠标在客户操作系统中不显示,或者不动,怎么办?

试试使用选项 -usb -usbdevice tablet 启动 kvm/qemu。如果还不行,在启动前设定环境变量SDL_VIDEO_X11_DGAMOUSE为0。如:

$ export SDL_VIDEO_X11_DGAMOUSE=0

可参看 http://wiki.clug.org.za/wiki/QEMU_mouse_not_working

翻译不易,转载请注明出处 ykyi.net

KVM你问我答FAQ (一)

使用KVM需要哪些准备?

你需要一台运行Linux的x86的机器。它的CPU是有VT技术支持的英特尔cpu或者有SVM(又常被称为AMD-V)支持的AMD的CPU.



KVM支持64位的处理器吗?

KVM支持64位的处理器!此时,你可以运行32位或者64位的客户机。



What is Intel VT / AMD-V / hvm?

英特尔VT,是什么?AMD-V又是什么?hvm是什么?

Intel VTAMD’s AMD-V 都指的是指令集扩展。它们在硬件层面帮助实现虚拟机管理技术。这种技术使得在虚拟机上运行的速度接近直接在真实机器上运行的速度。HVM是硬件虚拟机的缩写(Hardware Virtual Machine )则是一个生产商中立的词汇(vendor-neutral term),它常常用来指代x86指定集扩展。



从哪里得到KVM内核模块呢?

可以从这里获得 http://www.linux-kvm.org/page/Getting_the_kvm_kernel_modules



我如何知道我的CPU支持Intel VT技术或者AMD-V技术呢?

如果你的Linux操作系统比较新,尝试以下的指令:
. egrep ‘^flags.*(vmx|svm)’ /proc/cpuinfo

如果出现一些文字,那说说你的CPU支持虚拟化。你也可以在/proc/cpuinfo文件中找到处理器模块的名字,然后到供应商的网站上查询。
注意:
1. 如果安装了Xen hypervisor,为了防止被劫持,你在dom0和domU中都得不到这些输出。dom0和domU是Xen hypervisor的术语。如果你没有安装Xen,直接忽略。
2. 一些产商默认在BIOS定设中禁用了CPU的虚拟化支持。你需要先在BIOS中打开虚拟化支持。
3. 如果你用的是intel cpu,对于内核版本2.6.15以前的Linux,你得不到这样的输出。如果你用的是amd cpu,对于内核版 本2.6.16以前的linux,你得不到这样的输出。如果你不确定你的Linux内核版本,用#uname -r 命令查看。



出现 “KVM: disabled by BIOS” error 错误

Check if there is an option to enable it in the BIOS. If not, look for a more recent BIOS on the vendor’s web site.
在BIOS设定在找找看有没有启用cpu虚拟化的选项,如果没有,去到主板厂商的网站上面看看有没有新的BIOS发布并支持打开cpu虚拟化,那么你需要刷新BIOS.
注意:
1.对于部分硬件(如 HP nx 6320),你需要先关掉主机电源,再打开主机电源才能使BIOS中启用cpu虚拟化支持生效。
2.BIOS的部分设定有可能与启用CPU虚拟化冲突。比如在Thinkpad T500上,启用Intel AMT技术会出现冲突。这样kvm-intel在载入时会抱怨”disabled by bios”错误。
3. 在一些Dell的硬件中,你还需要禁用”Trusted Execution”,否则不能打开VT。

 



你该怎么使用AMD-V扩展呢?

在根用户权限下敲入:modprobe kvm-amd

 



KVM使用什么样的用户空间工具。(User space tools)

KVM使用稍稍修改过的QEMU作为用户空间工具来管理创建的虚拟机。执行QEMU以后,从linux内核的视角来看,每个虚拟机仅仅是一个普通的进程。你可以用经典的Unix命令,如top, kill, taskset等等来操作虚拟机。



KVM使用何种类型的虚拟磁盘。

QEMU支持的多种磁盘格式如raw images,qcow2(QEMU原生磁盘格式),VMWARE format,等等,KVM都支持(KVM inherits a wealth of disk formats support from QEMU)。