Çekirdeğin bir main () işlevi var mı? [kapalı]


52

Aygıt sürücülerini ve Çekirdek programlamayı öğreniyorum. Jonathan Corbet'in kitabına göre, main()aygıt sürücülerinde işlev yok .

Bu yüzden iki soru:

  • Neden main()aygıt sürücülerinde bir işleve ihtiyacımız yok ?
  • Çekirdeğin bir main()işlevi var mı?

Birisi bunu bana açıklayabilir mi?


1
Burada da aynı kullanıcı tarafından sorulan sorular: stackoverflow.com/q/18266063/827263
Keith Thompson

@KeithThompson ... Evet ... Sadece istediğime cevap alamadığım için burada sordum.
birisi

@Shadur ... neyse, şimdi kapanmak üzere ... Ve bunu göç etme ayrıcalığına sahip değilim ...
birisi,

Yanıtlar:


82

Kullanıcı alanı programlarında, ikili çalıştırıldığında libc başlatma kodu tarafından çağrılanmain() programın giriş noktasıdır . Çekirdek kodunda libc'ye güvenme lüksü yoktur, çünkü libc'nin kendisi bellek ayırma, giriş / çıkış, işlem yönetimi vb. İçin çekirdek arama arayüzüne dayanır.

Bu eşdeğer, bahsedilen main()çekirdek kod içinde start_kernel()olan, bootloader denilen kernel image yüklü sonra, bellek ve kurulum gerekli donanım ve bellek sayfalama içine sıkıştırılmış. start_kernel()sistem kurulumunun çoğunluğunu gerçekleştirir ve sonunda başlatma işlemini başlatır.

Linux çekirdeği modüllerine giriş noktası, module_init()makro çağırılarak çekirdeğe kaydedilen bir başlatma işlevidir . Kayıtlı modül başlatma işlevi daha sonra çekirdek başlatması sırasında işlev aracılığıyla çekirdek kodu ile çağrılırdo_initcalls() .


11
mainC'deki yöntemin asıl amacını tanıdığınız için teşekkür ederiz (OS'nin doğrudan arama yaptığı main, genellikle böyle olmayan ve hatta C ++ için durumun daha az olduğu bir yanlış anlaşılmadır ). ' Sadece bunun için yapabilirsem, sana başka bir oy ver.
CVn'de

1
@Thomas ... Bu mükemmel cevap için teşekkürler ....
birisi

17

Çekirdeğin bir mainişlevi yoktur. mainC dilinin bir kavramdır. Çekirdek C ve montaj ile yazılmıştır. Çekirdeğin giriş kodu meclis tarafından yazılmıştır.

Önyükleme sırası aşağıdaki gibi düzenlenir:

  1. BIOS, genellikle bir önyükleme bloğu cihazından bir önyükleyici yükler. Şu anda popüler bir boot loader grub.
  2. Grub, bir ilk kök cihazı ( initrd) ile mümkün olan bir çekirdek görüntüsünü ram içine yükler . Sonra bir adresten kod yürütülür.
  3. Çekirdek görüntüsünde bazı çekirdek modülleri vardır, örneğin: dosya sistemi modülleri, aygıt sürücüleri. Çekirdek görüntüsü, kök dosya sistemini bağlamak için dosya sistemi modülünü kullanır. Artık çekirdek tüm çekirdek modüllerini diskten yükleyip çalıştırabilir.
  4. Çekirdek başlatma görevlerini çalıştırır. Örneğin: PCI veriyolu üzerinden geçiş yapın ve tüm PCI aygıtlarını bulun, tüm aygıt sürücülerini ilklendirin.
  5. Son olarak, çekirdek işlem 0 ve işlem 1'i oluşturur ( initişlem), CPU bağlamını halka 0'dan halka 3'e geçirir ve init işlemini başlatır (işlem kimliği 1'dir). Şimdi çekirdek önyüklemesi bitti!
  6. initProgram tüm init komut dosyalarını çalıştırır. Tüm servisler başlatıldı. Kabuk denir. Kullanıcılar giriş yapabilir.

mainİşlev bir Cı fonksiyonudur. Aslında ana yöntem C programlarının giriş noktası değildir. C çalışma zamanı daha önce birçok işlevi çağırır main. GCC'nin bir genişletme özelliği var: yapıcılar. "Yapıcı" olarak bildirilen işlevler daha önce çağrılır main.

Örneğin:

/* This should not be used directly. Use block_init etc. instead. */ 
#define module_init(function, type) \
    static void _attribute__((constructor)) do_qemu_init ## function(void) { \
    register_module_init(function, type); \
} 

Bu makro qemu projesinden.


Ana yöntem ac yöntemidir. Aslında ana yöntem c programının girişi değildir. Çalışma zamanı ana yöntemden önce birçok yöntemi çağırmıştır.
Edward Shen

Eh, bios genellikle bir önyükleyici yükler ve bu önyükleyici bir çekirdek görüntüsü (ve muhtemelen bir initrd) yükler. Çekirdeğin kodu çekirdeğin görüntüsünde,
initrd'de

GCC'nin bir genişletme özelliği var: yapıcı. Metod bildirisine "constructor" ana metottan önce çağrılır. Örneğin: / * Bu doğrudan kullanılmamalıdır. Bunun yerine block_init vs. kullanın. * / #define module_init (function, type) \ statik boşluk _attribute __ ((yapıcı)) do_qemu_init ## function (void) {\ register_module_init (function, type); \}
Edward Shen

1
initrd.img Çekirdek görüntüsü DEĞİLDİR . Çekirdek tarafından önyükleme sırasında yüklenen bir dizi modül. Çekirdek görüntülerinde genellikle "vmlinuz" ile başlayan isimler bulunur, ancak dağıtımdan dağıtıma farklılık gösterir.
goldilocks

3
Bu cevap "her şey bir PC / Linux / i86" dır ve bu şekilde önyüklenir ve çekirdek de bu şekildedir ... Neden herkes dünyadaki tek olası yol olduğunu düşünüyor?
Jens

9

Sistemi, gerçek sistemden korumalı moda geçmeye hazırlamak için arch / x86 / boot / main.c öğesinde bir main () işlevi vardır, ancak diğer mimarilerin böyle bir kodu yoktur. Linux çekirdeği 2.6.x'in x86 platformunda nasıl çizildiğine dair güzel bir genel bakış . Gerçekten okumaya değer.

NASIL belgesi Linux çekirdeği gelişimi yapmak için, Linux çekirdeği

Standart C kütüphanesine güvenmeyen bağlantısız bir C ortamı, bu nedenle C standardının bazı bölümleri desteklenmez.

BT standardı olan BTW’nin anlamı

Bir 'ana' işlev tanımlamak için bağlantısız bir ortamda bir programın gerekli olup olmadığı, uygulama tarafından tanımlanır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.