Linux çekirdek sistemi çağrılarının uygulamalarını nasıl bulabilirim?


375

Bir işlevin mkdirçekirdek kaynağına bakarak nasıl çalıştığını anlamaya çalışıyorum . Bu, çekirdeğin içsellerini anlama ve çeşitli işlevler arasında gezinme girişimidir. mkdirİçinde tanımlanmış olduğunu biliyorum sys/stat.h. Prototipi buldum:

/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

Şimdi bu fonksiyonun hangi C dosyasında uygulandığını görmem gerekiyor. Kaynak dizinden denedim

ack "int mkdir"

görüntülenen

security/inode.c
103:static int mkdir(struct inode *dir, struct dentry *dentry, int mode)

tools/perf/util/util.c
4:int mkdir_p(char *path, mode_t mode)

tools/perf/util/util.h
259:int mkdir_p(char *path, mode_t mode);

Fakat hiçbiri içindeki tanımla eşleşmiyor sys/stat.h.

Sorular

  1. Hangi dosyada mkdiruygulama var?
  2. Yukarıdaki gibi bir fonksiyon tanımlaması ile hangi dosyanın uygulandığını nasıl öğrenebilirim? Çekirdeklerin yöntemleri tanımlama ve uygulamada takip ettiği herhangi bir kalıp var mı?

NOT: Çekirdek 2.6.36-rc1 kullanıyorum .


2
Bu arada, şuna bir göz atın: voinici.ceata.org/~tct/resurse/utlk.pdf
Tom Brito

Yanıtlar:


386

Sistem çağrıları normal işlev çağrıları gibi gerçekleştirilmez. Kullanıcı alanından çekirdek alana geçiş yapmak için özel bir kod gerekir, temel olarak çağrı sitesinde programınıza enjekte edilen bir satır içi montaj kodu. Sistem çağrısını "yakalayan" yan kod, aynı zamanda en azından ilk başta derinlemesine anlamanız gerekmeyen düşük seviyeli şeylerdir.

Gelen include/linux/syscalls.hÇekirdek kaynak dizin altında, bu bulmak:

asmlinkage long sys_mkdir(const char __user *pathname, int mode);

Sonra /usr/include/asm*/unistd.h, şunu bulursun:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

Bu kod diyor mkdir(2)ki sistem çağrısı # 83. Diğer bir deyişle, sistem çağrıları, kendi programınızdaki normal bir işlev çağrısındaki adrese göre değil, programınızla bağlantılı bir kitaplıktaki bir işleve göre numara olarak adlandırılır. Yukarıda bahsettiğim satır içi montaj tutkal kodu, parametrelerinizi beraberinde alarak, kullanıcıdan çekirdek alanına geçiş yapmak için bunu kullanır.

