โดยทั่วไป 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
เมื่อแก้ไขคอนฟิกของ 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