it-swarm-tr.com

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

Bir işlevin mesela mkdir, çekirdek kaynağına bakarak nasıl çalıştığını anlamaya çalışıyorum. Bu, çekirdek iç kısımlarını anlama ve çeşitli işlevler arasında gezinme girişimidir. mkdir'ın 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);

Ama hiçbiri sys/stat.h.

Sorular

  1. Hangi dosya mkdir uygulamasına sahiptir?
  2. Yukarıdaki gibi bir işlev tanımıyla, hangi dosyanın uygulamaya sahip olduğunu nasıl bulabilirim? Çekirdeklerin tanımlama ve uygulama yöntemlerinde izlediği bir kalıp var mı?

NOT: Çekirdek kullanıyorum 2.6.36-rc1 .

376
Navaneeth K N

Sistem çağrıları normal işlev çağrıları gibi yapılmaz. Kullanıcı alanından çekirdek alanına geçiş yapmak için özel kod gerekir, temel olarak çağrı sitesinde programınıza enjekte edilen biraz satır içi Montaj kodu. Sistem çağrısını "yakalayan" çekirdek tarafı kodu, muhtemelen en azından ilk başta derinlemesine anlamanız gerekmeyen düşük seviyeli öğelerdir.

Çekirdek kaynak dizininizin altındaki include/linux/syscalls.h bölümünde şunu bulabilirsiniz:

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

Sonra /usr/include/asm*/unistd.h İçinde şunu bulabilirsiniz:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

Bu kod mkdir(2) sistem çağrısı # 83 diyor. Yani sistem çağrıları, kendi programınızdaki normal bir işlev çağrısında olduğu gibi veya programınıza bağlı bir kitaplıktaki bir işlevde olduğu gibi adrese göre değil, numaraya göre çağrılır. Yukarıda bahsettiğim satır içi Montaj tutkal kodu bunu, parametrelerinizle birlikte alarak kullanıcıdan çekirdek alanına geçiş yapmak için 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 listesinin olmamasıdır: Örneğin, open(2), 2 veya 3 parametre alabilir. Bu, open(2) 'nin C değil C++ özelliğinin aşırı yüklü olduğu, ancak syscall arabiriminin C uyumlu olduğu anlamına gelir. (Bu, C'nin varargs özelliği ile aynı şey değildir, bu da tek bir işlevin değişken sayıda argüman almasına izin verir.)