Burada işlerin biraz garip olduğuna dair bir başka kanıt da, sistem çağrıları için her zaman katı bir parametre listesi bulunmadığıdır: open(2)örneğin, 2 veya 3 parametre alabilir. Bu demektir ki open(2)bir aşırı , C ++, C bir özelliği, henüz syscall arayüzü Cı-uyumludur. (Bu, tek bir fonksiyonun değişken sayıda argüman almasına izin veren C'nin varargs özelliği ile aynı şey değildir .)

İlk sorunuza cevap vermek için, var olan tek bir dosya mkdir()yok. Linux birçok farklı dosya sistemini desteklemektedir ve her biri "mkdir" işlemi için kendi uygulamasına sahiptir. Çekirdeğin hepsini tek bir sistem çağrısının arkasına gizlemesini sağlayan soyutlama katmanına VFS denir . Yani, muhtemelen fs/namei.c, içinde kazmaya başlamak istersiniz vfs_mkdir(). Düşük seviyeli dosya sistemi değiştirme kodunun gerçek uygulamaları başka yerdedir. Örneğin, ext4 uygulaması ext4_mkdir(), içinde tanımlandığı şekilde adlandırılır fs/ext4/namei.c.

İkinci sorunuza gelince, evet, tüm bunların kalıpları var, ancak tek bir kural yok. Gerçekte ihtiyacınız olan şey, belirli bir sistem çağrısını nerede aramanız gerektiğini bulmak için çekirdeğin nasıl çalıştığını anlamak için oldukça geniş bir anlayış. Tüm sistem çağrıları VFS'yi kapsamaz, bu nedenle çekirdek tarafındaki çağrı zincirleri tümüyle başlamaz fs/namei.c. mmap(2)örneğin, mm/mmap.cçekirdeğin bellek yönetimi ("mm") alt sisteminin bir parçası olduğu için başlar .

Bovet ve Cesati'nin " Linux çekirdeğini anlama " nın bir kopyasını almanızı tavsiye ederim .


Çok iyi cevap. Bahsettiğiniz kitap hakkında bir nokta, "Linux Çekirdeğini Anlamak". Ben yok, ama piyasaya sürülme tarihinden itibaren (2000) ve TOC (cevher sahasında) bana öyle geliyor ki bu, yaklaşık 2.2 çekirdek artı 2.4 çekirdekten bazı içgörüler (ama benim hatalıyım). Sorum şu: 2.6 çekirdek içini kapsayan eşdeğer bir kitap var mı? (ya da 2.2, 2.4 ve 2.6'yı kapsıyorsa daha iyi)?
DavAlPi

2
@DavAlPi: Bildiğim kadarıyla Bovet & Cesati hala bu konuyla ilgili en iyi kitap. Daha fazla malzemeyle takviye etmem gerektiğinde, birlikte Documentationçalıştığım çekirdeğin kaynak ağacının alt dizinine kazıyorum .
Warren Young,

1
Aslında açık (2) bir varargs işlevidir. Bunu çağırmanın sadece iki yolu vardır, bu nedenle manpage bu şekilde belgelenir, gerçek prototip ...herhangi bir varargs işlevi olarak var. Tabii ki, bu libc düzeyinde uygulanmaktadır. Üçüncü parametre kullanılmadığında çekirdeği ABI'ya 0 veya bir çöp değeri geçebilir.
Random832

"Anlamana gerek yok bir şey". Eğer böyle bir cümle yığın değişimi ağında bulamazsa, dünya daha iyi bir yer olurdu.
Petr

84

Bu muhtemelen doğrudan sorunuzu yanıtlamıyor, ancak stracetemel sistem çağrılarını anlamaya çalışırken, en basit kabuk komutları için bile yapılan eylemi gerçekten çok iyi buldum . Örneğin

strace -o trace.txt mkdir mynewdir

Komutu çağıran sistem mkdir mynewdir, izleme zevkiniz için trace.txt dosyasına atılır.


5
+1 Düzgün numara! Bunu daha önce kullanmazdım
David Oneill

3
Daha da iyisi, çıktı dosyasını trace.strace yapın ve VIM'de açın. VIM onu daha kolay hale getirerek vurgulayacaktır.
Marcin

55

Linux çekirdek kaynağını okumak için iyi bir yer Linux çapraz referansıdır (LXR) ¹. Aramalar, serbest metin arama sonuçlarına ek olarak, yazılan eşleşmeleri (işlev prototipleri, değişken bildirimleri, vb.) Döndürür, bu nedenle yalnızca bir grepten daha iyidir (ve daha hızlıdır).

LXR önişlemci tanımlarını genişletmiyor. Sistem çağrıları, adlarını her yerde önişlemci tarafından yönetiliyor. Ancak, çoğu (tümü?) Sistem çağrıları SYSCALL_DEFINExmakro ailelerinin biriyle tanımlanır . Yana mkdiriki bağımsız değişken, için bir arama alır SYSCALL_DEFINE2(mkdir, potansiyel satışları ilanından mkdirsistem çağrısı :

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
{
    return sys_mkdirat(AT_FDCWD, pathname, mode);
}

Tamam, sys_mkdiratdemek ki bu mkdiratsistem, yani üzerine tıklamak yalnızca sizi bildirime yönlendirir include/linux/syscalls.h, ancak tanım hemen yukarıdadır.

Ana iş mkdiratçağırmaktır vfs_mkdir(VFS jenerik dosya sistemi katmanıdır). Bunun üzerine iki arama sonucu gelir: içindeki beyan include/linux/fs.hve yukarıdaki birkaç satırın tanımı. Ana iş vfs_mkdirdosya sistemi özgü uygulama çağırmaktır; dir->i_op->mkdir. Nasıl bulmak için bu uygulanmaktadır, tek tek dosya sisteminin uygulanmasına çevirmek gerekiyor ve hiçbir sert ve hızlı-kural var - hatta çekirdek ağacının dışında bir modül olabilir.

¹ LXR bir endeksleme programıdır. Birkaç farklı bilinen sürüm kümesi ve biraz farklı web arayüzü olan LXR'ye bir arayüz sağlayan birkaç web sitesi vardır. Gelip gitme eğilimindedirler, bu yüzden alışkın olduğunuz kişi mevcut değilse, başka bir tane bulmak için “linux çapraz referansı” için bir web araması yapın.


Bu bir kaynağın heck. Mükemmel cevap.
Stabledog

Linux.no bağlantısında "Dahili Sunucu Hatası" .
Fredrick Gauss

@FredrickGauss Bir süredir lxr.linux.no, LXR'nin en güzel arayüzüydü, ancak sık sık çalışmama süresi vardı. Şimdi bence iyi gitti. İlk bağlantıyı başka bir LXR arayüzüne değiştirdim.
Gilles

21

Sistem çağrıları genellikle SYSCALL_DEFINEx()makroya sarılır , bu yüzden basit bir dosya grepbulamaz:

fs/namei.c:SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)

Makro genişletildikten sonra son fonksiyon ismi biter sys_mkdir. SYSCALL_DEFINEx()Makro her syscall tanım olması gerekir kod izleme gibi klişe şeyler ekler.


17

Not: .h dosyası işlevi tanımlamaz . Bu .h dosyasında ilan edildi ve başka bir yerde tanımlandı (uygulandı). Bu, derleyicinin, argümanların tür denetlenmesine izin vermek ve geri dönüş türlerini kodunuzdaki arama bağlamlarıyla eşleştirmek için işlevin imzası (prototip) hakkında bilgi içermesini sağlar.

Genel olarak, C'deki .h (başlık) dosyaları, işlevleri bildirmek ve makroları tanımlamak için kullanılır.

mkdirözellikle bir sistem çağrısıdır. Bu sistem çağrısının etrafında bir GNU libc sargısı olabilir (aslında kesinlikle, kesinlikle). Bunun gerçek çekirdek uygulaması mkdir, çekirdek kaynaklarını arayarak ve özellikle sistem çağrılarıyla bulunabilir.

Her dosya sistemi için bir tür dizin oluşturma kodu uygulaması olacağını da unutmayın. VFS (sanal dosya sistemi) katmanı, sistem çağrı katmanının arayabileceği ortak bir API sağlar. Her dosya sistemi, aranacak VFS katmanının işlevlerini kaydetmelidir. Bu, farklı dosya sistemlerinin dizinlerin nasıl yapılandırıldığına dair kendi semantiklerini uygulamalarına izin verir (örneğin, belirli girdileri aramayı daha verimli hale getirmek için bir tür karma düzeni kullanarak depolanırlarsa). Linux çekirdeği kaynak ağacında arama yapıyorsanız, bu dosya sistemine özgü dizin oluşturma işlevlerini açmanızın muhtemel olduğu için bunu söylüyorum.


8

Bulduğunuz uygulamaların hiçbiri sys / stat.h'deki prototip ile eşleşmiyor Belki de bu başlık dosyasında bir include ifadesi aramak daha başarılı olabilir mi?


1
Uygulama (sys / stat.h'de açıklandığı gibi), userland ve libc'nin işidir. Çekirdek iç işleri ( gerçekte nasıl yapıldığı) çekirdek iç işleridir. Tüm çekirdek bilgisayar korsanlarının bakımı için, iç işlev xyzzy olarak adlandırılabilir ve 5 parametre alabilir. Kullanıcı aramasını almak, gereken çekirdeğe ihtiyaç duyulan her şeye çevirmek, göndermek ve sonuçları toplamak libc'nin işidir.
vonbrand

6

Burada, düşük seviyeli çekirdek kaynak kodunu bulmak için çeşitli teknikleri anlatan birkaç harika blog yazısı var.


12
Lütfen yalnızca bloglara veya forumlara bağlantılar yayınlamayın, içeriklerini özetleyin, böylece okuyucular ne hakkında olduklarını görebilir ve siteler kaybolursa bir şeyler kaldı. Ayrıca, ilk bağlantınız bu soru için konu dışı olan libc ile ilgilidir.
Gilles
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.