Ubuntu编译内核及grub的一些笔记 | 迟思堂工作室
A-A+

Ubuntu编译内核及grub的一些笔记

2014-11-04 20:05 GNU/Linux系统 暂无评论 阅读 5,632 次

最近心态不稳定,不怎么想发表文章,但看了看之前写了的笔记,想想还是整理出来吧,其实我写文章,也有一部分原因是为了心里的慰藉——当年游戏打不过别人,关注点便转向其它方面。这里整理的是以前编译内核、引导启动过程的步骤及问题的解决。

内核编译

安装Ubuntu默认没有基本的开发环境,需要自己去安装。比如编译内核要安装gcc,还要装ncurses库:

apt-get install build-essential apt-get install libncurses5-dev libncurses5

Ubuntu编译内核的步骤十分简单,只要下面几个命令:

make menuconfig(默认不需要也行) make bzImage make modules sudo make modules_install sudo make install

在最后一步,会自动去更新grub配置,不用再自己生成内核的img,再自己拷贝内核文件到/boot目录了。不过,默认的配置会编译很多很多的模块,编译时间久,无意间看了一下,竟然有4000个左右——懒人不动手,就得花时间等。

对于内核模块的编译,一般选择在源码树外的目录进行编译,这时,要自己写Makefile——而且这个Makefile还不是很简单,其实,如果将其放到内核树中编译,可能会变得简单一些。实际上,我就体会到这种做法的好处。最近做的东西是基于x86平台的,它不像ARM那样可以直接在uboot下载内核文件启动。我要将内核文件拷贝到系统的/boot目录,然后再重启设备,这过程很麻烦。为了方便调试,将驱动以ko形式在系统运行时加载、调试。通过后再将其编译进内核。这时,驱动的源码是放到内核树中的,所以不用再重新写Makefile。

比如,编写字符模块hello,把需要的代码放到driver/char/hello目录,再修改char目录的Kconfig和Makefile。

Kconfig为配置的文件,通过它,make menuconfig才能识别出来,。

config HELLO tristate "Hello world" default y ---help--- God help those whom help themself.

保存配置文件后,其中的HELLO变成CONFIG_HELLO,再修改Makefile

obj-$(CONFIG_HELLO) += hello/

这样编译时就会找到hello目录。另外,还要在hello目录加上一个Makefile来指定编译哪些文件,编译后的模块名称:

如:

# # Makefile for the hello drivers. # obj-$(CONFIG_HELLO) += Hello.o Hello-objs := hello.o hello_drv.o

第一行指定了编译后模块名称(如果make menuconfig时选择“M”的话),编译得到的将是Hello.ko文件,第二行指定了要编译哪些文件。注意第一行的Hello必须与第二行的Hello-objs中的“Hello”一致,否则会编译不通过,会有如下提示:

make[3]: *** No rule to make target `drivers/char/hello/hello.o', needed by `drivers/char/hello/built-in.o'.  Stop.

我因为这个问题而花费了好几分钟。

进行上面操作后,编译模块就十分简单了,不需要额外的Makefile(因为已经写有了),编译单个模块,以I801驱动模块为例:

make CONFIG_I2C_I801=m -C /home/latelee/kernel_source/linux-3.17.1 M=/home/latelee/kernel_source/linux-3.17.1/drivers/i2c/busses/ modules

如果进入kernel source目录,就可以简化成:

make CONFIG_I2C_I801=m -C . M=drivers/i2c/busses modules

对于上面所说的模块,则是:

make CONFIG_HELLO=m -C . M=drivers/char/ modules

Grub启动

Ubuntu默认是启动图形界面的,可以通过修改grub配置文件,改为text模式启动。修改/etc/default/grub,把splash改成text,再运行update-grub命令,即可完成。

如果直接改/boot/grub/grub.cfg的话,也是可以的,但下次重新安装内核又会再次使用/etc下的配置,因此,还是要改配置文件。

有一次,启动硬盘后,出现错误信息:

error: file '/grub/i386-pc/normal.mod' not found. grub rescue>

在网上找了解决方法,如下
1、使用live cd进入系统
2、挂载根分区硬盘(假设"/"分区是sda1)

mount /dev/sda1 /mnt

3、安装grub

sudo grub-install /dev/sda --root-directory=/mnt

如果系统进入了grub,但由于路径错误不能正常启动,可以在grub命令行用命令来启动。实际上,我就遇到过几次,因为连接着显示器,错误信息一闪而过,就变黑屏了,看不及看清楚。最终有同事提示下才发现问题所在。因为我的vmlinuz文件在/分区,会引用全路径/boot/vmlinuz,而我的grub配置文件是另一个硬盘的配置,是/boot分区,直接用/vmlinuz。——这也是同时多进程工作的弊端,有时会分不清到底自己在搞哪一块。我也同时因为同时在secureCRT中连接多个Linux(一同个窗口,一个连设备ssh,一个连虚拟机ssh,一个连服务器ssh)而无意间把服务器关机了,幸好影响不大。

下面是grub启动linux的命令示例:

grub> grub>linux /vmlinuz-3.17.1 root=/dev/sda2 grub>initrd /initrd-3.17.1 grub>boot

最后,附上一个很简单但能正常启动的grub.cfg:

set default=0 # 第一个启动项 set timeout=10 # 超时时间 menuentry 'My Ubuntu --first' { set root='hd0,msdos1' echo "vmlinuz...." linux   /vmlinuz-3.17.1 root=/dev/sda2 ro  console=tty0 console=ttyS2,115200n8 } menuentry 'My Ubuntu --second' { set root='hd0,msdos1' echo "vmlinuz...." linux   /vmlinuz-3.17.1_nof75111 root=/dev/sda2 ro  console=tty0 console=ttyS2,115200n8 }

发行版本的grub.cfg有很多内容,其实就包括上一篇文章说到的uuid,我一度担心因为在Grub中要配置,而每个硬盘的分区id不同,则要分别改配置文件,结果用dd命令拷贝后无须担心这个问题了。

李迟,发表于2014年11月04日晚上



如果本文对阁下有帮助,不妨赞助笔者以输出更多好文章,谢谢!
donate




给我留言