คอมไพล์ Linux kernel บน Fedora 9 ในรูปแบบ RPMS

โดยทั่วไป kernel ที่ติดตั้งมากับลินุกซ์เวอร์ชั่น (distribution) ต่างๆ รวมทั้ง Fedora ด้วย จะสามารถใช้งานได้เลย รองรับอุปกรณ์ hardware ได้ส่วนใหญ่หลากหลายชนิด ไม่จำเป็นต้องแก้ไขเพิ่มเติมแต่อย่างใด

แต่ในบางครั้งถ้ามีอุปกรณ์รุ่นใหม่ที่ kernel ไม่รู้จัก หรือต้องการจะปรับแต่ง kernel ให้เรียกใช้งานเฉพาะสำหรับอุปกรณ์ที่เราใช้อยู่จริงๆ ทั้งนี้เพื่อประหยัด CPU/Memory ที่ถูกใช้โดยเปล่าประโยชน์ รวมทั้งเพิ่มความปลอดภัยให้กับตัวลินุกซ์เองด้วย

ในบทความนี้จึงขอแนะนำวิธีปรับแต่ง kernel และคอมไพล์ใหม่ โดยจะทดสอบบน Fedora 9

คำเตือน การคอมไพล์ kernel จะใช้เนื้อที่จำนวนมากหลายกิกะไบต์ อย่าลืมเผื่อเนื้อที่ไว้ก่อนที่จะเริ่มคอมไพล์ เพราะถ้าเนื้อที่ไม่เพียงพอ การคอมไพล์จะมีปัญหา และต้องเริ่มคอมไพล์ใหม่ ซึ่งจะใช้เวลานานมาก

แนะนำให้คอมไพล์ kernel ในรูปแบบ src.rpm ด้วยผู้ใช้งานธรรมดาที่ไม่ใช่ root ซึ่งสามารถดูได้ที่ วิธีการคอมไพล์ไฟล์ src.rpm ด้วยผู้ใช้งานธรรมดา

ติดตั้งไฟล์ src.rpm ซึ่งเป็น kernel source ในรูปแบบไฟล์ rpm

[user01@server ~]$ rpm -ivh kernel-2.6.25-14.fc9.src.rpm
   1:kernel                 warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
...
########################################### [100%]

หมายเหตุ ไม่ต้องสนใจ warning ที่เกี่ยวข้องกับ user, group does not exists

ผลลัพธ์ที่ได้จากการติดตั้งไฟล์ src.rpm จะได้ไฟล์ kernel.spec ใน SPECS/ ซึ่งจะเป็นชุดคำสั่ง (script) ในการคอมไพล์ และไฟล์ที่เป็น source code ที่อยู่ใน SOURCES/

ตัวอย่างผลลัพธ์ที่ได้จากการติดตั้งไฟล์ src.rpm

[user01@server ~]$ cd rpmbuild/
[user01@server rpmbuild]$ ls SPECS/
kernel.spec
[user01@server rpmbuild]$ ls SOURCES/
config-debug                                   linux-2.6-e1000-ich9.patch
config-generic                                 linux-2.6-efika-not-chrp.patch
config-i586                                    linux-2.6-execshield.patch
...
linux-2.6-drm-modesetting-oops-fixes.patch     merge.pl
linux-2.6-drm-radeon-fix-oops2.patch           nouveau-drm.patch
linux-2.6-drm-radeon-fix-oops.patch            nouveau-drm-update.patch

เข้าไปที่ไดเร็คทอรี SPECS/ แล้วใช้คำสั่ง rpmbuild เพื่อสร้าง kernel source tree สำหรับการคอมไพล์

หมายเหตุ การใช้ option ‘-bp’ จะแตกไฟล์ source code และทำการ patch ไฟล์ต่างๆ ที่อยู่ใน SOURCES/ ตามที่ระบุในไฟล์ kernel.spec

