Chinaunix首页 | 论坛 | 博客
  • 博客访问: 409313
  • 博文数量: 118
  • 博客积分: 294
  • 博客等级: 二等列兵
  • 技术积分: 667
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-16 20:31
文章分类

全部博文(118)

文章存档

2014年(3)

2012年(25)

2011年(90)

分类:

2011-12-28 20:36:59

原文地址:查看linux源代码 作者:xuxiyao8888

一. 如何查看linux命令源代码

以搜索ls命令源码为例,先搜索命令所在包,命令如下:
which ls /bin/ls
用命令搜索该软件所在包,代码如下:

dpkg -S /bin/ls coreutils: /bin/ls
从上一步中可以知道ls命令的实现在包coreutils中,用apt安装(说安装有些歧义,主要是区分apt-get -d)该包的源代码然后解压,代码如下:
sudo apt-get source coreutils cd /usr/src/coreutils-XXX #XXX表示版本号 sudo tar zxvf coreutils-XXX.tar.gz

或者只下载源码,然后手动打补丁再解压,代码如下:
sudo apt-get -d source coreutils cd /usr/src tar zxvf coreutils-XXX.tar.gz gzip -d coreutils-XXX.diff.gz #这一步会生成coreutils-XXX.diff文件 patch -p0 < coreutils-XXX.diff cd coreutils-XXX tar zxvf coreutils-XXX.tar.gz
OK,这几步执行完后,就可以进入/usr/src/coreutils-XXX/coreutils-XXX/src中查看各命令对应的源代码了

二. ubuntu10.10构建内核树

先查看linux内核版本:$uname -r

网上说用apt-cache search linux-source命令, 会列出一些可选源码包,对准你的内核版本号,选择“with Ubuntu patche”的那个

最后用apt-get install linux-source-2.6.35下载之。解压缩源码包,进入解压后的源码目录。

 可是我试了,搜不到,但是还是可以直接用上面的apt-get 命令下载的,但是我下载,也可以直接到这个网址下源代码,这里面有各个版本的内核,从1.0到2.6的,都有。

在编译之前我们需要Ubuntu原来内核的一个配置文件,这是我/usr/src目录下的文件预览:ls -al

drwxr-xr-x  4 root root     4096 2010-09-04 21:31 fglrx-8.723.1
drwxr-xr-x 24 root root     4096 2010-09-04 20:35 linux-headers-2.6.35-22
drwxr-xr-x  7 root root     4096 2010-09-04 20:35 linux-headers-2.6.35-22-generic
drwxr-xr-x 25 root root     4096 2010-09-16 21:39 linux-source-2.6.35
-rw-r--r--  1 root root 65846876 2010-09-01 22:41 linux-source-2.6.35.tar.bz2

现在我们需要/boot目录下的config-2.6.35-22-generic文件,我们把它拷贝到我们刚下好解压的目录,也就是linux-source-2.6.35

sudo cp /boot/config-2.6.35-22-generic /usr/src/linux-source-2.6.35/.config

接下来切换到root用户
sudo -i

cd /usr/src/linux-source-2.6.35

make menuconfig或者直接make oldconfig(无需拷贝.config)

终端会弹出一个配置界面

最后有两项:load a alternative kernel configuration... 
save a alternative configuration... 
选择load a kernel configuration保存,然后在选择save akernel configuration再保存退出,并退出配置环境。

 

接下来我们就要开始编译了。

#cd /usr/src/linux-source-2.6.35
#make
记住一定要是管理员帐号运行,这个过程很久,如果你的cpu是双核的可以在make后面加个参数,make -j4.

#make bzImage 执行结束后,可以看到在当前目录下生成了一个新的文件: vmlinux, 其属性为-rwxr-xr-x。 

 

下面就要编译模块了,但是编译模块时可能会出现如下问题
编译问题(ld: /ubuntu/omnibook/sections.lds: No such file: No such file or directory 
解决方法:

在/usr/src/linux-source-2.6.35/ubuntu/omnibook/Makefile 中

ifeq ($(KERNELRELEASE),)

# Support for direct Makefile invocation

的前面增加:
PWD=$(shell pwd)

 也就是在ifeq的上一行增加。

然后再编译模块

#make modules /* 编译 模块 */


#make modules_install  这条命令能在/lib/modules目录下产生一个目录

 如果一切顺利,编译过程中不出现什么错误的话,接下来我们就可以开始linux模块的helloworld了。

我在 /home/xxxx/linux_modules/ 目录下创建2个文本文件 hello.c Makefile

 //hello.c 
#include  
#include  
MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void) 

printk(KERN_ALERT "Hello, world\n"); 
return 0; 
}

static void hello_exit(void) 

printk(KERN_ALERT"Goodbye, cruel world\n"); 
}

module_init(hello_init); 
module_exit(hello_exit);

 

//Makefile

# Makefile2.6(2.6内核专门的Makefile文件)
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationshsip of files and target modules are listed here.
mymodule-objs := hello.o #param-objs := file1.o file2.o
obj-m := hello.o         #obj-m := param.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
    $(MAKE) -C $(KDIR) M=$(PWD)
clean:
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions #这个伪命令没起作用,待解决,不影响make

.PHONY: modules modules_install clean
endif
#KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读取执行else之后的内容,如果 make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C $(KDIR)指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及要生成的目标模块名。param-objs := file1.o file2.o 表示param.o由file1.o与file2.o 连接生成,obj-m := param.o表示编译连接后将生成param.o模块。

需要注意的是makefile的格式$(MAKE)前面要加个tab.
make 编译,不出现错误的话,用ls -al查看linux_modules目录下产生了如下文件:
hello.c   hello.mod.c  hello.o   modules.order
hello.ko  hello.mod.o  Makefile  Module.symvers

其中hello.ko就是可加载的模块文件

现在我们就可以将编译好的模块helloworld加载到内核中去了

#insmod ./hello.ko   //这个命令把hello.ko加载到内核

#lsmod|grep hello   //lsmod 这个命令可以查看当前所有的驱动模块,结果应该显示hello 680 0

#rmmod hello         //这个命令是把hello这个模块移除掉

程序的输出结果可以在(printk 不会输出到终端)

dmesg |grep world
或是/var/log/syslog文件中查看

Hello,World
Goodbye,cruel world

这是程序的输出。


如果在输入insmod ./hello.ko时出现如下错误提示:insmod: error inserting 'hello.ko': -1 Invalid module format

是因为记载版本号的字符串和当前正在运行的内核模块的不一样,这个版本印戳作为一个静态的字符串存在于内核模块中,叫vermagic,可以从编译模块中间生成的文件helloworld.moc.h中,如果出现这种情况:

1,根据modinfo hello.ko命令查看vermagic的值 
2,根据uname -r查看内核版本 
3,对比上边两步的值是否相同 
若相同,我就不知道了 
若不同,采用make -C /lib/modules/此处为你内核版本号对应的文件夹/build M=你模块源码的路径 modules
 

阅读(640) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~