İlk sorunuzu cevaplamak için, mkdir() bulunan tek bir dosya yoktur. Linux birçok farklı dosya sistemini destekler ve her birinin kendi "mkdir" işlemi uygulaması vardır. Çekirdeğin tek bir sistem çağrısının arkasındaki her şeyi gizlemesine izin veren soyutlama katmanına [~ # ~] vfs [~ # ~] denir. Bu nedenle, muhtemelen vfs_mkdir() ile fs/namei.c 'Da kazmaya başlamak istersiniz. Düşük düzeyli dosya sistemi değiştirme kodunun gerçek uygulamaları başka yerlerdedir. Örneğin, ext4 uygulamasına fs/ext4/namei.c içinde tanımlanan ext4_mkdir() adı verilir.

İkinci sorunuza gelince, evet tüm bunların kalıpları vardır, ancak tek bir kural yoktur. Aslında ihtiyacınız olan şey, belirli bir sistem çağrısını nerede arayacağınızı anlamak için çekirdeğin nasıl çalıştığına dair oldukça geniş bir anlayıştır. Tüm sistem çağrıları VFS'yi içermez, bu nedenle çekirdek tarafı çağrı zincirlerinin tümü fs/namei.c İle başlamaz. Örneğin, mmap(2)mm/mmap.c içinde başlıyor, çünkü bu bellek yönetimi ("mm") alt sisteminin bir parçası çekirdek.

Bovet ve Cesati'nin " Linux Çekirdeğini Anlama " nin bir kopyasını almanızı öneririm.

388
Warren Young

Bu muhtemelen sorunuza doğrudan cevap vermiyor, ancak en basit Shell komutları için bile yapılan temel sistem çağrılarını anlamaya çalışırken strace'nin gerçekten havalı olduğunu gördüm. Örneğin.

strace -o trace.txt mkdir mynewdir

Sistem mkdir mynewdir görüntüleme keyfiniz için trace.txt dosyasına gönderilecektir.

86
Banjer

Linux çekirdek kaynağını okumak için iyi bir yer Linux çapraz referansı (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 grep'ten daha hızlıdır (ve daha hızlıdır).

LXR, önişlemci tanımlarını genişletmez. Sistem çağrılarının adları her yerde önişlemci tarafından yönetilir. Ancak, çoğu (tümü?) Sistem çağrıları SYSCALL_DEFINEx makro aileleri. mkdir iki bağımsız değişken aldığından, SYSCALL_DEFINE2(mkdir, mkdir syscall'ın beyanı ile sonuçlanır:

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

tamam, sys_mkdirat, mkdirat sistem çağrısı olduğu anlamına gelir, bu nedenle üzerine tıklamanız sizi include/linux/syscalls.h, ancak tanım biraz yukarıda.

mkdirat 'ın asıl işi vfs_mkdir (VFS, genel dosya sistemi katmanıdır). Bunun üzerine iki arama sonucu gösterilir: include/linux/fs.h ve tanım birkaç satır yukarıda. Ana işi vfs_mkdir, dosya sistemine özgü uygulamayı çağırmaktır: dir->i_op->mkdir. this nasıl uygulandığını bulmak için, tek tek dosya sisteminin uygulanmasına dönmeniz gerekir ve zor ve hızlı bir kural yoktur - çekirdek ağacının dışında bir modül bile olabilir.

¹ LXR bir indeksleme programıdır. Biraz farklı bilinen sürümler ve biraz farklı web arayüzleri ile 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 yoksa, başka bir tane bulmak için “linux çapraz referansı” için bir web araması yapın.

Sistem çağrıları genellikle SYSCALL_DEFINEx() makrosuna sarılır, bu nedenle basit bir grep bunları bulamaz:

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

Makro genişletildikten sonra son işlev adı sys_mkdir Olur. SYSCALL_DEFINEx() makrosu, her syscall tanımının sahip olması gereken izleme kodu gibi ortak öğeleri ekler.

22
stefanha

Not: .h dosyası tanımla işlevi gerçekleştirmez. Bu .h dosyasında bildirildi ve başka bir yerde tanımlandı (uygulandı). Bu, derleyicinin, argümanların tür denetlemesine izin vermek ve dönüş türlerini kodunuzdaki arama bağlamlarıyla eşleştirmek için işlevin imzası (prototip) hakkında bilgi içermesine olanak tanır.

Genel olarak C'deki .h (header) 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 sarmalayıcı olabilir (neredeyse kesinlikle, aslında). mkdir 'ın gerçek çekirdek uygulaması bulunabilir. özellikle çekirdek kaynaklarını ve sistem çağrılarını arayarak.

Ayrıca her dosya sistemi için bir tür dizin oluşturma kodu uygulaması olacağını unutmayın. VFS (sanal dosya sistemi) katmanı, sistem çağrı katmanının arayabileceği ortak bir API sağlar. Her dosya sistemi, VFS katmanının çağrılacağı işlevleri kaydetmelidir. Bu, farklı dosya sistemlerinin dizinlerin nasıl yapılandırıldığına ilişkin kendi semantiklerini uygulamalarına izin verir (örneğin, belirli girişleri aramayı daha verimli hale getirmek için bir çeşit karma şeması kullanılarak saklanırlarsa). Bundan bahsetmiştim çünkü Linux çekirdeği kaynak ağacında arama yapıyorsanız, bu dosya sistemine özgü dizin oluşturma fonksiyonlarının üzerinden geçeceksiniz.

17
Jim Dennis

Bulduğunuz uygulamaların hiçbiri sys/stat.h içindeki prototiple eşleşmiyor Belki de bu başlık dosyasıyla birlikte içerme ifadesi aramak daha başarılı olabilir mi?

8
greg0ire

İşte düşük seviyeli çekirdek kaynak kodunu avlamak için çeşitli teknikleri açıklayan birkaç harika blog yazısı.

6
An̲̳̳drew