[user01@server rpmbuild]$ cd SPECS/
[user01@server SPECS]$ rpmbuild -bp --target=`uname -m` kernel.spec
Building target platforms: i686
Building for target i686
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.43192
+ umask 022
+ cd /home/user01/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ patch_command='patch -p1 -F1 -s'
+ '[' '!' -d kernel-2.6.25/vanilla-2.6.25 ']'
+ rm -f pax_global_header
+ cd /home/user01/rpmbuild/BUILD
+ rm -rf kernel-2.6.25
+ /bin/mkdir -p kernel-2.6.25
+ cd kernel-2.6.25
+ /usr/bin/bzip2 -dc /home/user01/rpmbuild/SOURCES/linux-2.6.25.tar.bz2
+ tar -xf -
...
...
...
config:3405:warning: trying to assign nonexistent symbol INSTRUMENTATION
.config:3450:warning: trying to assign nonexistent symbol ACPI_CUSTOM_DSDT_INITRD
.config:3464:warning: trying to assign nonexistent symbol CGROUP_MEM_CONT
.config:3480:warning: trying to assign nonexistent symbol DEBUG_IGNORE_QUIET
+ echo '# i386'
+ cat .config
+ find . '(' -name '*.orig' -o -name '*~' ')' -exec rm -f '{}' ';'
+ cd ..
+ exit 0

ตรวจสอบ kernel source tree ที่ถูกสร้างขึ้น

[user01@server SPECS]$ cd ../BUILD/kernel-2.6.25/
/home/user01/rpmbuild/BUILD/kernel-2.6.25
[user01@server kernel-2.6.25]$ ls -CF
linux-2.6.25.i686/  vanilla-2.6.25/

สร้างคอนฟิกของ kernel ที่จะใช้เป็นต้นแบบ

เข้าไปในไดเร็คทอรี linux-2.6.25.i686 ภายในนี้จะมีไดเร็คทอรีย่อยที่ชื่อว่า configs/ ซึ่งจะมีไฟล์คอนฟิกสำหรับเครื่องต่างๆ ในที่นี้จะเลือกไฟล์สำหรับเครื่องที่เป็น i686 ชื่อไฟล์คือ kernel-2.6.25-i686.config

copy ไฟล์คอนฟิกนี้ไปเป็นชื่อไฟล์ .config

[user01@server kernel-2.6.25]$ cd linux-2.6.25.i686/
[user01@server linux-2.6.25.i686]$ ls configs/
kernel-2.6.25-i586.config  kernel-2.6.25-i686-debug.config  kernel-2.6.25-i686-PAEdebug.config
kernel-2.6.25-i686.config  kernel-2.6.25-i686-PAE.config    kernel-2.6.25-i686-xen.config
[user01@server linux-2.6.25.i686]$ cp configs/kernel-2.6.25-i686.config .config

รันคำสั่ง make oldconfig

[user01@server linux-2.6.25.i686]$ make oldconfig
scripts/kconfig/conf -o arch/x86/Kconfig
*
* Linux Kernel Configuration
*
*
* General setup
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?] y
Local version - append to kernel release (LOCALVERSION) []
Automatically append version information to the version string (LOCALVERSION_AUTO) [N/y/?] n
Support for paging of anonymous memory (swap) (SWAP) [Y/n/?] y
System V IPC (SYSVIPC) [Y/n/?] y
...
...
...
CRC32 functions (CRC32) [Y/?] y
CRC7 functions (CRC7) [N/m/y/?] n
CRC32c (Castagnoli, et al) Cyclic Redundancy-Check (LIBCRC32C) [M/y/?] m
#
# configuration written to .config
#

รันคำสั่ง make menuconfig สำหรับการเลือกคอนฟิกของ kernel โดยจะมีรูปแบบการเลือกเป็นแบบเมนู

[user01@server linux-2.6.25.i686]$ make menuconfig

ตัวอย่างหน้าจอของ make menuconfig
Fedora 9 make menuconfig

