| |||||||
Linux kodunu incelemeden önce Linux'un nasıl oluşturulduğu, derlendiği ve bağlandığı konusunda bazı temel fikirlere sahip olmalıyız. Bunu en baştan başlayarak yapmanın bir yolu Linux makefile'ları anlamaktır. Çevrimiçi kaynak gösterimini tercih ediyorsanız Cross-Referencing Linux bağlantısını kontrol edin.
Bu üst seviye için bazı iyi bilinen makefile hedefleri şunlardır:
linux/Makefile anahatları ile aşağıdaki gibidir:
include .depend
include .config
include arch/i386/Makefile
vmlinux: linux/vmlinux üretir
/* "stext" giriş noktası arch/i386/kernel/head.S dosyasında tanımlı*/
$(LD) -T $(TOPDIR)/arch/i386/vmlinux.lds -e stext
/* $(HEAD) */
+ from arch/i386/Makefile
arch/i386/kernel/head.o
arch/i386/kernel/init_task.o
init/main.o
init/version.o
init/do_mounts.o
--start-group
/* $(CORE_FILES) */
+ from arch/i386/Makefile
arch/i386/kernel/kernel.o
arch/i386/mm/mm.o
kernel/kernel.o
mm/mm.o
fs/fs.o
ipc/ipc.o
/* $(DRIVERS) */
drivers/...
char/char.o
block/block.o
misc/misc.o
net/net.o
media/media.o
cdrom/driver.o
and other static linked drivers
+ from arch/i386/Makefile
arch/i386/math-emu/math.o (ifdef CONFIG_MATH_EMULATION)
/* $(NETWORKS) */
net/network.o
/* $(LIBS) */
+ from arch/i386/Makefile
arch/i386/lib/lib.a
lib/lib.a
--end-group
-o vmlinux
$(NM) vmlinux | grep ... | sort > System.map
tags: vim için linux/tags üretir
modules: modülleri üretir
modules_install: modülleri kurar
clean mrproper distclean: derlemenin yapıldığı dizini temizler
psdocs pdfdocs htmldocs mandocs: çekirdek belgelerini üretir
include Rules.make
rpm: bir rpm üretir
|
Burada --start-group ve --end-group, sembol referans sorununu çözmek için ld komut satırı seçenekleridir. Ayrıntılar için Using LD, the GNU linker: Command Line Options belgesine başvurabilirsiniz.
Rules.make çoklu Makefile dosyaları için kurallar içerir.
Derlemeden sonra ld birkaç nesne ve arşiv dosyasını biraraya getirir, verilerini yeniden yerleştirir ve sembol referansları bağlayıp kapatır. linux/arch/i386/vmlinux.lds dosyası linux/Makefile tarafından yerleşik çekirdek görüntüsü linux/vmlinux 'un ilintilenmesinde kullanılan ilintileyici betik olarak tasarlanmıştır.
/* i386 Linux çekirdeği oluşturmak için ld betiği
* Martin Mares <mj@atrey.karlin.mff.cuni.cz> tarafından yazılmıştır;
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
/* "ENTRY" linux/Makefile içinde "-e stext" komut satırı seçeneği ile değiştirilir */
ENTRY(_start)
/* Çıktı dosyası (linux/vmlinux) yerleşimi.
* Bakınız Using LD, the GNU linker: Specifying Output Sections */
SECTIONS
{
/* Çıktı bölümü .text 3G+1M adresinden başlar.
* Bakınız Using LD, the GNU linker: The Location Counter */
. = 0xC0000000 + 0x100000;
_text = .; /* Metin ve salt okunur veri */
.text : {
*(.text)
*(.fixup)
*(.gnu.warning)
} = 0x9090
/* Tahsis edilmemiş oyuklar 0x9090 ile doldurulur, örn. "NOP NOP" için opcode.
* Bakınız Using LD, the GNU linker: Optional Section Attributes */
_etext = .; /* text bölümünün sonu */
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
/* Sonraki 16 baytlık sınıra hizalandı.
* Bakınız Using LD, the GNU linker: Arithmetic Functions */
. = ALIGN(16); /* Olağandışılık tablosu */
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
__start___ksymtab = .; /* Çekirdek sembol tablosu */
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
.data : { /* Veri */
*(.data)
CONSTRUCTORS
}
/* "CONSTRUCTORS" için bakınız:
* Using LD, the GNU linker: Option Commands */
_edata = .; /* data bölümünün sonu */
. = ALIGN(8192); /* init_task */
.data.init_task : { *(.data.init_task) }
. = ALIGN(4096); /* Init kodu ve veri */
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
. = ALIGN(16);
__setup_start = .;
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
.initcall.init : { *(.initcall.init) }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
. = ALIGN(4096);
.data.page_aligned : { *(.data.idt) }
. = ALIGN(32);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
__bss_start = .; /* BSS */
.bss : {
*(.bss)
}
_end = . ;
/* Çıktı bölümü /DISCARD/ son ilintileme çıktısına dahil edilmeyecektir.
* Bakınız Using LD, the GNU linker: Section Definitions */
/* Çıkarılacak bölümler */
/DISCARD/ : {
*(.text.exit)
*(.data.exit)
*(.exitcall.exit)
}
/* Aşağıdaki çıktı bölümleri 0. bellek konumuna adreslenmiştir.
* Bakınız Using LD, the GNU linker: Optional Section Attributes */
/* Stab hata ayıklama bölümleri. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
} |
linux/arch/i386/Makefile, linux/Makefile tarafından i386'ya özel öğelerin ve kuralların sağlanması için dahil edilmiştir.
Aşağıdaki bütün hedefler linux/Makefile'ının vmlinux hedefine bağımlıdır. Bunlar, linux/arch/i386/boot/Makefile içinde bazı seçenekler ile ilgili hedefler oluşturarak yapılır.
Tablo 1.1. linux/arch/i386/Makefile içindeki hedefler
| Hedef | Komut | ||||
|---|---|---|---|---|---|
| zImage[a] | @$(MAKE) -C arch/i386/boot zImage[b] | ||||
| bzImage | @$(MAKE) -C arch/i386/boot bzImage | ||||
| zlilo | @$(MAKE) -C arch/i386/boot BOOTIMAGE=zImage zlilo | ||||
| bzlilo | @$(MAKE) -C arch/i386/boot BOOTIMAGE=bzImage zlilo | ||||
| zdisk | @$(MAKE) -C arch/i386/boot BOOTIMAGE=zImage zdisk | ||||
| bzdisk | @$(MAKE) -C arch/i386/boot BOOTIMAGE=bzImage zdisk | ||||
| install | @$(MAKE) -C arch/i386/boot BOOTIMAGE=bzImage install | ||||
| |||||
Bu makefile'ın linux/Makefile tarafından ihraç edilen bazı çevre değişkenlerini yeniden tanımlaması önemlidir. Özellikle:
OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S |
Etki, altdizindeki makefile'lara geçecek ve aracın davranışı değişecektir. objcopy komut satırı seçeneklerinin ayrıntıları için GNU Binary Utilities: objcopy'ye bakınız.
$(LIBS)'in niçin "$(TOPDIR)/arch/i386/lib/lib.a"'yı iki defa içerdiği belli değildir.
LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a |
Bazı araç dizileri ile ortaya çıkan ilintileme sorunları üzerinde çalıştırmak için olabilir.
linux/arch/i386/boot/Makefile ne linux/arch/i386/Makefile içerisine ne de linux/Makefile içerisine dahil edilmediği için biraz daha bağımsızdır.
Bununla birlikte biraz ilişki vardır:
zdisk, zlilo veya zdisk hedefleri için gereken $(BOOTIMAGE) değeri linux/arch/i386/Makefile'dan gelir.
Tablo 1.2. linux/arch/i386/boot/Makefile içindeki hedefler
| Hedef | Komut | |
|---|---|---|
| zImage |
| |
| bzImage |
| |
| zdisk |
| |
| zlilo |
| |
| install |
|
tools/build {bootsect, setup, compressed/vmlinux.out}'dan zImage'ı veya {bbootsect, bsetup, compressed/bvmlinux,out}'dan bzImage'ı derler. linux/Makefile "export ROOT_DEV = CURRENT". Dikkat ederseniz $(OBJCOPY) linux/arch/i386/Makefile içerisindeki linux/arch/i386/Makefile tarafından yeniden tanımlanmıştır.
Tablo 1.3. linux/arch/i386/boot/Makefile içindeki hedeflerin desteklenmesi
| Hedef: Öngereksinimler | Komut | ||||
|---|---|---|---|---|---|
| compressed/vmlinux: linux/vmlinux | @$(MAKE) -C compressed vmlinux | ||||
| compressed/bvmlinux: linux/vmlinux | @$(MAKE) -C compressed bvmlinux | ||||
| tools/build: tools/build.c | $(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include[a] | ||||
| bootsect: bootsect.o | $(LD) -Ttext 0x0 -s --oformat binary bootsect.o[b] | ||||
| bootsect.o: bootsect.s | $(AS) -o $@ $< | ||||
| bootsect.s: bootsect.S ... | $(CPP) $(CPPFLAGS) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ | ||||
| bbootsect: bbootsect.o | $(LD) -Ttext 0x0 -s --oformat binary $< -o $@ | ||||
| bbootsect.o: bbootsect.s | $(AS) -o $@ $< | ||||
| bbootsect.s: bootsect.S ... | $(CPP) $(CPPFLAGS) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ | ||||
| setup: setup.o | $(LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ $< | ||||
| setup.o: setup.s | $(AS) -o $@ $< | ||||
| setup.s: setup.S video.S ... | $(CPP) $(CPPFLAGS) -D__ASSEMBLY__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ | ||||
| bsetup: bsetup.o | $(LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ $< | ||||
| bsetup.o: bsetup.s | $(AS) -o $@ $< | ||||
| bsetup.s: setup.S video.S ... | $(CPP) $(CPPFLAGS) -D__BIG_KERNEL__ -D__ASSEMBLY__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ | ||||
| |||||
Dikkat ederseniz bootsect.S bbootsect.s'ye ve setup.S bsetup.s'ye derlendiğinde -D__BIG_KERNEL__'e sahipti. Bunların kodları Yerden Bağımsız Kod (Place Independent Code - PIC) olmalı, bu durumda -Ttext seçeneğinin ne yaptığının önemi yoktur.
Bu dosya görüntüsünün sıkıştırılıp çözülmesi mekanizmasını yerine getirir.
Sıkıştırma/çözmeyi önyükleme kodundan ayırmak iyidir. Bu böl-ve-yönet çözümü bizim sıkıştırma/çözme mekanizmasını kolayca geliştirmemize veya yeni bir önyükleme yöntemi uyarlamamıza imkan sağlar.
linux/arch/i386/boot/compressed/ dizini head.S ve misc.c dosyalarını içerir.
Tablo 1.4. linux/arch/i386/boot/compressed/Makefile içindeki hedefler
| Hedef | Komut | ||||
|---|---|---|---|---|---|
| vmlinux[a] | $(LD) -Ttext 0x1000 -e startup_32 -o vmlinux head.o misc.o piggy.o | ||||
| bvmlinux | $(LD) -Ttext 0x100000 -e startup_32 -o bvmlinux head.o misc.o piggy.o | ||||
| head.o | $(CC) $(AFLAGS) -traditional -c head.S | ||||
| misc.o |
| ||||
| piggy.o |
| ||||
| |||||
piggy.o input_len değişkeninini ve gzip ile sıkıştırılmış linux/vmlinux'ı içerir. input_len piggy.o'nun başında yer alır ve input_len'in kendisi hariç piggy.o'nun boyutuna eşittir. piggy.o bağlayıcı betiğinde geniş açıklamalar için bakınız Using LD, the GNU linker: Section Data Expressions.
Tam olarak söylemek gerekirse objcopy tarafından üretilen gzip ile sıkıştırılmış olan linux/vmlinux'un kendisi (ELF biçiminde) değil onun ikili görüntüsüdür. Dikkat ederseniz $(OBJCOPY), linux/arch/i386/Makefile linux/arch/i386/Makefile içerisinde -O binary seçeneğini kullanarak ham ikili çıktı almak için yeniden tanımlanmıştır.
{bootsect, setup} veya {bbootsect, bsetup} bağlandığı zaman, $(LD) onların ikili biçimde çıktı alınması için --oformat binary seçeneğini belirtir. zImage (veya bzImage) yapıldığında, $(OBJCOPY) compressed/vmlinux (veya compressed/bvmlinux)'dan da bir ara ikili çıktı üretir. zImage veya bzImage'ın tüm bileşenlerinin ham ikili biçimde olması görüntünün kendi kendini bir yükleyiciye başvurmadan yükleyebilmesi ve yerleştirebilmesi için elzemdir.
Hem vmlinux hem de bvmlinux head.o ve misc.o'yu piggy.o'dan önce hazırlar, fakat farklı başlangıç adreslerine (0x1000 ve 0x100000) bağlanırlar.
linux/arch/i386/tools/build.c zImage veya bzImage üretmek için konak aracıdır.
linux/arch/i386/boot/Makefile içinde:
tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage tools/build -b bbootsect bsetup compressed/bvmlinux.out $(ROOT_DEV) > bzImage |
-b büyük_çekirdek_mi (is_big_kernel) anlamındadır, sistem görüntüsünün çok büyük olup olmadığını kontrol eder.
tools/build aşağıdaki zImage veya bzImage'a yeniden yönlendirilen çıktıları standart çıktı birimine verir:
tools/build standart çıktıya yazarken bootsect veya bbootsect'ın bazı içeriklerini değiştirecektir:
Tablo 1.5. tools/build tarafından yapılan değişiklikler
| Offset | Byte | Değişken | Komut |
|---|---|---|---|
| 1F1 (497) | 1 | setup_sectors | kurulum sektörleri sayısı, >=4 |
| 1F4 (500) | 2 | sys_size | system size in 16-bytes cinsinden sistem boyutu, küçük-biten |
| 1FC (508) | 1 | minor_root | root dev minor |
| 1FD (509) | 1 | major_root | root dev major |
Takip eden bölümde compressed/vmlinux vmlinux olarak ve compressed/bvmlinux bvmlinux olarak anılacaktır.
| ||||||||||