เมื่อแก้ไขคอนฟิกของ kernel เรียบร้อย และออกจาก menuconfig แล้ว ให้แก้ไขไฟล์ .config โดยเพิ่ม hardware platform ไว้บนบรรทัดบนสุด โดยสามารถตรวจสอบ hardware platform ได้จากการรันคำสั่ง uname -i

ตัวอย่างการตรวจสอบและเพิ่ม hardware platform ในไฟล์ .config

[user01@server linux-2.6.25.i686]$ uname -i
i386
[user01@server linux-2.6.25.i686]$ vi .confg
# i386
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.25
# Tue Sep 16 14:03:32 2008
#

หลังจากเพิ่ม hardware platform ในไฟล์ .config แล้ว copy ไฟล์นี้กลับเข้าไปใน SOURCES/ แต่เปลี่ยนชื่อเป็น config-<arch> โดย <arch> ได้มาจากการรันคำสั่ง uname -m

[user01@server linux-2.6.25.i686]$ cp .config ../../../SOURCES/config-i686

ตามคำแนะนำในไฟล์ kernel.spec ว่า ถ้ามีการแก้ไขคอนฟิกของ kernel ให้เพิ่มการ define ตัวแปร buildid ด้วย ในที่นี้จะระบุเป็น .spalinux.test1.

ตัวอย่างการแก้ไขการ define ตัวแปร buildid

...
%define buildid .spalinux.test1
...

คอมไพล์ kernel และสร้างเป็นไฟล์ RPMS ใหม่ โดยจะเลือกคอมไพล์ให้เป็น package เฉพาะตัว base kernel สำหรับการบู๊ตเครื่อง และ kernel-devel ไว้สำหรับคอมไพล์โปรแกรมอื่นๆ เพิ่มเติม

หมายเหตุ option ‘-bb’ เป็นการระบุให้มีการคอมไพล์โปรแกรมจริงๆ ซึ่งการคอมไพล์ kernel นั้นจะใช้เวลาค่อนข้างนานหลายชั่วโมง ขึ้นอยู่กับคอนฟิกที่เราเลือกด้วย แล้วก็ขึ้นกับ CPU, Memory

[user01@server SPECS]$ rpmbuild -bb --with baseonly --without debuginfo --target=`uname -m` kernel.spec
Building target platforms: i686
Building for target i686
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.55363
+ umask 022
+ cd /home/user01/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ patch_command='patch -p1 -F1 -s'
+ '[' '!' -d kernel-2.6.25/vanilla-2.6.25 ']'
+ cd kernel-2.6.25
+ '[' -d linux-2.6.25.i686 ']'
+ rm -rf deleteme.i686
+ mv linux-2.6.25.i686 deleteme.i686
+ rm -rf deleteme.i686
+ cp -rl vanilla-2.6.25 linux-2.6.25.i686
...
...
...
Checking for unpackaged file(s): /usr/lib/rpm/check-files /var/tmp/kernel-2.6.25-14.spalinux.test1.fc9.i686-root
Wrote: /home/user01/rpmbuild/RPMS/i686/kernel-2.6.25-14.spalinux.test1.fc9.i686.rpm
Wrote: /home/user01/rpmbuild/RPMS/i686/kernel-devel-2.6.25-14.spalinux.test1.fc9.i686.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.98631
+ umask 022
+ cd /home/user01/rpmbuild/BUILD
+ cd kernel-2.6.25
+ rm -rf /var/tmp/kernel-2.6.25-14.spalinux.test1.fc9.i686-root
+ exit 0

ผลลัพธ์ที่ได้จากการคอมไพล์จะอยู่ในไดเร็คทอรี RPMS/ แล้วแยกย่อยตามชนิด (arch) ของเครื่องที่ระบุตอนใช้คำสั่ง rpmbuild

[user01@server RPMS]$ find i686/
i686/
i686/kernel-2.6.25-14.spalinux.test1.fc9.i686.rpm
i686/kernel-devel-2.6.25-14.spalinux.test1.fc9.i686.rpm

ข้อมูลอ้างอิง

Leave a Reply

Your email address will not be published.