Bölüm 15: Linux

İşletim Sistemleri
UNIX ve Linux tarihçesiTasarım hedefleri ve arayüzlerKabuk ve boru hatlarıÇekirdek yapısı ve modüllerSüreçler, sinyaller, iş parçacıklarıÇizelgeleme: CFS ve EEVDFÖnyükleme ve systemdBellek: sayfalama, bölgeler, SLUBG/Ç: aygıtlar, blk-mq, ağDosya sistemleri: VFS, ext4Güvenlik: izinler, konteynerlerAndroid
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Tarih ve aile

UNIX’ten BSD, MINIX, GNU ve Linux’a uzanan çizgiyi; dağıtımları ve Android’i konumlandırmak.

Arayüzler ve kabuk

Kütüphane / sistem çağrısı / çekirdek katmanlarını ayırmak; boru hatlarının fork, pipe, dup2 ile kurulduğunu göstermek.

Süreçler ve çizelgeleme

fork ve execve’nin çekirdekteki adımlarını, sinyal teslimini, task_struct, clone() bayraklarını ve NPTL’i; CFS’ten EEVDF’ye geçişte nelerin değiştiğini açıklamak.

Bellek

Adres alanı düzenini, 4/5 düzeyli sayfa tablolarını, bellek bölgelerini, SLUB ayırıcısını, sayfa önbelleğini ve OOM’u yorumlamak.

G/Ç ve dosyalar

Aygıt dosyaları, blk-mq, ağ yığını; VFS, i-node, ext4 extent ve günlükleme, bağlar ve /proc.

Güvenlik

rwx/setuid/umask hesaplamak; yetenekler, namespaces + cgroups, SELinux/AppArmor, seccomp ve Android korumalı alanını tanımak.

Giriş ve Tarihçe · Adım adım

UNIX’ten Linux’a Zaman Çizelgesi

1969–1983UNIX doğuyor1969UNIX, PDP-7 (Bell Labs)1971PDP-11’e taşındı1973C ile yeniden yazıldı1977BSD (Berkeley)1983System V, 4.2BSD1983GNU projesi1984–1993?1994–2010?2011–2026?

Ken Thompson ve Dennis Ritchie UNIX’i 1969’da PDP-7 üzerinde assembly ile yazdı; 1973’te C ile yeniden yazılması taşınabilirliği getirdi. AT&T kaynak kodunu üniversitelere verdi: Berkeley’den BSD doğdu.

1969–1983UNIX doğuyor1969UNIX, PDP-7 (Bell Labs)1971PDP-11’e taşındı1973C ile yeniden yazıldı1977BSD (Berkeley)1983System V, 4.2BSD1983GNU projesi1984–1993Özgür UNIX arayışı1987MINIX (Tanenbaum)1988POSIX standardı1989GPL lisansı1991Linux 0.01 (Torvalds)19920.12: GPL’ye geçiş1993Slackware, Debian1994–2010?2011–2026?

Ticari UNIX’ler (System V, SunOS, AIX…) birbirinden ayrışınca POSIX ortak arayüzü tanımladı. Tanenbaum öğretim için MINIX’i yazdı; Linus Torvalds 1991’de MINIX üzerinde kendi çekirdeğini geliştirdi ve GNU araçlarıyla birleştirdi.

1969–1983UNIX doğuyor1969UNIX, PDP-7 (Bell Labs)1971PDP-11’e taşındı1973C ile yeniden yazıldı1977BSD (Berkeley)1983System V, 4.2BSD1983GNU projesi1984–1993Özgür UNIX arayışı1987MINIX (Tanenbaum)1988POSIX standardı1989GPL lisansı1991Linux 0.01 (Torvalds)19920.12: GPL’ye geçiş1993Slackware, Debian1994–2010Linux olgunlaşıyor1994Linux 1.019962.0: SMP desteği1999Red Hat halka arz20032.6 serisi2005git2008Android: HTC Dream2011–2026?

Linux 1.0 (1994), 2.0 ile çok işlemci, 2.6 ile kesilebilir çekirdek ve O(1)/CFS çizelgeleyicileri. 2005’te BitKeeper sorunu üzerine Torvalds git’i yazdı. İlk Android telefonu 2008’de çıktı.

1969–1983UNIX doğuyor1969UNIX, PDP-7 (Bell Labs)1971PDP-11’e taşındı1973C ile yeniden yazıldı1977BSD (Berkeley)1983System V, 4.2BSD1983GNU projesi1984–1993Özgür UNIX arayışı1987MINIX (Tanenbaum)1988POSIX standardı1989GPL lisansı1991Linux 0.01 (Torvalds)19920.12: GPL’ye geçiş1993Slackware, Debian1994–2010Linux olgunlaşıyor1994Linux 1.019962.0: SMP desteği1999Red Hat halka arz20032.6 serisi2005git2008Android: HTC Dream2011–2026Her yerde Linux20113.0 numarası2017Top500: %100 Linux20226.0; 6.1’de Rust20236.6: EEVDF20246.12: sched_ext, RT20266.x → 7.0 serisi

2017’den beri dünyanın en hızlı 500 süper bilgisayarının tamamı Linux çalıştırıyor. 6.x serisinde Rust desteği, EEVDF ve sched_ext geldi; numaralar yalnızca büyüdüğü için artar (6.19’un ardından 7.0).

Giriş ve Tarihçe

GNU, Linux ve Dağıtımlar

Uygulamalar: masaüstü, sunucu yazılımlarıPaket yöneticisi + depolar (apt, dnf, pacman)init sistemi: systemdGNU araçları + C kütüphanesi (glibc, musl)Linux çekirdeğidağıtım(distro)Android: Linux çekirdeği + Bionic libc,GNU araçları yok
AileÖrneklerPaket
DebianDebian, Ubuntu, Mint, Pardus.deb / apt
Red HatFedora, RHEL, Rocky, Alma.rpm / dnf
ArchArch, Manjaropacman
SUSEopenSUSE, SLESzypper
HafifAlpine (musl + BusyBox)apk

Sürüm modeli: ~9–10 haftada bir ana sürüm (2 haftalık birleştirme penceresi + rc1…rc7). Her yılın son sürümü LTS olur: 6.6, 6.12, 6.18…

“Linux” tam olarak yalnızca çekirdeğin adıdır; kullanıcıların kurduğu sistem bir dağıtımdır (GNU/Linux).

Giriş ve Tarihçe

Tasarım Hedefleri ve UNIX Felsefesi

Basit (simple)

Az sayıda, iyi tanımlı kavram: süreç, dosya, boru.

Şık (elegant)

Küçük, tek iş yapan araçlar birleştirilerek büyük iş yapılır.

Tutarlı (consistent)

“Her şey dosyadır”: disk, terminal, boru aynı read/write ile.

Güçlü (powerful)

Kabuk betikleri, boru hatları, düzenli ifadeler.

Esnek (flexible)

Metin akışları evrensel arayüz; araçlar birbirini bilmeden çalışır.

Programcı için

Sistemi programcılar programcılar için tasarladı: az “sihir”, sessiz başarı.

UNIX felsefesi (McIlroy): Her program tek bir işi iyi yapmalı ve başka programlarla birlikte çalışabilmelidir. Programlar metin akışlarını işlemelidir, çünkü metin evrensel arayüzdür.
/home/ali/not.txt/dev/tty1boru (pipe)soketfd → read() / write()

POSIX bu arayüzü standartlaştırır: aynı kaynak kod Linux, BSD ve macOS’ta derlenebilir.

Kabuk ve Arayüzler · Adım adım

Katmanlar ve Arayüzler: Bir printf’in Yolculuğu

KullanıcılarStandart yardımcı programlarkabuk, editör, derleyiciStandart kütüphane (glibc)printf, open, fork sarmalayıcılarıLinux çekirdeğisüreç, bellek, dosya, G/ÇDonanımCPU, bellek, diskler, terminalkullanıcı arayüzükütüphane arayüzüsistem çağrısı arayüzükullanıcı moduçekirdek modu1 · Uygulamaprintf("merhaba\n");glibc tamponuna yazar

Program printf çağırır. Bu henüz bir sistem çağrısı değildir: glibc metni kullanıcı alanındaki bir tampona yazar.

KullanıcılarStandart yardımcı programlarkabuk, editör, derleyiciStandart kütüphane (glibc)printf, open, fork sarmalayıcılarıLinux çekirdeğisüreç, bellek, dosya, G/ÇDonanımCPU, bellek, diskler, terminalkullanıcı arayüzükütüphane arayüzüsistem çağrısı arayüzükullanıcı moduçekirdek modu1 · Uygulamaprintf("merhaba\n");glibc tamponuna yazar2 · glibcwrite(1, buf, 8)rax ← 1 (write), syscall

Tampon boşaltılırken glibc’nin write() sarmalayıcısı çalışır: sistem çağrısı numarasını (x86-64’te write = 1) rax’a, argümanları yazmaçlara koyar ve syscall komutunu yürütür.

KullanıcılarStandart yardımcı programlarkabuk, editör, derleyiciStandart kütüphane (glibc)printf, open, fork sarmalayıcılarıLinux çekirdeğisüreç, bellek, dosya, G/ÇDonanımCPU, bellek, diskler, terminalkullanıcı arayüzükütüphane arayüzüsistem çağrısı arayüzükullanıcı moduçekirdek modu1 · Uygulamaprintf("merhaba\n");glibc tamponuna yazar2 · glibcwrite(1, buf, 8)rax ← 1 (write), syscall3 · Çekirdek girişientry_SYSCALL_64sys_call_table[1] → vfs_write

CPU çekirdek moduna geçer. Giriş kodu numarayla sys_call_table’dan işleyiciyi seçer; VFS dosya tanımlayıcısı 1’in arkasındaki nesneyi bulur.

KullanıcılarStandart yardımcı programlarkabuk, editör, derleyiciStandart kütüphane (glibc)printf, open, fork sarmalayıcılarıLinux çekirdeğisüreç, bellek, dosya, G/ÇDonanımCPU, bellek, diskler, terminalkullanıcı arayüzükütüphane arayüzüsistem çağrısı arayüzükullanıcı moduçekirdek modu1 · Uygulamaprintf("merhaba\n");glibc tamponuna yazar2 · glibcwrite(1, buf, 8)rax ← 1 (write), syscall3 · Çekirdek girişientry_SYSCALL_64sys_call_table[1] → vfs_write4 · Sürücüpty/tty sürücüsüterminal ekrana basar

fd 1 bir sözde terminale (pty) bağlıdır; tty katmanı veriyi terminal öykünücüsüne iletir. Disk olsaydı yol sayfa önbelleğine ve blok katmanına giderdi.

KullanıcılarStandart yardımcı programlarkabuk, editör, derleyiciStandart kütüphane (glibc)printf, open, fork sarmalayıcılarıLinux çekirdeğisüreç, bellek, dosya, G/ÇDonanımCPU, bellek, diskler, terminalkullanıcı arayüzükütüphane arayüzüsistem çağrısı arayüzükullanıcı moduçekirdek modu1 · Uygulamaprintf("merhaba\n");glibc tamponuna yazar2 · glibcwrite(1, buf, 8)rax ← 1 (write), syscall3 · Çekirdek girişientry_SYSCALL_64sys_call_table[1] → vfs_write4 · Sürücüpty/tty sürücüsüterminal ekrana basar5 · Dönüşrax ← 8 (yazılan bayt)sysret → kullanıcı modu

Dönüş değeri rax’ta (8 bayt) döner, sysret ile kullanıcı moduna dönülür. Hata olursa negatif değer glibc’de errno’ya çevrilir ve −1 döner.

Kabuk ve Arayüzler

Temel Komutlar ve Yönlendirme

KategoriKomutlarNot
Dosya / dizinls cd pwd mkdir rm -r cp mv touch find tartouch zaman damgasını günceller; dosya yoksa boş dosya oluşturur
Metin (filtre)cat less head tail grep sort uniq wc echostdin’den okur, stdout’a yazar: boru hattında birleşir
Süreç / sistemps top kill chmod chown df du syncsync kirli tamponları diske yazar (makineler arası eşitleme: rsync)
Ağssh scp ping curl wget tracerouteip addr, ip route, ss, nft; eski ifconfig, route, netstat, iptables’ın yerini aldı
Bilgiman uname free lsblk/proc komut değil, sözde dosya sistemidir: cat /proc/meminfo
# yönlendirme: 0 = stdin, 1 = stdout, 2 = stderr
sort < girdi.txt > cikti.txt 2> hatalar.log   # < okur, > yazar (üzerine)
echo "satır" >> gunluk.txt                  # >> sona ekler
make 2>&1 | tee derleme.log &              # stderr→stdout, boru, arka plan
sort’un tanımlayıcı tablosu (kabuk exec’ten önce kurar):0 stdingirdi.txt1 stdoutcikti.txt2 stderrhatalar.log

Kabuk ve Arayüzler · Adım adım

Boru Hattı: Veri Aşamalardan Akar

cat log.txtPID 2101|çıktı (stdout)grep hataPID 2102|çıktı (stdout)sortPID 2103|çıktı (stdout)uniq -cPID 2104çıktı (stdout)kabuk: 3 boru + 4 çocuk süreç (fork + exec), hepsi eş zamanlı

Kabuk satırı ayrıştırır, 3 boru ve 4 süreç oluşturur. Süreçler aynı anda çalışır; her biri yalnızca kendi stdin/stdout’unu bilir.

cat log.txtPID 2101|çıktı (stdout)hata: diskbilgi: açılışhata: ağhata: diskuyarı: ısıhata: ağhata: diskgrep hataPID 2102|çıktı (stdout)sortPID 2103|çıktı (stdout)uniq -cPID 2104çıktı (stdout)

cat dosyanın 7 satırını boruya yazar. Boru tamponu (varsayılan 64 KiB) dolarsa yazan süreç bloke olur: üretici–tüketici.

cat log.txtPID 2101|çıktı (stdout)hata: diskbilgi: açılışhata: ağhata: diskuyarı: ısıhata: ağhata: diskgrep hataPID 2102|çıktı (stdout)hata: diskhata: ağhata: diskhata: ağhata: disksortPID 2103|çıktı (stdout)uniq -cPID 2104çıktı (stdout)

grep satır satır okur, eşleşen 5 satırı hemen iletir. Filtre durumsuzdur, akışı bekletmez.

cat log.txtPID 2101|çıktı (stdout)hata: diskbilgi: açılışhata: ağhata: diskuyarı: ısıhata: ağhata: diskgrep hataPID 2102|çıktı (stdout)hata: diskhata: ağhata: diskhata: ağhata: disksortPID 2103|çıktı (stdout)hata: ağhata: ağhata: diskhata: diskhata: diskuniq -cPID 2104çıktı (stdout)

sort ise tüm girdiyi (EOF’a kadar) okumadan çıktı veremez: son satır ilk sırayı değiştirebilir.

cat log.txtPID 2101|çıktı (stdout)hata: diskbilgi: açılışhata: ağhata: diskuyarı: ısıhata: ağhata: diskgrep hataPID 2102|çıktı (stdout)hata: diskhata: ağhata: diskhata: ağhata: disksortPID 2103|çıktı (stdout)hata: ağhata: ağhata: diskhata: diskhata: diskuniq -cPID 2104çıktı (stdout) 2 hata: ağ 3 hata: diskterminal

uniq -c yalnızca ardışık tekrarları sayar; bu yüzden önce sort gerekir. Sonuç: 2 × “hata: ağ”, 3 × “hata: disk”.

Kabuk ve Arayüzler · Kodu adım adım çalıştır

Kabuk Bir Boru Hattını Nasıl Kurar?

int fd[2];
pipe(fd);              /* 3: okuma, 4: yazma */
if (fork() == 0) {    /* çocuk 1 */
    dup2(fd[1], 1);
    close(fd[0]); close(fd[1]);
    execlp("ls", "ls", NULL);
}
if (fork() == 0) {    /* çocuk 2 */
    dup2(fd[0], 0);
    close(fd[0]); close(fd[1]);
    execlp("wc", "wc", "-l", NULL);
}
/* kabuk: iki ucu da kapat */
close(fd[0]); close(fd[1]);
wait(NULL); wait(NULL);
kabuk0tty1tty2tty3boru-o4boru-yçocuk 101234çocuk 201234boru tamponuy →→ o

pipe() çekirdekte bir tampon ve iki uç oluşturur: en küçük boş numaralar 3 (okuma) ve 4 (yazma).

kabuk0tty1tty2tty3boru-o4boru-yçocuk 10tty1tty2tty3boru-o4boru-yçocuk 201234boru tamponuy →→ o

fork(): çocuk, tanımlayıcı tablosunun kopyasını alır; iki süreç aynı boruyu işaret eder.

kabuk0tty1tty2tty3boru-o4boru-yçocuk 10tty1boru-y2tty34çocuk 201234boru tamponuy →→ o

dup2(4, 1): stdout artık borunun yazma ucu. Fazla uçlar kapatılır.

kabuk0tty1tty2tty3boru-o4boru-yls0tty1boru-y2tty34çocuk 201234boru tamponuy →→ o

execlp görüntüyü ls ile değiştirir; tanımlayıcı tablosu korunur. ls hiçbir şey bilmeden boruya yazar.

kabuk0tty1tty2tty3boru-o4boru-yls0tty1boru-y2tty34wc0boru-o1tty2tty34boru tamponuy →→ o

İkinci çocuk stdin’ini borunun okuma ucuna bağlar ve wc -l olur.

kabuk0tty1tty2tty34ls0tty1boru-y2tty34wc0boru-o1tty2tty34boru tamponuy →→ o

Kabuk iki ucu da kapatır. Kapatmasaydı yazma ucu açık kalır, wc hiç EOF görmez ve sonsuza dek beklerdi. Sonra iki çocuğu bekler.

Çekirdek Yapısı

Linux Çekirdeğinin Yapısı

Sistem çağrılarıG/Ç bileşeniSanal dosya sistemi (VFS)TerminallerSatır disipliniKarakter aygıt sürücüleriSoketlerAğ protokolleriAğ aygıt sürücüleriDosya sistemleriGenel blok katmanıG/Ç çizelgeleyiciBlok aygıt sürücüleriBellek yönetimiSanal bellekSayfalama,sayfa değiştirmeSayfa önbelleğiSüreç yönetimiSinyal işlemeSüreç/iş parçacığıoluşturma, sonlanmaCPU çizelgelemeKesmelerDağıtıcı (dispatcher)

Üstte sistem çağrısı arayüzü, altta kesmeler ve dağıtıcı (bağlam değiştirme). Tüm bileşenler tek adres alanında çalışır: Linux monolitik bir çekirdektir. Klasik 4.4BSD çekirdeği de aynı üç bileşene ayrılıyordu.

Çekirdek Yapısı · Adım adım

Yüklenebilir Çekirdek Modülleri (LKM)

kullanıcı alanı# modprobe e1000emodules.dep: bağımlılıklarçekirdekfinit_module()imza denetimiyer değiştirmesembol bağlamamodule_init()sürücü kaydıPCI aygıtı eşleşir → probe()çekirdek sembol tablosuEXPORT_SYMBOL ile dışa açılanlareth0 arayüzü hazır

Monolitik ama modüler: sürücülerin çoğu yüklenebilir çekirdek modülüdür (.ko). Yönetici modprobe ile ister ya da udev aygıt görününce otomatik yükler.

kullanıcı alanı# modprobe e1000emodules.dep: bağımlılıklarçekirdekfinit_module()imza denetimiyer değiştirmesembol bağlamamodule_init()sürücü kaydıPCI aygıtı eşleşir → probe()çekirdek sembol tablosuEXPORT_SYMBOL ile dışa açılanlareth0 arayüzü hazır

modprobe, /lib/modules/$(uname -r)/modules.dep dosyasından bağımlılıkları bulur ve önce onları yükler (insmod bunu yapmaz).

kullanıcı alanı# modprobe e1000emodules.dep: bağımlılıklarçekirdekfinit_module()imza denetimiyer değiştirmesembol bağlamamodule_init()sürücü kaydıPCI aygıtı eşleşir → probe()çekirdek sembol tablosuEXPORT_SYMBOL ile dışa açılanlareth0 arayüzü hazır

finit_module() sistem çağrısı modülü çekirdeğe kopyalar; Secure Boot açıkken imzası doğrulanır. CAP_SYS_MODULE yeteneği gerekir.

kullanıcı alanı# modprobe e1000emodules.dep: bağımlılıklarçekirdekfinit_module()imza denetimiyer değiştirmesembol bağlamamodule_init()sürücü kaydıPCI aygıtı eşleşir → probe()çekirdek sembol tablosuEXPORT_SYMBOL ile dışa açılanlareth0 arayüzü hazır

Çekirdek modülün yer değiştirmelerini yapar ve kullandığı sembolleri EXPORT_SYMBOL ile dışa açılmış çekirdek fonksiyonlarına bağlar.

kullanıcı alanı# modprobe e1000emodules.dep: bağımlılıklarçekirdekfinit_module()imza denetimiyer değiştirmesembol bağlamamodule_init()sürücü kaydıPCI aygıtı eşleşir → probe()çekirdek sembol tablosuEXPORT_SYMBOL ile dışa açılanlareth0 arayüzü hazır

module_init fonksiyonu çalışır: sürücü kendini PCI alt sistemine kaydeder (pci_register_driver).

kullanıcı alanı# modprobe e1000emodules.dep: bağımlılıklarçekirdekfinit_module()imza denetimiyer değiştirmesembol bağlamamodule_init()sürücü kaydıPCI aygıtı eşleşir → probe()çekirdek sembol tablosuEXPORT_SYMBOL ile dışa açılanlareth0 arayüzü hazır

Eşleşen aygıt için probe() çağrılır, ağ arayüzü oluşur. lsmod listeler, rmmod kaldırır. Modül çekirdek ayrıcalığıyla çalışır: hatası tüm sistemi çökertebilir.

Kaynak ağacı ~40 milyon satır; büyük kısmı sürücüler. 6.1’den beri çekirdekte Rust desteği var, ilk Rust sürücüsü 6.8’de girdi; eBPF güvenli, doğrulanmış küçük programları çekirdekte çalıştırır.

Süreçler

fork ve exec Çekirdekte Ne Yapar?

shPID 501shPID 748lsPID 7481. fork() → yeni süreç2. execve() → aynı süreçkopya: aynı programgörüntü ls ile değişir

fork() çekirdekte

  • Yeni task_struct ayır, ebeveynden doldur, yeni PID ata
  • Çekirdek yığını ayır; yazmaçları kopyala (çocukta dönüş değeri 0)
  • Sayfa tablolarını kopyala, yazılabilir sayfaları salt okunur işaretle (COW)
  • Açık dosyaları paylaş: struct file referans sayısı artar
  • Sinyal işleyicileri, cwd, kimlik bilgileri kopyalanır

execve() çekirdekte

  • ELF başlığı okunur; eski mm_struct bırakılır, yenisi kurulur ve segmentler mmap edilir
  • setuid/setgid bitine göre yeni cred hazırlanır
  • PC ← ld.so (dinamik bağlayıcı) ya da programın giriş noktası
  • Başarısız execve −1 döner; çocuk geleneksel olarak _exit(127) ile çıkar

Eski UNIX fork’ta veri ve yığını gerçekten kopyalardı; Linux yalnızca sayfa tablolarını kopyalar (COW). Çoğu fork’u hemen exec izlediği için kopyalanan sayfa sayısı çok azdır.

Süreçler

POSIX Sinyalleri

Sinyal, bir sürece olay bildiren yazılım kesmesidir. Senkron (SIGSEGV, SIGFPE: sürecin kendi komutu) ya da eş zamansız (SIGINT, SIGTERM: dışarıdan) olabilir. Süreç her sinyal için varsayılan eylemi, yok saymayı ya da bir işleyici (kaynak temizleme, günlük yazma) seçebilir.

SinyalNoNe zaman üretilir?Varsayılan
SIGHUP1Terminal bağlantısı koptu; cinlerde “yapılandırmayı yeniden oku”sonlandır
SIGINT2Ctrl-C (ön plan süreç grubuna)sonlandır
SIGQUIT3Ctrl-\çekirdek dökümü
SIGILL4Geçersiz makine komutuçekirdek dökümü
SIGABRT6abort(): süreç kendini anormal sonlandırırçekirdek dökümü
SIGFPE8Tamsayı sıfıra bölme gibi aritmetik hataçekirdek dökümü
SIGKILL9kill -9; yakalanamaz, yok sayılamazsonlandır
SIGSEGV11Geçersiz bellek erişimiçekirdek dökümü
SIGPIPE13Okuyanı kalmamış boruya yazmasonlandır
SIGALRM14alarm() süresi doldusonlandır
SIGTERM15kill komutunun varsayılanı; nazik sonlandırma isteğisonlandır
SIGUSR1/210/12Kullanıcı tanımlısonlandır
SIGCHLD17Çocuk süreç bitti/durduyok say
SIGSTOP / SIGCONT19/18Durdur (yakalanamaz) / devam ettir; Ctrl-Z → SIGTSTPdurdur / sürdür

Numaralar x86/ARM Linux içindir. SIGKILL ve SIGTERM’in ikisi de kill komutuyla gönderilebilir; fark yakalanabilirlikte.

Süreçler · Adım adım

Sinyal Teslimi

kullanıcı moduçekirdek modumain() döngüsükesildiği yer: PC = 0x401a2chandler(SIGINT)bayrak = 1; return;rt_sigreturntrampolin: sistem çağrısıtty sürücüsüCtrl-C → SIGINTtask_structbekleyen: 2 · maske: boşsinyal çerçevesiyazmaçlar kullanıcı yığınına

Kullanıcı Ctrl-C’ye basar: tty satır disiplini ön plan süreç grubuna SIGINT üretir. Çekirdek yalnızca hedef görevin bekleyen sinyal kümesinde 2. biti açar.

kullanıcı moduçekirdek modumain() döngüsükesildiği yer: PC = 0x401a2chandler(SIGINT)bayrak = 1; return;rt_sigreturntrampolin: sistem çağrısıtty sürücüsüCtrl-C → SIGINTtask_structbekleyen: 2 · maske: boşsinyal çerçevesiyazmaçlar kullanıcı yığınınaçekirdekten dönüşte denetim

Sinyal hemen işlenmez. Süreç bir sistem çağrısından ya da kesmeden kullanıcı moduna dönerken çekirdek “bekleyen ve maskelenmemiş” sinyal var mı diye bakar.

kullanıcı moduçekirdek modumain() döngüsükesildiği yer: PC = 0x401a2chandler(SIGINT)bayrak = 1; return;rt_sigreturntrampolin: sistem çağrısıtty sürücüsüCtrl-C → SIGINTtask_structbekleyen: 2 · maske: boşsinyal çerçevesiyazmaçlar kullanıcı yığınına

sigaction ile işleyici kurulmuşsa çekirdek kullanıcı yığınına bir sinyal çerçevesi (kaydedilmiş yazmaçlar + dönüş trampolini) yazar ve PC’yi işleyiciye ayarlar.

kullanıcı moduçekirdek modumain() döngüsükesildiği yer: PC = 0x401a2chandler(SIGINT)bayrak = 1; return;rt_sigreturntrampolin: sistem çağrısıtty sürücüsüCtrl-C → SIGINTtask_structbekleyen: 2 · maske: boşsinyal çerçevesiyazmaçlar kullanıcı yığınınayalnızca async-signal-safe çağrılar

İşleyici kullanıcı modunda çalışır. İçinde yalnızca async-signal-safe fonksiyonlar (ör. write, bir volatile sig_atomic_t bayrağı) güvenlidir; printf, malloc değil.

kullanıcı moduçekirdek modumain() döngüsükesildiği yer: PC = 0x401a2chandler(SIGINT)bayrak = 1; return;rt_sigreturntrampolin: sistem çağrısıtty sürücüsüCtrl-C → SIGINTtask_structbekleyen: 2 · maske: boşsinyal çerçevesiyazmaçlar kullanıcı yığınına

İşleyici dönünce trampolin rt_sigreturn sistem çağrısını yapar: çekirdek çerçevedeki yazmaçları geri yükler. (sigreturn işleyiciye girmez, işleyiciden döner.)

kullanıcı moduçekirdek modumain() döngüsükesildiği yer: PC = 0x401a2chandler(SIGINT)bayrak = 1; return;rt_sigreturntrampolin: sistem çağrısıtty sürücüsüCtrl-C → SIGINTtask_structbekleyen: 2 · maske: boşsinyal çerçevesiyazmaçlar kullanıcı yığınınabağlam geri yüklendi, kaldığı yerden devam

Süreç kesildiği komuttan devam eder. İşleyici yoksa varsayılan eylem uygulanırdı: SIGINT için sonlandırma.

Süreçler · Kodu adım adım çalıştır

Bekleyen Sinyalleri Seçme: Kod İzleme

/* kullanıcı moduna dönerken (çekirdek) */
void sinyal_bak(task *t) {
    unsigned long h = t->bekl & ~t->engl;
    while (h) {
        int sig = __builtin_ctzl(h) + 1;
        t->bekl &= ~(1UL << (sig - 1));
        teslim_et(t, sig); /* işleyici/varsayılan */
        h = t->bekl & ~t->engl;
    }
}
/* önce:  sigprocmask(SIG_BLOCK, {SIGINT}) */
/* sonra: sigprocmask(SIG_UNBLOCK, {SIGINT}) */
1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDSIGINT engellendi

Süreç kritik bir bölüme girmeden SIGINT’i sigprocmask ile engelledi (engelli kümesinde 2. bit). Sinyaller her görevde bir bit kümesidir.

1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDCtrl-C, kill -USR1, çocuk bitti

Süreç uyurken üç sinyal gelir: Ctrl-C (2), kill -USR1 (10) ve bir çocuğun bitişi (17). Çekirdek yalnızca bekleyen kümesinde bitleri açar; hiçbir şey hemen çalışmaz.

1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDhazır = bekleyen & ~engelli = {10, 17}

Süreç kullanıcı moduna dönerken çekirdek bakar: hazır = bekleyen & ~engelli. SIGINT bekliyor ama engelli; teslime hazır olanlar 10 ve 17.

1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDSIGUSR1 → işleyici çalışır

En küçük numaralı hazır bit (ctz): 10. Bekleyenden silinir ve teslim edilir: SIGUSR1 → işleyici çalışır. Hazır küme yeniden hesaplanır.

1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDSIGCHLD → varsayılan: yok say

En küçük numaralı hazır bit (ctz): 17. Bekleyenden silinir ve teslim edilir: SIGCHLD → varsayılan: yok say. Hazır küme yeniden hesaplanır.

1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDhazır boş: döngü biter, SIGINT bekliyor

Hazır küme boş, döngü biter ve süreç kullanıcı modunda sürer. SIGINT kaybolmadı: bekleyen kümesinde duruyor.

1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDengel kalktı: hazır = {2}

Kritik bölüm bitti, SIGINT’in engeli kaldırıldı. sigprocmask’tan dönüşte aynı denetim yapılır: hazır = {2}.

1234567891011121314151617bekleyenengellihazır2 SIGINT · 10 SIGUSR1 · 17 SIGCHLDSIGINT → varsayılan: sonlandır

SIGINT teslim edilir; işleyici kurulmadığı için varsayılan eylem: süreç sonlanır. Engellemek sinyali ertelemek demektir, yok saymak değil. Aynı sinyal birden çok gelseydi tek bit olarak birleşirdi.

Süreçler

Süreç Yönetimi Sistem Çağrıları

Sistem çağrısıAçıklama
fork()Süreci kopyalayarak yeni süreç oluşturur (COW)
clone(), clone3()Neyin paylaşılacağı bayraklarla seçilen yeni görev (iş parçacığı, konteyner)
execve()Mevcut süreç görüntüsünü yeni programla değiştirir
waitpid()Çocuğun bitmesini bekler, çıkış durumunu alır (zombiyi toplar)
exit() / _exit()Çağıran süreci sonlandırır (exit stdio tamponlarını boşaltır)
kill()Sürece sinyal gönderir; sinyal sonlandırma olmak zorunda değil
sigaction()Bir sinyal için işleyici ya da eylem atar
sigprocmask()Sinyal maskesini (bloke edilen sinyaller) okur/değiştirir
sigpending()Bloke olduğu için bekleyen sinyalleri döndürür
sigsuspend()Maskeyi geçici değiştirir ve bir sinyal gelene kadar uyur
rt_sigreturn()İşleyiciden dönüşte kaydedilmiş bağlamı geri yükler
alarm() / pause()n saniye sonra SIGALRM / bir sinyal gelene kadar uyu
fork()kopya, COWexecve()yeni programçalışırsinyaller, G/Çexit()kaynaklar bırakılırzombi (Z)durum bekliyorwaitpid()ebeveyn toplarkill()/sigaction() ile sinyal, alarm()/pause() ile zamanlama her aşamada araya girebilir

Sistem çağrısı, kullanıcı programının çekirdekten hizmet istemesinin tek yoludur; Linux x86-64’te ~460 tane vardır. Süreç ağacı pstree -p ya da ps -ef --forest ile görülür.

Süreçler

Süreç Tanımlayıcısı: task_struct

struct task_struct__state (R, S, D…)pid, tgidprio, policyse: vruntime, deadlinemmfilesfssighand, signalcrednsproxycgroupsparent, childrenmm_structVMA’lar, pgd (sayfa tablosu)files_structfd dizisi → struct filefs_structkök dizin, cwd, umasksighand_structsinyal işleyicilericreduid, gid, yeteneklernsproxypid, net, mnt… ad alanlarıcss_setcgroup sınırlarısched_entityEEVDF ağacındaki düğümiş parçacıkları bunları paylaşabilirher görev: ayrı çekirdek yığını

Linux’ta süreç ile iş parçacığı arasında yapısal fark yoktur: ikisi de bir görev (task_struct). Fark, hangi alt yapıları paylaştıklarıdır. Kullanıcının gördüğü PID aslında tgid’dir (iş parçacığı grubu kimliği). __state D (kesilemez uyku) iken görev SIGKILL ile bile hemen ölmez; bu yüzden çoğu bekleme artık TASK_KILLABLE kullanır.

Süreçler · Adım adım

clone() ve İş Parçacıkları

fork() = clone(SIGCHLD)ebeveynPID 900, TGID 900çocukPID 901, TGID 901mm (adres alanı)mm (adres alanı)files (açık dosyalar)files (açık dosyalar)fs (kök, cwd)fs (kök, cwd)sighand (işleyiciler)sighand (işleyiciler)nsproxy (ad alanları)nsproxy (ad alanları)kopya (COW): ayrı ama başta aynı

fork() glibc’de yalnız SIGCHLD bayrağıyla çağrılan bir clone()’dur: çocuk her yapının kopyasını alır (bellek COW ile). Ayrı PID, ayrı TGID: yeni bir süreç.

pthread_create()ebeveynPID 900, TGID 900iş parçacığıTID 902, TGID 900mm (adres alanı)files (açık dosyalar)fs (kök, cwd)sighand (işleyiciler)nsproxy (ad alanları)tümü paylaşılır: aynı adres alanı

pthread_create() → clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | …). Hepsi paylaşılır; yeni görev aynı TGID’e girer. NPTL: her iş parçacığı bir çekirdek görevi (1:1 model).

konteyner: clone(CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET …)ebeveynPID 900, TGID 900çocukPID 1 (içeride)mm (adres alanı)mm (adres alanı)files (açık dosyalar)files (açık dosyalar)fs (kök, cwd)fs (kök, cwd)sighand (işleyiciler)sighand (işleyiciler)nsproxy (ad alanları)yeni ad alanlarıkopya + yeni ad alanları

Ad alanı bayrakları (CLONE_NEWPID, CLONE_NEWNS, CLONE_NEWNET…) çocuğa yeni bir görünüm verir: içeride kendini PID 1 sanır. Konteynerlerin temeli budur.

Çizelgeleme ve Önyükleme

CFS’ten EEVDF’ye: Adil Paylaşım

SürümAdil sınıfın seçim kuralıVeri yapısı
2.4 (2001)O(n): her seçimde tüm hazır görevler taranırtek liste
2.6.0–2.6.22 (2003)O(1): öncelik başına liste, etkin ve süresi dolmuş iki dizi140 listelik dizi + biteşlem
2.6.23–6.5 (2007)CFS: en küçük vruntimekırmızı-siyah ağaç
6.6+ (2023)EEVDF: uygun görevler (v ≤ V) içinde en erken sanal son tarihaynı ağaç, alt ağaç bilgisiyle zenginleştirilmiş
  • Değişmeyenler: sched_entity içindeki vruntime, nice → ağırlık tablosu (sched_prio_to_weight, nice 0 → 1024) ve çalışma kuyruğundaki ağaç.
  • CFS’in gecikme ayarları (sched_latency, uyanma ayrıntı düzeyi) yerine tek bir temel dilim (base_slice_ns) kaldı; sanal son tarih d = v + dilim × 1024 / ağırlık.
  • Gecikmeye duyarlı görev sched_setattr() ile daha kısa dilim isteyebilir (6.12+): kısa dilim, erken son tarih ve daha sık seçilme demektir.

Çizelgeleme ve Önyükleme · Adım adım

Önyükleme: UEFI’den systemd’ye

UEFIürün yazılımıGRUB2 /systemd-bootÇekirdekvmlinuzinitramfsgeçici köksystemdPID 1Oturumgetty, gdm, sshd• POST, donanımı başlat• NVRAM’deki önyükleme girdisi• ESP (FAT32) bölümünden• EFI uygulamasını yükle• Secure Boot: imza denetimi (shim)

Güç verilince UEFI ürün yazılımı donanımı sınar ve ESP bölümündeki EFI uygulamasını yükler. Secure Boot açıksa her aşama bir sonrakinin imzasını doğrular.

UEFIürün yazılımıGRUB2 /systemd-bootÇekirdekvmlinuzinitramfsgeçici köksystemdPID 1Oturumgetty, gdm, sshd• menü, çekirdek seçimi• komut satırı: root=… quiet• vmlinuz + initramfs• dosyalarını belleğe yükle• çekirdeğe atla

Önyükleyici çekirdek görüntüsünü (vmlinuz) ve initramfs’i belleğe yükler, komut satırı parametrelerini verir. Çekirdek EFI uygulaması olarak doğrudan da başlatılabilir (UKI).

UEFIürün yazılımıGRUB2 /systemd-bootÇekirdekvmlinuzinitramfsgeçici köksystemdPID 1Oturumgetty, gdm, sshd• kendini aç, start_kernel()• bellek, kesmeler, zamanlayıcı• PID 0 → boşta görevi• kernel_init (PID 1)• kthreadd (PID 2)Linux başladı

Çekirdek kendini açar, start_kernel() bellek yönetimini, kesmeleri, çizelgeleyiciyi kurar. İlk görev PID 0 boşta görevi olur; kernel_init (PID 1) ve kthreadd (PID 2) oluşturulur.

UEFIürün yazılımıGRUB2 /systemd-bootÇekirdekvmlinuzinitramfsgeçici köksystemdPID 1Oturumgetty, gdm, sshd• RAM’de cpio arşivi• gerekli modüller: NVMe, LVM• LUKS şifre çözme• gerçek kökü bağla• switch_root → /sbin/initLinux başladı

Kök dosya sistemini bağlamak için gereken sürücüler çekirdekte olmayabilir (NVMe, RAID, şifreli disk). initramfs RAM’de geçici bir kök sağlar, gerçek kökü bağlar ve switch_root yapar.

UEFIürün yazılımıGRUB2 /systemd-bootÇekirdekvmlinuzinitramfsgeçici köksystemdPID 1Oturumgetty, gdm, sshd• birim (unit) dosyaları• bağımlılık grafiği• paralel başlatma• journald, udevd, ağ• default.targetLinux başladı

PID 1 artık systemd: birim dosyalarındaki bağımlılıklara göre hizmetleri paralel başlatır, hedefe (multi-user.target veya graphical.target) ulaşır.

UEFIürün yazılımıGRUB2 /systemd-bootÇekirdekvmlinuzinitramfsgeçici köksystemdPID 1Oturumgetty, gdm, sshd• agetty → login → bash• veya gdm grafik oturum• sshd uzaktan giriş• systemd --user• systemd-analyze: süreLinux başladı

Konsolda agetty → login → kabuk; masaüstünde gdm; uzaktan sshd. Klasik UNIX’teki init → getty → login → sh zinciri hâlâ tanınabilir.

Bellek Yönetimi

Sürecin Sanal Adres Alanı

Çekirdek alanıtüm süreçlerde aynı; kullanıcı modunda erişilemezkanonik olmayan delikbu adresler kullanılamazYığın (stack) ↓main, yerel değişkenler; ASLR ile rastgele başlangıçmmap bölgesi ↓libc.so, ld.so, eşlenmiş dosyalar, iş parçacığı yığınlarıÖbek (heap) ↑ brkmalloc’un küçük istekleri; brk ile büyürbsssıfırla başlatılan küresellerdatailk değerli küresellertext (kod)salt okunur + çalıştırılabilir; süreçler arasında paylaşılırNULL sayfası eşlenmez → SIGSEGVx86-64, 4 düzey (48 bit):kullanıcı 2⁴⁷ B = 128 TiBçekirdek 128 TiB5 düzey, LA57 (57 bit):kullanıcı 2⁵⁶ B = 64 PiBcat /proc/PID/maps

Her bölge bir VMA (vm_area_struct) ile tanımlanır; VMA’lar mm_struct içinde bir “maple tree”de tutulur. Yığın ve mmap aşağı, öbek yukarı büyür; aradaki boşluk yalnızca sanaldır, fiziksel bellek harcamaz.

Bellek Yönetimi

Paylaşım, Eşlenmiş Dosyalar ve Bellek Çağrıları

Süreç ASüreç BFiziksel bellektextsayfa önbelleğiveri Ayığın Averi Byığın Byığın Averi.db (eşl.)veri Atextyığın Bveri.db (eşl.)veri Btextyeşil oklar: paylaşılan çerçeveler
Çağrıİşlev
brk / sbrkÖbeğin (veri kesiminin) sonunu taşıyarak büyütür/küçültür
mmapDosyayı, aygıtı ya da anonim belleği adres alanına eşler
munmapEşlemeyi kaldırır, belleği sisteme geri verir
mprotectBölgenin izinlerini (r/w/x) değiştirir
madviseÇekirdeğe kullanım ipucu verir (ör. MADV_DONTNEED)
msyncPaylaşımlı eşlemenin kirli sayfalarını dosyaya yazar

MAP_SHARED: yazılanlar dosyaya ve diğer süreçlere görünür. MAP_PRIVATE: yazınca kopyala, dosya değişmez. glibc malloc küçük istekleri öbekten, ≥ 128 KiB istekleri doğrudan mmap ile karşılar.

Bellek Yönetimi · Adım adım

Sayfa Tablosu Yürüyüşü: 4 ve 5 Düzey

sanal adres 0x00007f3a1c2b5e88işaret = 0bit 63–48PGD = 254bit 47–39PUD = 232bit 38–30PMD = 225bit 29–21PTE = 181bit 20–12ofset = 0xe88bit 11–0CR3PGD tablosu512 girdi × 8 BPUD tablosu512 girdi × 8 BPMD tablosu512 girdi × 8 BPTE tablosu512 girdi × 8 B48 bitlik adres: 4 × 9 bit dizin + 12 bit ofset

x86-64’te 4 KiB sayfa → 12 bit ofset. Kalan 36 bit, her biri 512 girdilik (9 bit) dört tabloya bölünür. 63–48. bitler 47. bitin kopyasıdır (kanonik adres).

sanal adres 0x00007f3a1c2b5e88işaret = 0bit 63–48PGD = 254bit 47–39PUD = 232bit 38–30PMD = 225bit 29–21PTE = 181bit 20–12ofset = 0xe88bit 11–0CR3PGD tablosu512 girdi × 8 B[254]PUD tablosu512 girdi × 8 BPMD tablosu512 girdi × 8 BPTE tablosu512 girdi × 8 B

CR3 yazmacı sürecin en üst tablosunu (PGD) gösterir; bağlam değiştirmede CR3 değişir. Dizin 254 → PUD tablosunun adresi.

sanal adres 0x00007f3a1c2b5e88işaret = 0bit 63–48PGD = 254bit 47–39PUD = 232bit 38–30PMD = 225bit 29–21PTE = 181bit 20–12ofset = 0xe88bit 11–0CR3PGD tablosu512 girdi × 8 B[254]PUD tablosu512 girdi × 8 B[232]PMD tablosu512 girdi × 8 BPTE tablosu512 girdi × 8 B

PUD[232] bir PMD tablosunu gösterir. (Burada 1 GiB’lık dev sayfa da bitebilir.)

sanal adres 0x00007f3a1c2b5e88işaret = 0bit 63–48PGD = 254bit 47–39PUD = 232bit 38–30PMD = 225bit 29–21PTE = 181bit 20–12ofset = 0xe88bit 11–0CR3PGD tablosu512 girdi × 8 B[254]PUD tablosu512 girdi × 8 B[232]PMD tablosu512 girdi × 8 B[225]PTE tablosu512 girdi × 8 B

PMD[225] bir PTE tablosunu gösterir. (2 MiB’lık dev sayfa / THP burada biter.)

sanal adres 0x00007f3a1c2b5e88işaret = 0bit 63–48PGD = 254bit 47–39PUD = 232bit 38–30PMD = 225bit 29–21PTE = 181bit 20–12ofset = 0xe88bit 11–0CR3PGD tablosu512 girdi × 8 B[254]PUD tablosu512 girdi × 8 B[232]PMD tablosu512 girdi × 8 B[225]PTE tablosu512 girdi × 8 B[181]

PTE[181]: geçerli (present) biti, çerçeve numarası, R/W, U/S, NX, kirli (D) ve erişildi (A) bitleri. Present = 0 ise sayfa hatası.

sanal adres 0x00007f3a1c2b5e88işaret = 0bit 63–48PGD = 254bit 47–39PUD = 232bit 38–30PMD = 225bit 29–21PTE = 181bit 20–12ofset = 0xe88bit 11–0CR3PGD tablosu512 girdi × 8 B[254]PUD tablosu512 girdi × 8 B[232]PMD tablosu512 girdi × 8 B[225]PTE tablosu512 girdi × 8 B[181]4 KiB çerçeveçerçeve0x3c5a1+ 0xe88fiziksel adres = 0x3c5a1e88

Çerçeve numarası ofsetle birleşir: fiziksel adres = çerçeve × 4096 + ofset.

sanal adres 0x00007f3a1c2b5e88işaret = 0bit 63–48PGD = 254bit 47–39PUD = 232bit 38–30PMD = 225bit 29–21PTE = 181bit 20–12ofset = 0xe88bit 11–0CR3PGD tablosu512 girdi × 8 B[254]PUD tablosu512 girdi × 8 B[232]PMD tablosu512 girdi × 8 B[225]PTE tablosu512 girdi × 8 B[181]4 KiB çerçeveçerçeve0x3c5a1+ 0xe88fiziksel adres = 0x3c5a1e88TLB: sonraki erişimde 4 bellek okuması atlanır

Her erişimde 4 ek okuma pahalıdır: TLB çeviriyi önbelleğe alır. 5 düzeyli sayfalama (LA57, Linux 4.14+) araya P4D ekleyerek 57 bit adres sağlar. Linux’un genel modeli 5 düzeydir; donanım daha azını kullanıyorsa düzeyler katlanır.

Bellek Yönetimi

Fiziksel Belleğin Gösterimi

NUMA düğümü 0 (pglist_data)ZONE_DMA0–16 MiB (eski ISA)ZONE_DMA320–4 GiB (32 bit DMA)ZONE_NORMALgeri kalan RAMZONE_MOVABLEtaşınabilir sayfalarher bölgede:free_area[0…10] (buddy listeleri)LRU listeleri, su seviyelerimem_map: struct page dizisi70: boş80: boş150: eşlenmiş200: boşher 4 KiB sayfa için 64 B→ RAM’in %1,56’sıaddress_space (dosya)folio: ardışık sayfalarıtek birim olarak yönetir (5.16+)boş liste

Linux fiziksel belleği düğüm → bölge → sayfa hiyerarşisiyle tanımlar. Çok soketli makinede her CPU kendi düğümünden ayırmayı tercih eder (NUMA). 64 bit sistemlerde ZONE_HIGHMEM yoktur; yalnızca 32 bit çekirdeklerde kalmıştır. Her bölgenin free_area dizisi buddy ayırıcının order 0–10 (4 KiB–4 MiB) boş listelerini tutar; durum /proc/buddyinfo’da.

Bellek Yönetimi

SLUB Nesne Ayırıcısı

Buddy ayırıcı: sayfa çerçeveleri (alloc_pages)kmem_cache: task_structkmem_cache: dentry (192 B)kmem_cache: kmalloc-64kmem_cache: inode_cachedentry önbelleğinin içi:CPU 0 etkin slabkilitsiz hızlı yolkısmi (partial) slabboş nesnesi olanlardolu slabtamamen kullanılıyorslab = 1 veya birkaç ardışık sayfa

Çekirdek çok sayıda küçük, aynı boyda nesne (task_struct, dentry, inode) ayırır; her biri için sayfa ayırmak israftır. SLUB nesne önbellekleri tutar; kmalloc 8 B–8 KiB boy sınıflarını kullanır. SLOB (6.4) ve SLAB (6.8) kaldırıldı: tek ayırıcı SLUB. Büyük, fiziksel bitişik olması gerekmeyen alan için vmalloc.

Bellek Yönetimi · Kodu adım adım çalıştır

SLUB Serbest Listesi: Kod İzleme

void *slab_ayir(kmem_cache *c) {
    void *nesne = c->freelist;    /* listenin başı */
    if (!nesne)
        nesne = yeni_slab(c);     /* yavaş yol */
    c->freelist = *(void **)nesne;  /* sonraki */
    return nesne;
}
void slab_birak(kmem_cache *c, void *nesne) {
    *(void **)nesne = c->freelist;  /* nesnenin içine */
    c->freelist = nesne;
}
/* a,b = ayir; birak(a); c,d,e,f = ayir */
slab sayfası (4 KiB)+0boş+1024boş+2048boş+3072boşfreelist → +0 → +1024 → +2048 → +3072 → NULL

Yeni bir slab: 4 KiB’lık sayfa 1 KiB’lık dört nesneye bölünmüş. Boş nesneler bir listede; “sonraki” işaretçisi ayrı bir yapıda değil, boş nesnenin kendi içinde saklanır.

slab sayfası (4 KiB)+0a+1024boş+2048boş+3072boşfreelist → +1024 → +2048 → +3072 → NULLa = ayir()

slab_ayir: listenin başı (+0) alınır, freelist onun içindeki sonraki işaretçiye (+1024) ilerler. Kilit yok, sayfa ayırma yok: birkaç komut.

slab sayfası (4 KiB)+0a+1024b+2048boş+3072boşfreelist → +2048 → +3072 → NULLb = ayir()

b için +1024 verilir; freelist +2048’i gösterir.

slab sayfası (4 KiB)+0boş+1024b+2048boş+3072boşfreelist → +0 → +2048 → +3072 → NULLbirak(a)

a serbest bırakılır: nesnenin ilk 8 baytına eski baş (+2048) yazılır ve freelist +0 olur. Liste bir yığın gibi çalışır (son giren ilk çıkar).

slab sayfası (4 KiB)+0c+1024b+2048boş+3072boşfreelist → +2048 → +3072 → NULLc = ayir()

c, a’nın az önce bıraktığı +0’ı alır: büyük olasılıkla hâlâ CPU önbelleğinde olduğu için “sıcak” bir nesne.

slab sayfası (4 KiB)+0c+1024b+2048d+3072efreelist → NULLd, e = ayir()

d +2048’i, e +3072’yi alır. +3072’nin içindeki sonraki işaretçi NULL’dı: slab doldu, freelist boş.

slab sayfası (4 KiB)+0c+1024b+2048d+3072e2:+0f2:+1024boş2:+2048boş2:+3072boşfreelist → 2:+1024 → 2:+2048 → 2:+3072 → NULLf = ayir()

f için liste boş: yavaş yol. Sayfa ayırıcıdan (buddy) yeni bir sayfa alınır, dört nesneye bölünür, ilki f’ye verilir. Yaygın durum hızlı, nadir durum doğru.

Bellek Yönetimi · Adım adım

Sayfa Önbelleği, Geri Kazanım ve OOM

5 GiBanonim (uygulama)8 GiBsayfa önbelleğiboş 2 GiBRAM 16 GiBboş bellek2 GiByüksekdüşükmin(büyütülmüş)kswapd0arka planda geri kazanımMGLRU nesillerigen 0 (soğuk) … gen 3 (sıcak)zswap → takassoğuk anonim sayfalardoğrudan geri kazanımayıran süreç beklerOOM killeren yüksek oom_score → SIGKILLtakas: 0 GiBzswap + swap alanı

Boş bellek israftır: Linux kullanılmayan RAM’i sayfa önbelleği olarak dosya verisi için kullanır. free -h’deki “available” bu önbelleğin geri alınabilir kısmını da sayar.

8,3 GiBanonim (uygulama)6 GiBsayfa önbelleğiRAM 16 GiBboş bellek0,7 GiByüksekdüşükmin(büyütülmüş)kswapd0arka planda geri kazanımMGLRU nesillerigen 0 (soğuk) … gen 3 (sıcak)zswap → takassoğuk anonim sayfalardoğrudan geri kazanımayıran süreç beklerOOM killeren yüksek oom_score → SIGKILLtakas: 0 GiBzswap + swap alanı

Uygulama büyüdü, boş bellek düşük su seviyesinin altına indi: kswapd uyanır ve arka planda temiz önbellek sayfalarını bırakır (kirli olanlar önce diske yazılır).

9 GiBanonim (uygulama)4,7 GiBsayfa önbelleği1,3 GiBRAM 16 GiBboş bellek1,3 GiByüksekdüşükmin(büyütülmüş)kswapd0arka planda geri kazanımMGLRU nesillerigen 0 (soğuk) … gen 3 (sıcak)zswap → takassoğuk anonim sayfalardoğrudan geri kazanımayıran süreç beklerOOM killeren yüksek oom_score → SIGKILLtakas: 1 GiBzswap + swap alanı

MGLRU (6.1) sayfaları erişim nesillerine ayırır; en soğuk nesil önce gider. Soğuk anonim sayfaların dosyası yoktur: zswap ile RAM’de sıkıştırılır, gerekirse takas alanına yazılır.

11,5 GiBanonim (uygulama)3,2 GiBsayfa önbelleğiRAM 16 GiBboş bellek0,3 GiByüksekdüşükmin(büyütülmüş)kswapd0arka planda geri kazanımMGLRU nesillerigen 0 (soğuk) … gen 3 (sıcak)zswap → takassoğuk anonim sayfalardoğrudan geri kazanımayıran süreç beklerOOM killeren yüksek oom_score → SIGKILLtakas: 2 GiBzswap + swap alanı

Ayırma hızı geri kazanımı geçti, boş bellek min seviyesinin altında: ayıran süreç kendisi doğrudan geri kazanım yapar ve takılır (gecikme artar).

4,6 GiBanonim (uygulama)2 GiBboş 8,4 GiBRAM 16 GiBboş bellek8,4 GiByüksekdüşükmin(büyütülmüş)kswapd0arka planda geri kazanımMGLRU nesillerigen 0 (soğuk) … gen 3 (sıcak)zswap → takassoğuk anonim sayfalardoğrudan geri kazanımayıran süreç beklerOOM killeren yüksek oom_score → SIGKILLtakas: 2 GiBzswap + swap alanıbellek_yiyen (PID 7311)öldürüldü

Hiçbir şey yetmezse OOM killer en yüksek oom_score’lu (çoğunlukla en büyük) süreci SIGKILL ile öldürür; oom_score_adj ile etkilenebilir. cgroup sınırı aşılırsa yalnız o gruptan seçilir.

Giriş/Çıkış

Aygıtlar Dosyadır: Major ve Minor Numaralar

$ ls -l /dev     # seçilmiş satırlar
brw-rw---- 1 root disk   8, 0 sda
brw-rw---- 1 root disk   8, 1 sda1
brw-rw---- 1 root disk 259, 0 nvme0n1
crw-rw-rw- 1 root root   1, 3 null
crw-rw-rw- 1 root tty    5, 0 tty
  • c karakter aygıtı: bayt akışı, genelde önbelleksiz (terminal, /dev/null, fare)
  • b blok aygıtı: sabit boy bloklar, rastgele erişim; sayfa önbelleği ve G/Ç çizelgeleyici kullanır
  • Ağ arayüzleri (eth0) /dev’de yoktur; soketlerle kullanılır
  • Düğümleri devtmpfs + udev aygıt görününce dinamik oluşturur
open("/dev/sda1")i-node: tür bmajor 8, minor 1blok aygıt tablosu7 → loop8 → sd (SCSI disk)259 → blkext (NVMe)minor: 0 = tüm disk, 1 = bölüm 1disk başına 16 minor: sdb = 16

Boyut sütunu yerine “major, minor” görünür. Major sürücüyü, minor o sürücünün yönettiği birimi seçer. Uygulama diske de terminale de aynı open/read/write ile erişir.

Giriş/Çıkış

Linux G/Ç Sisteminin Yapısı

Sistem çağrıları: open, read, write, ioctl, mmap, send, recvVFS (sanal dosya sistemi)Soket katmanıKarakter aygıtlarıtty + satır disiplinikarakter sürücüsüBlok aygıtlarıext4 / XFS / Btrfssayfa önbelleğiblok katmanı: blk-mqG/Ç çizelgeleyiciblok sürücüsü (NVMe)Ağ aygıtlarıTCP / UDPIP + netfilterkuyruk disiplini (qdisc)ağ sürücüsü (NAPI)Donanım: terminal, NVMe SSD, ağ kartı

Üç aygıt türü üç ayrı yoldan iner. Klasik BSD’de de benzer ayrım vardı; System V’in STREAMS modül yığını ise Linux ana çekirdeğine hiç girmedi. Ağ yolunda veri sk_buff yapılarında taşınır; XDP/eBPF paketleri sürücü düzeyinde işleyebilir.

Giriş/Çıkış

Sürücü Arayüzü: file_operations ve Terminal

static const struct file_operations my_fops = {
    .owner          = THIS_MODULE,
    .open           = my_open,
    .release        = my_release,     /* close */
    .read           = my_read,
    .write          = my_write,
    .unlocked_ioctl = my_ioctl,
    .poll           = my_poll,
    .mmap           = my_mmap,
};
cdev_init(&cdev, &my_fops);  /* major:minor → fops */
Eski UNIX girişleriLinux karşılığı
k_open, tty_open, pr_open, ip_open.open
k_close, tty_close, pr_close….release
mem_read, k_read, tty_read.read
mem_write, tty_write, pr_write….write
k_ioctl, tty_ioctl, pr_ioctl….unlocked_ioctl
Terminal G/Ç (termios): tcgetattr/tcsetattr terminal parametrelerini okur/yazar: kanonik mod (satır düzenleme, ICANON) ya da ham mod, ECHO. cfset/cfget[io]speed giriş/çıkış baud hızı; bugün çoğunlukla seri portlar için, terminaller ise sözde terminaldir (pty).

Klasik ders kitabı tablosu her sürücü için ayrı giriş noktaları (k_*, tty_*, pr_*, ip_*) listeler; Linux bunları tek bir işlev işaretçisi yapısında toplar. VFS her read()’i ilgili sürücünün .read’ine yönlendirir.

Giriş/Çıkış

Blok Katmanı: blk-mq ve G/Ç Çizelgeleyiciler

Linux blok katmanı blk-mq çok kuyrukludur: her CPU kendi yazılım kuyruğuna yazar, istekler isteğe bağlı bir G/Ç çizelgeleyiciden (none, mq-deadline, bfq, kyber) geçip aygıtın donanım kuyruklarına dağıtılır. Etkin çizelgeleyici aygıt başına /sys/block/<aygıt>/queue/scheduler dosyasından okunur ve değiştirilir.

Giriş/Çıkış · Adım adım

Ağ: Soketler ve Bağlantı Kurulumu

Sunucuİstemcisocket() → fd 3bind(:80)listen(3, 128)accept() → fd 4read(4) / write(4)socket() → fd 3connect(sunucu:80)write(3) / read(3)close(3) → FIN

Sunucu bir soket oluşturur (fd 3), 80. porta bağlar (bind) ve listen ile dinleme kuyruğu açar. Soket de bir dosya tanımlayıcısıdır.

Sunucuİstemcisocket() → fd 3bind(:80)listen(3, 128)accept() → fd 4read(4) / write(4)socket() → fd 3connect(sunucu:80)write(3) / read(3)close(3) → FINaccept bloke: bağlantı bekliyor

Sunucu accept’te bloke olur. İstemci kendi soketini oluşturur.

Sunucuİstemcisocket() → fd 3bind(:80)listen(3, 128)accept() → fd 4read(4) / write(4)socket() → fd 3connect(sunucu:80)write(3) / read(3)close(3) → FINSYNSYN-ACKACK

connect çağrısıyla istemci çekirdeği üçlü el sıkışmayı (SYN, SYN-ACK, ACK) yapar; uygulama bu paketleri hiç görmez.

Sunucuİstemcisocket() → fd 3bind(:80)listen(3, 128)accept() → fd 4read(4) / write(4)socket() → fd 3connect(sunucu:80)write(3) / read(3)close(3) → FINSYNSYN-ACKACKçekirdek el sıkışmayı tamamladı,accept yeni bir soket döndürür

Bağlantı kurulunca accept yeni bir soket (fd 4) döndürür; fd 3 dinlemeye devam eder. Çok istemcili sunucular epoll veya iş parçacıklarıyla binlerce soketi yönetir.

Sunucuİstemcisocket() → fd 3bind(:80)listen(3, 128)accept() → fd 4read(4) / write(4)socket() → fd 3connect(sunucu:80)write(3) / read(3)close(3) → FINSYNSYN-ACKACKçekirdek el sıkışmayı tamamladı,accept yeni bir soket döndürürGET / HTTP/1.1200 OK …

Veri write/read ile akar: çekirdek sk_buff’lara koyar, TCP/IP başlıklarını ekler, sürücü kartın halkasına yazar. close FIN gönderir.

Dosya Sistemleri

Dizin Ağacı ve Bağlama

/binbootdevetchomelibprocsystmpusrvarmnt→ usr/bin→ usr/libsanalsanaldevtmpfsalibinlibshareusbvfat (USB)foto/ belge/mount /dev/sdb1 /mnt/usb
  • /usr/bin: komutlar (/bin artık ona bağlantı)
  • /etc: metin yapılandırma dosyaları
  • /dev: aygıt dosyaları
  • /usr/lib: paylaşımlı kütüphaneler, /usr/lib/modules: çekirdek modülleri
  • /usr: salt okunur, paylaşılabilir yazılım (bin, lib, share)
  • /home: kullanıcı dizinleri; /root: yöneticinin
  • /var: değişken veri (günlükler, kuyruklar, önbellek)
  • /proc, /sys: çekirdeğin sözde dosya sistemleri
  • /boot: çekirdek ve initramfs
  • /tmp: geçici (çoğu dağıtımda tmpfs)

Windows’taki sürücü harfleri yerine tek bir ağaç vardır: başka bir dosya sistemi herhangi bir dizine bağlanır (mount). Düzen FHS standardına uyar; çoğu dağıtım “usrmerge” ile /bin, /lib’i /usr altına taşıdı.

Dosya Sistemleri

VFS: Tanımlayıcılar, Açık Dosyalar ve i-node’lar

Süreç A (fd)0tty1tty2tty3→ dosya#14çocuk A′ (fork)0tty1tty2tty3→ dosya#14Süreç C0tty1tty2tty3→ dosya#24struct file #1f_pos = 150 O_RDONLYreferans = 2struct file #2f_pos = 0referans = 1dentry"x.txt"inode 1234boyut, izin, extentext4 → diskVFS nesneleri:superblock: bağlı dosya sistemiinode: dosyanın kendisidentry: ad → inode (önbellek)file: açık dosya oturumu

Linux’ta açık dosya struct file’dır (f_pos, bayraklar, referans sayısı); süreç tablosu task_struct → files_struct içindedir ve fork() sonrası iki süreç aynı struct file’ı gösterir. Nesnelerin işlem tabloları (super_operations, inode_operations, file_operations) çağrıyı ext4, XFS, Btrfs, NFS ya da procfs’in kendi işlevine yönlendirir; dentry’ler dcache’te tutulur.

Dosya Sistemleri

Dosya ve Dizin Sistem Çağrıları, stat

Dosya çağrısıİşlev
open, creatAç / oluştur, fd döndür
closeTanımlayıcıyı kapat
read, writeKonumdan oku / yaz
lseekKonumu taşı
stat, fstat, lstatBilgi al (lstat: bağın kendisi)
pipe, dup2Boru oluştur / fd kopyala
fcntlKilit, bayraklar vb.
mkdir, rmdirDizin oluştur / sil (boşsa)
link, unlinkAd ekle / sil
rename, chdirTaşı (atomik) / cwd değiştir
getdents64Dizin girdilerini oku
stat alanıAnlamı
st_devDosyanın bulunduğu aygıt
st_inoi-node numarası
st_modeTür + izin bitleri
st_nlinkKatı bağ sayısı
st_uid, st_gidSahip ve grup
st_sizeBayt cinsinden boyut
st_atimeSon erişim zamanı
st_mtimeSon içerik değişikliği
st_ctimeSon i-node değişikliği (oluşturma değil!)
st_blocksAyrılan 512 B blok sayısı
stat("a.txt", &st)dizin: a.txt → 812i-node 812st_ino, st_mode, st_nlink, st_size, zamanlar …

opendir/readdir/closedir sistem çağrısı değil, getdents64 üzerine kurulu kütüphane fonksiyonlarıdır. Oluşturma zamanı yalnız yeni statx() ile (stx_btime) alınabilir.

Dosya Sistemleri · Adım adım

Dosya Kilitleme

0123456789101112131415A: paylaşımlı kilit 4–7baytpaylaşımlı (okuma) kilitler çakışabilir; özel (yazma) kilidi hiçbir kilitle çakışamaz

A süreci 4–7. baytlara paylaşımlı (okuma) kilit koyar: fcntl(fd, F_SETLK, &fl) ile l_type = F_RDLCK, l_start = 4, l_len = 4.

0123456789101112131415A: paylaşımlı kilit 4–7B: paylaşımlı kilit 6–9baytpaylaşımlı (okuma) kilitler çakışabilir; özel (yazma) kilidi hiçbir kilitle çakışamaz

B 6–9’a paylaşımlı kilit ister: çakışma paylaşımlı kilitler arasında serbesttir, istek kabul edilir.

0123456789101112131415A: paylaşımlı kilit 4–7B: paylaşımlı kilit 6–9C: paylaşımlı kilit 2–11baytpaylaşımlı (okuma) kilitler çakışabilir; özel (yazma) kilidi hiçbir kilitle çakışamaz

C 2–11’e paylaşımlı kilit koyar; 6–7 baytları artık üç kilitle kaplı.

0123456789101112131415A: paylaşımlı kilit 4–7B: paylaşımlı kilit 6–9C: paylaşımlı kilit 2–11baytD: özel (yazma) kilidi bayt 9 → F_SETLKW ile blokepaylaşımlı (okuma) kilitler çakışabilir; özel (yazma) kilidi hiçbir kilitle çakışamaz

D bayt 9’a özel (F_WRLCK) kilit ister: B ve C’nin kilitleriyle çakışır. F_SETLK hemen hata döndürür, F_SETLKW ise kilitler kalkana dek bekler. Çekirdek bekleme döngüsünü fark ederse EDEADLK döndürür.

Bu kilitler tavsiye niteliğindedir (advisory): kilidi sormayan bir süreç yine yazabilir. Bütün dosya için flock(); iş parçacıklarıyla güvenli kullanım için açık dosyaya bağlı OFD kilitleri vardır.

Dosya Sistemleri

ext2/ext4 Disk Düzeni ve i-node

Disk bölümü:önyüklemeblok grubu 0blok grubu 1blok grubu 2…blok grubu nsüperblokgrup tanımlayıcılarıblok biteşlemii-node biteşlemii-node tablosuveri bloklarıi-node (256 B)mod (tür + izin)uid, gid, boyutatime, mtime, ctimebağ sayısı12 doğrudan bloktekli dolaylıikili dolaylıüçlü dolaylı12 × 4 KiB = 48 KiB+ 1024 × 4 KiB = 4 MiB+ 1024² × 4 KiB = 4 GiB+ 1024³ × 4 KiB = 4 TiBext4: extent ağacıi-node’da 4 extent sığar:(mantıksal blok, uzunluk, fiziksel blok)0, 2048, 34816 → 8 MiB tek girditek extent en çok 32768 blok= 128 MiB; dosya ≤ 16 TiBdolaylı blok yerine az sayıdabüyük ardışık parça

Klasik UNIX düzeni (önyükleme bloğu, süperblok, i-node’lar, veri) ext2’de blok gruplarına bölündü: i-node ile verisi aynı gruba yakın konur, süperblok yedeklenir. Dolaylı bloklarla teorik sınır ~4 TiB’tır (ext2’de i_blocks alanı nedeniyle 2 TiB). Kök dizinin i-node numarası her zaman 2’dir.

Dosya Sistemleri · Adım adım

ext4 Günlükleme (Journaling)

Bellek (sayfa önbelleği)Günlük (journal)Diskteki asıl yerlerveri Di-node M1bitmap M2extent M3kirli sayfalar

Bir write() + fsync() birkaç bloğu değiştirir: veri (D) ile birlikte i-node, blok biteşlemi ve extent gibi üst veriler. Bunlardan biri yazılıp diğeri yazılmadan çökme olursa dosya sistemi tutarsız kalır.

Bellek (sayfa önbelleği)Günlük (journal)Diskteki asıl yerlerveri Di-node M1bitmap M2extent M3kirli sayfalarveri D

Varsayılan data=ordered modunda önce veri blokları asıl yerine yazılır; böylece üst veri hiçbir zaman çöp içeren bloğu göstermez.

Bellek (sayfa önbelleği)Günlük (journal)Diskteki asıl yerlerveri Di-node M1bitmap M2extent M3kirli sayfalarveri DT42 tanımM1M2M3T42 commit

Üst veri blokları günlüğe bir işlem (T42) olarak yazılır; en sonda commit kaydı. Commit diske ulaştığı an işlem kalıcıdır.

Bellek (sayfa önbelleği)Günlük (journal)Diskteki asıl yerlerveri Di-node M1bitmap M2extent M3kirli sayfalarveri DT42 tanımM1M2M3T42 commitM1M2M3checkpoint: günlük alanı serbest

Checkpoint: üst veri asıl yerlerine yazılır, günlükteki alan yeniden kullanılır (dairesel tampon).

Bellek (sayfa önbelleği)Günlük (journal)Diskteki asıl yerlerveri Di-node M1bitmap M2extent M3kirli sayfalarveri DT42 tanımM1M2M3T42 commitM1M2M3commit’ten sonra çökme → bağlarken T42 yeniden oynatılırcommit’ten önce çökme → T42 yok sayılır; eski tutarlı hâl

Çökmeden sonra tam fsck taraması yerine günlük okunur: commit’li işlemler yeniden oynatılır, yarım kalanlar atılır. Saniyeler içinde tutarlılık.

Diğer modlar: data=journal (veri de günlüğe; en güvenli, en yavaş) ve data=writeback (sıra garantisi yok). XFS de üst veri günlüğü kullanır; Btrfs ise günlük yerine yazınca kopyala ile tutarlıdır.

Dosya Sistemleri · Adım adım

Dizinler ve Yol Çözümleme

open("/home/ali/notlar.txt")/ (i-node 2).2..2etc524289home131073usr786433home (131073)ali (131074)

Mutlak yol kökten başlar: kök dizinin i-node’u (2) okunur, veri bloklarındaki girdilerde “home” aranır → 131073. Her dizin için x (arama) izni denetlenir.

open("/home/ali/notlar.txt")/ (i-node 2).2..2etc524289home131073usr786433home (131073).131073..2ali131074ayse131090ali (131074)

“home” dizininin verisinde “ali” aranır → 131074.

open("/home/ali/notlar.txt")/ (i-node 2).2..2etc524289home131073usr786433home (131073).131073..2ali131074ayse131090ali (131074).131074..131073foto132011notlar.txt132010

“ali” dizininde “notlar.txt” → 132010. (Göreli yol olsaydı süreç cwd’sinden başlanırdı.)

open("/home/ali/notlar.txt")/ (i-node 2).2..2etc524289home131073usr786433home (131073).131073..2ali131074ayse131090ali (131074).131074..131073foto132011notlar.txt132010i-node 132010-rw-r--r-- aliboyut 2 KiBextent: 1 blok→ struct file, fd 3

Son bileşenin i-node’u okunur, izinler denetlenir, struct file oluşturulup fd döndürülür.

open("/home/ali/notlar.txt")/ (i-node 2).2..2etc524289home131073usr786433home (131073).131073..2ali131074ayse131090ali (131074).131074..131073foto132011notlar.txt132010i-node 132010-rw-r--r-- aliboyut 2 KiBextent: 1 blok→ struct file, fd 3dizin girdisi (ext2/4): i-node no · kayıt uzunluğu · ad uzunluğu · tür · adsilinen girdi bir öncekinin kayıt uzunluğuna eklenir; büyük dizinlerde htree (hash ağaç) kullanılır

Her adım disk okuması gerektirseydi yavaş olurdu: dentry önbelleği (dcache) ad → i-node eşlemelerini bellekte tutar; sıcak yollar diske hiç gitmeden çözülür.

Dosya Sistemleri

Katı ve Sembolik Bağlar

/home/alia.txt500k777/home/ali/yedekb.txt500i-node 500bağ sayısı = 2katı baği-node 777 (bağ)hedef: "a.txt"yol ileveri blokları
$ ln a.txt yedek/b.txt     # katı
$ ln -s a.txt k            # sembolik
$ ls -li
500 -rw-r--r-- 2 ali ali 9 a.txt
777 lrwxrwxrwx 1 ali ali 5 k -> a.txt
  • Katı bağ: aynı i-node, bağ sayısı artar. rm a.txt yalnız adı siler; veri sayaç 0 olunca (ve açık fd kalmayınca) serbest kalır.
  • Katı bağ dosya sistemi sınırını aşamaz, dizinlere konamaz.
  • Sembolik bağ: hedefin yolunu tutar; başka dosya sistemine, dizine işaret edebilir. Hedef silinirse bağ sarkar.

Dosya Sistemleri · Kodu adım adım çalıştır

Bağ Sayısı ve unlink: Kod İzleme

int fd = open("a.txt", O_CREAT|O_RDWR, 0644);
write(fd, "veri", 4);
link("a.txt", "b.txt");      /* katı bağ */
symlink("a.txt", "s.txt");   /* sembolik */
unlink("a.txt");
int r1 = open("b.txt", O_RDONLY);
int r2 = open("s.txt", O_RDONLY);
unlink("b.txt");
close(r1);
close(fd);
dizina.txt812i-node 812 · "veri"bağ sayısı = 1açık dosya = 1a.txt oluşturuldu, 4 bayt yazıldı

open yeni bir i-node (812) ayırır, dizine “a.txt → 812” girdisini ekler: bağ sayısı 1. fd 3 açık: açık dosya sayısı 1.

dizina.txt812b.txt812i-node 812 · "veri"bağ sayısı = 2açık dosya = 1b.txt aynı i-node’a ikinci ad

link yalnızca yeni bir dizin girdisi yazar: b.txt → 812. Veri kopyalanmaz; bağ sayısı 2. a.txt ile b.txt eşittir, hangisinin “asıl” olduğu yoktur.

dizina.txt812b.txt812s.txt813i-node 812 · "veri"bağ sayısı = 2açık dosya = 1i-node 813 (bağ)içerik: "a.txt"s.txt: yolu tutan ayrı dosya

symlink ayrı bir i-node (813) oluşturur; içeriği yalnızca “a.txt” yoludur. 812’nin bağ sayısı değişmez.

dizinb.txt812s.txt813i-node 812 · "veri"bağ sayısı = 1açık dosya = 1i-node 813 (bağ)içerik: "a.txt"a.txt adı silindi, veri duruyor

unlink("a.txt") adı siler, bağ sayısını 1’e indirir. Veri b.txt üzerinden hâlâ erişilebilir.

dizinb.txt812s.txt813i-node 812 · "veri"bağ sayısı = 1açık dosya = 2i-node 813 (bağ)içerik: "a.txt"b.txt açıldı

b.txt sorunsuz açılır: r1 = 4, açık dosya sayısı 2.

dizinb.txt812s.txt813i-node 812 · "veri"bağ sayısı = 1açık dosya = 2i-node 813 (bağ)içerik: "a.txt"s.txt → "a.txt" → yok

s.txt açılınca çekirdek içindeki yolu (“a.txt”) izler; o ad artık yok. Sembolik bağ sarkar: r2 = −1, ENOENT.

dizins.txt813i-node 812 · "veri"bağ sayısı = 0açık dosya = 2i-node 813 (bağ)içerik: "a.txt"hiç adı kalmadı, ama iki fd açık

Son ad da silindi: bağ sayısı 0. Ama iki tanımlayıcı açık olduğu için i-node ve veri henüz serbest bırakılmaz; ls onu artık göstermez.

dizins.txt813i-node 812 · "veri"bağ sayısı = 0açık dosya = 1i-node 813 (bağ)içerik: "a.txt"r1 kapandı

close(r1): açık dosya sayısı 1. fd 3 üzerinden okuma/yazma hâlâ çalışır.

dizins.txt813i-node 812 serbesti-node 813 (bağ)içerik: "a.txt"bağ 0 ve açık 0: bloklar serbest

Son tanımlayıcı da kapandı: iki sayaç da 0, i-node ve veri blokları serbest kalır. Geçici dosyaların “aç, sonra hemen unlink et” kalıbı buna dayanır.

Dosya Sistemleri

ext4’ün Ötesi: XFS, Btrfs ve Diğerleri

Dosya sistemiÖne çıkan özellikTipik kullanım
ext4Günlükleme, extent, olgun ve hızlı fsckÇoğu dağıtımda varsayılan
XFSParalel G/Ç, büyük dosyalar, gecikmeli ayırmaRHEL varsayılanı, büyük sunucular
BtrfsYazınca kopyala, anlık görüntü, sağlama toplamı, sıkıştırma, alt birimlerFedora, openSUSE varsayılanı
F2FSFlash’a uygun günlük yapılı (log-structured)Android telefonlar
tmpfsTamamen RAM’de (sayfa önbelleği + takas)/tmp, /run, /dev/shm
NFS, SMBAğ dosya sistemleriPaylaşılan ev dizinleri
kök v1kök v2düğümdüğümdüğüm′B1B2B3B4B4′B4 değişince yalnız yol kopyalanır;kök v1 = anlık görüntü (snapshot)

VFS sayesinde hepsi aynı sistem çağrılarıyla kullanılır; findmnt veya df -T hangi dizinde hangi dosya sisteminin bağlı olduğunu gösterir.

Dosya Sistemleri

/proc ve /sys: Çekirdeğe Açılan Pencereler

$ cat /proc/loadavg
0.42 0.37 0.30 2/1234 98765
$ grep -E "MemTotal|MemAvailable" /proc/meminfo
MemTotal:       16303452 kB
MemAvailable:    9876544 kB
$ ls /proc/self
cmdline  cwd  environ  exe  fd  maps  status  …
$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline kyber bfq
$ sysctl vm.swappiness        # = /proc/sys/vm/swappiness
vm.swappiness = 60
/proc

Süreç başına dizinler (/proc/PID/status, maps, fd/) ve çekirdek istatistikleri. ps, top, free verisini buradan okur. /proc/sys: ayarlanabilir çekirdek parametreleri.

/sys (sysfs)

Aygıt modeli: her aygıt, sürücü ve veri yolu bir dizin; dosya başına tek değer. /sys/fs/cgroup cgroup v2 arayüzüdür.

Etkileşimli simülatör: Linux Süreç Gezgini: ps, top ve /proc ile PID/PPID ilişkileri, süreç ağacı, dosya tanımlayıcıları ve bellek haritaları.

Güvenlik · Adım adım

chmod ve umask Hesapları

$ chmod 754 betik.shsgtrwxrwxrwxistenen0754000111101100rwxr-xr--sonuç0754000111101100rwxr-xr--

Her sekizli rakam üç bittir: 7 = 111 = rwx, 5 = 101 = r-x, 4 = 100 = r--.

$ chmod g+w,o-r betik.shsgtrwxrwxrwxönceki0754000111101100rwxr-xr--g+w: OR 0200020000000010000o-r: AND ~0040004000000000100sonuç0770000111111000rwxrwx---

Sembolik mod mevcut bitleri değiştirir: grup yazma biti eklenir, diğerlerinin okuma biti silinir → 0770.

$ umask 022 ; touch a ; mkdir dsgtrwxrwxrwxdosya isteği0666000110110110umask0022000000010010sonuç0644000110100100rw-r--r--

Yeni dosya 666, dizin 777 ister; umask’taki bitler silinir: 666 & ~022 = 0644, dizin 777 & ~022 = 0755. (Çıkarma değil, bit temizleme!)

$ umask 027 ; touch a ; mkdir dsgtrwxrwxrwxdosya isteği0666000110110110umask0027000000010111sonuç0640000110100000rw-r-----

Daha sıkı umask: dosya 666 & ~027 = 0640 (rw-r-----), dizin 777 & ~027 = 0750 (rwxr-x---). Diğerleri hiçbir şey göremez.

$ chmod 4755 passwd ; chmod 1777 /tmpsgtrwxrwxrwxsetuid + 7554755100111101101rwsr-xr-xyapışkan + 7771777001111111111rwxrwxrwt

4xxx setuid: çalışan süreç dosya sahibinin kimliğini alır → rwsr-xr-x. 2xxx setgid (dizinde: yeni dosyalar grubu miras alır). 1xxx yapışkan bit: /tmp’de herkes yazar ama yalnız kendi dosyasını silebilir → rwxrwxrwt.

Kontrol: stat -c "%a %A" dosya sekizli ve sembolik izni birlikte gösterir; umask -S maskeyi sembolik yazar. Etkileşimli simülatör: İşletim Sistemi Koruma ve İzinler Laboratuvarı.

Güvenlik

Erişim Denetimi, root ve Yetenekler

  1. euid = 0 (root) → izin ver (çalıştırma için en az bir x biti gerekir)
  2. euid = dosya sahibi → yalnız sahip bitlerine bak
  3. egid ya da ek gruplardan biri = dosya grubu → grup bitleri
  4. aksi halde diğer bitleri

İlk eşleşen sınıf kazanır: ----rw-rw- dosyasını sahibi ali okuyamaz, başkaları okur.

Yetenekler (capabilities): setcap cap_net_raw+ep /usr/bin/ping ile ping setuid root olmadan ham soket açar.
Çağrıİşlev
chmodDosyanın izin modunu değiştirir
chownSahip ve grubu değiştirir
accessErişimi gerçek uid/gid ile sınar
getuid, geteuidGerçek / etkin uid
getgid, getegidGerçek / etkin gid
setuid, setresuiduid değiştirir (ayrıcalık bırakma)
setgidgid değiştirir
umaskYeni dosyalar için izin maskesi

Kullanıcı ve grup kimlikleri /etc/passwd ve /etc/group’ta; parola özetleri yalnız root’un okuyabildiği /etc/shadow’da tutulur. sudo yetkilendirilmiş kullanıcıya komut başına root yetkisi verir.

Güvenlik · Kodu adım adım çalıştır

Dosya İzin Denetimi: Kod İzleme

int izin_var(cred *c, inode *f, int istek) {
    int bit, m = f->mode;       /* r4 w2 x1 */
    if (c->euid == 0)           /* root */
        return !(istek & 1) || (m & 0111);
    if (c->euid == f->uid)
        bit = (m >> 6) & 7;     /* sahip */
    else if (grupta(c, f->gid))
        bit = (m >> 3) & 7;     /* grup */
    else
        bit = m & 7;            /* diğer */
    return (bit & istek) == istek;
}
rapor.txt: sahip ali, grup ekip, mod 0640sahiprw-grupr--diğer---istek: — · —

rapor.txt: sahibi ali, grubu ekip, mod 0640 = rw-r-----. veli ekip grubunda, can değil.

rapor.txt: sahip ali, grup ekip, mod 0640sahiprw-grupr--diğer---istek: ali (uid 1000) · wizin

ali dosyanın sahibi: sahip bitleri seçilir, bit = 6 (rw-). 6 & 2 == 2: izin.

rapor.txt: sahip ali, grup ekip, mod 0640sahiprw-grupr--diğer---istek: veli (uid 1001) · wret (EACCES)

veli ekip grubunda: grup bitleri seçilir, bit = 4 (r--). 4 & 2 ≠ 2: ret.

rapor.txt: sahip ali, grup ekip, mod 0640sahiprw-grupr--diğer---istek: veli (uid 1001) · rizin

veli ekip grubunda: grup bitleri seçilir, bit = 4 (r--). 4 & 4 == 4: izin.

rapor.txt: sahip ali, grup ekip, mod 0640sahiprw-grupr--diğer---istek: can (uid 1002) · rret (EACCES)

can ne sahip ne grupta: diğer bitleri seçilir, bit = 0 (---). 0 & 4 ≠ 4: ret.

rapor.txt: sahip ali, grup ekip, mod 0640sahiprw-grupr--diğer---istek: root (uid 0) · reuid 0: izin bitlerine bakılmazizin

root (euid 0): okuma ve yazma için izin bitlerine hiç bakılmaz; izin. Yalnız çalıştırmada en az bir x biti aranır.

rapor.txt: sahip ali, grup ekip, mod 0066sahip---gruprw-diğerrw-istek: ali (uid 1000) · rret (EACCES)

Mod 0066 (----rw-rw-) olsun: can ve veli okuyabilir, ama ali sahip sınıfına düşer ve orada bit yok: ret. İlk eşleşen sınıf kazanır; diğer bitlere hiç bakılmaz.

Güvenlik · Adım adım

Konteynerler: Ad Alanları + cgroups

Tek Linux çekirdeği (konak)Konak süreçlerisystemd (PID 1)sshd (PID 820)containerdapp → PID 48213Konteynerpid nsmnt nsnet nsuts nsipc nsuser nscgroup nstime ns

Çalışma zamanı (runc, crun) clone()/unshare() ile yeni ad alanları oluşturur: kendi PID numaraları, bağlama ağacı, ağ yığını, ana makine adı, IPC, kullanıcı eşlemesi (içerideki root dışarıda sıradan uid), cgroup ve saat görünümü.

Tek Linux çekirdeği (konak)Konak süreçlerisystemd (PID 1)sshd (PID 820)containerdapp → PID 48213Konteynerpid nsmnt nsnet nsuts nsipc nsuser nscgroup nstime nskök: overlayfsimaj katmanları (ro) + üst (rw)

Bağlama ad alanında pivot_root ile imajın kök dosya sistemine geçilir. Kök genelde overlayfs’tir: salt okunur imaj katmanları + konteynere özel yazılabilir üst katman.

Tek Linux çekirdeği (konak)Konak süreçlerisystemd (PID 1)sshd (PID 820)containerdapp → PID 48213Konteynerpid nsmnt nsnet nsuts nsipc nsuser nscgroup nstime nskök: overlayfsimaj katmanları (ro) + üst (rw)cgroup v2cpu.max · memory.max · pids.max

cgroup v2 kaynakları sınırlar: cpu.max = "50000 100000" (yarım CPU), memory.max = 512M, pids.max = 100. Ad alanı ne görüleceğini, cgroup ne kadar kullanılacağını belirler.

Tek Linux çekirdeği (konak)Konak süreçlerisystemd (PID 1)sshd (PID 820)containerdapp → PID 48213Konteynerpid nsmnt nsnet nsuts nsipc nsuser nscgroup nstime nskök: overlayfsimaj katmanları (ro) + üst (rw)cgroup v2cpu.max · memory.max · pids.maxgüvenlikyetenek düşür, seccomp, LSM

Saldırı yüzeyi daraltılır: gereksiz yetenekler düşürülür, no_new_privs, seccomp filtresi (onlarca riskli sistem çağrısı engellenir) ve AppArmor/SELinux profili uygulanır.

Tek Linux çekirdeği (konak)Konak süreçlerisystemd (PID 1)sshd (PID 820)containerdapp → PID 48213Konteynerpid nsmnt nsnet nsuts nsipc nsuser nscgroup nstime nskök: overlayfsimaj katmanları (ro) + üst (rw)cgroup v2cpu.max · memory.max · pids.maxgüvenlikyetenek düşür, seccomp, LSMexecve(app)içeride PID 1

Son olarak execve: uygulama içeride PID 1, konakta PID 48213. Hepsi aynı çekirdeği paylaşır: VM’den çok hafiftir ama çekirdek açığı tüm konteynerleri etkiler.

Güvenlik

seccomp ve Linux Güvenlik Modülleri (LSM)

uygulamaseccompDACyeteneklerLSM kancalarınesneopen("/etc/shadow")izin / errno / öldürrwx, uid, gidCAP_DAC_OVERRIDE?SELinux, AppArmorerişim verildiherhangi bir aşama “hayır” derse: EPERM / EACCES (seccomp: süreç öldürülebilir)
SELinux

Etiket tabanlı zorunlu erişim denetimi (MAC): her süreç ve dosyanın bir tipi var; politika hangi tipin hangisine ne yapabileceğini söyler. RHEL, Fedora, Android.

AppArmor

Yol tabanlı profiller: “bu program yalnız şu dosyalara erişebilir”. Yazması kolay. Ubuntu, SUSE, Debian.

Landlock (5.13+)

Ayrıcalıksız süreç kendini korumalı alana alır: “bundan sonra yalnız ./veri altına yazabilirim”.

seccomp-BPF

Sürecin yapabileceği sistem çağrılarını filtreler; Chrome, systemd hizmetleri, Docker, Android uygulamaları kullanır.

Android ve Özet · Adım adım

Android: Binder, Zygote ve Korumalı Alan

Uygulamalar (APK)Android çatısı (Java/Kotlin API)ART çalışma zamanı + yerel kütüphaneler (Bionic)HAL (donanım soyutlama)Linux çekirdeği + Binder, SELinuxzygoteçatı önceden yüklüsystem_serveruid 1000 (system)

Android Linux çekirdeği üzerinde çalışır ama GNU kullanıcı alanı yoktur: C kütüphanesi Bionic, uygulamalar ART’ta çalışır. Çekirdeğe eklenenler: Binder IPC, enerji yönetimi (wakelock), zorunlu SELinux.

Uygulamalar (APK)Android çatısı (Java/Kotlin API)ART çalışma zamanı + yerel kütüphaneler (Bionic)HAL (donanım soyutlama)Linux çekirdeği + Binder, SELinuxzygoteçatı önceden yüklüsystem_serveruid 1000 (system)

Önyüklemede init zygote sürecini başlatır; zygote çatı sınıflarını ve kaynakları bir kez yükleyip bekler.

Uygulamalar (APK)Android çatısı (Java/Kotlin API)ART çalışma zamanı + yerel kütüphaneler (Bionic)HAL (donanım soyutlama)Linux çekirdeği + Binder, SELinuxzygoteçatı önceden yüklüsystem_serveruid 1000 (system)com.ornek.appuid 10123 · untrusted_appfork() + kimlik

Uygulama açılırken zygote fork() eder: yüklü sayfalar COW ile paylaşılır, başlatma hızlanır. Çocuk uygulamanın benzersiz uid’ine, SELinux bağlamına ve seccomp filtresine geçer.

Uygulamalar (APK)Android çatısı (Java/Kotlin API)ART çalışma zamanı + yerel kütüphaneler (Bionic)HAL (donanım soyutlama)Linux çekirdeği + Binder, SELinuxzygoteçatı önceden yüklüsystem_serveruid 1000 (system)com.ornek.appuid 10123 · untrusted_appfork() + kimlik/dev/bindertek kopya +arayan uid

Uygulama bir hizmeti (konum, kamera) Binder ile çağırır: çekirdek veriyi alıcının eşlenmiş tamponuna tek kopyayla taşır ve arayanın uid’ini iletir; hizmet izni buna göre denetler.

Uygulamalar (APK)Android çatısı (Java/Kotlin API)ART çalışma zamanı + yerel kütüphaneler (Bionic)HAL (donanım soyutlama)Linux çekirdeği + Binder, SELinuxzygoteçatı önceden yüklüsystem_serveruid 1000 (system)com.ornek.appuid 10123 · untrusted_appfork() + kimlik/dev/bindertek kopya +arayan uid/data/data/com.ornek.appyalnız uid 10123lmkd: arka planı öldür

Korumalı alan: her uygulama ayrı bir Linux kullanıcısıdır, verisi yalnız kendisine açıktır. Bellek azalınca kullanıcı alanındaki lmkd, PSI sinyalleriyle önemsiz arka plan uygulamalarını öldürür.

Özet

Özet: Dersin Kavramları Linux’ta

KonuKavramLinux’taki karşılığı
YapılarSistem çağrısı, monolitik çekirdeksyscall, LKM, eBPF
SüreçlerPCB, oluşturma, IPCtask_struct, fork/exec/wait, sinyal, boru
İş parçacıklarıÇekirdek iş parçacığı modeliclone(), NPTL 1:1
ÇizelgelemeAdil paylaşım, gerçek zamanEEVDF, FIFO/RR/DEADLINE, sched_ext
SenkronizasyonKilit, koşul değişkenifutex, spinlock, RCU
KilitlenmeTespit ve önlemelockdep, fcntl EDEADLK
BellekAyırma, parçalanmabölgeler, buddy listeleri, SLUB
Sanal bellekSayfalama, değiştirme4/5 düzey tablo, COW, MGLRU, zswap, OOM
Dosya sistemlerii-node, dizin, günlükVFS, ext4, XFS, Btrfs
G/ÇSürücü, çizelgelemeaygıt dosyaları, blk-mq, io_uring
Çok işlemciliYük dengeleme, NUMACPU başına kuyruklar, çizelgeleme alanları
GüvenlikErişim denetimi, yalıtımrwx, yetenekler, namespaces, SELinux, seccomp
TasarımMekanizma ve politika ayrımıcgroup, sched_ext: politika kullanıcıda

Özet

Kontrol Soruları

  1. fork() çekirdekte hangi yapıları kopyalar, hangilerini paylaşır? COW neyi kazandırır?
  2. Kabuk ls | wc -l’yi nasıl kurar? Ebeveyn boru uçlarını kapatmazsa ne olur?
  3. Linux’ta süreç ile iş parçacığı arasındaki fark nedir? clone bayraklarıyla açıklayın.
  4. Linux 6.6’da adil sınıfta ne değişti, ne aynı kaldı?
  5. 0x00007f3a1c2b5e88 adresinin 4 düzeyli tablodaki dört dizini ve ofseti nedir?
  6. SLUB, task_struct gibi nesneler için doğrudan sayfa ayırmaya göre neden daha iyidir?
  7. umask 027 iken oluşturulan dosya ve dizinin izinleri nedir?
  8. Katı bağ ile sembolik bağ arasındaki fark nedir? Hedef silinince ne olur?
  9. ext4 sıralı günlüklemede çökmeden sonra tutarlılık nasıl sağlanır?
  10. Konteyner = ad alanları + cgroups: her biri neyi sağlar? VM’den farkı nedir?
Cevaplar
  1. Yeni task_struct, PID ve çekirdek yığını oluşur; sayfa tabloları kopyalanıp yazılabilir sayfalar salt okunur yapılır; açık dosyalar struct file referans sayısı artırılarak paylaşılır. COW ile sayfalar ancak yazılınca kopyalanır; fork’u exec izlediğinde neredeyse hiç kopya yapılmaz.
  2. pipe() → fork; çocuk 1 dup2(yazma, 1) + exec ls; çocuk 2 dup2(okuma, 0) + exec wc. Ebeveyn yazma ucunu açık tutarsa wc EOF görmez, sonsuza dek bekler.
  3. Yapısal fark yok: ikisi de task_struct. İş parçacığı CLONE_VM, CLONE_FILES, CLONE_SIGHAND, CLONE_THREAD ile adres alanını, dosyaları ve işleyicileri paylaşır, aynı TGID’dedir.
  4. Seçim kuralı değişti: en küçük vruntime yerine uygunlar (v ≤ V) içinde en erken sanal son tarih. vruntime, nice ağırlıkları ve kırmızı-siyah ağaç aynı kaldı; gecikme ayarlarının yerini temel dilim aldı.
  5. PGD = 254, PUD = 232, PMD = 225, PTE = 181, ofset = 0xe88.
  6. Aynı boydaki nesneler slab içinde yan yana paketlenir: iç parçalanma olmaz, ayırma ve bırakma O(1)’dir, CPU başına listelerle kilitsiz hızlı yol vardır.
  7. Dosya 666 & ~027 = 0640 (rw-r-----), dizin 777 & ~027 = 0750 (rwxr-x---).
  8. Katı bağ aynı i-node’a ikinci addır; hedef adı silinse de veri kalır. Sembolik bağ yolu tutan ayrı dosyadır; hedef silinince sarkar. Katı bağ dosya sistemi sınırını aşamaz.
  9. Veri önce asıl yerine, üst veri günlüğe yazılır, sonra commit. Bağlarken commit’li işlemler yeniden oynatılır, commit’siz olanlar atılır; tam fsck gerekmez.
  10. Ad alanları görünümü yalıtır (PID, ağ, bağlama…), cgroups kaynak kullanımını sınırlar. Konteynerler konak çekirdeğini paylaşır: hafif ama yalıtım VM’den zayıftır.

Özet

Kaynaklar

  • A. S. Tanenbaum, H. Bos, Modern Operating Systems, 4. baskı (2014) / 5. baskı (2023), Pearson — Bölüm 10: Case Study 1: Unix, Linux and Android.
  • A. Silberschatz, P. B. Galvin, G. Gagne, Operating System Concepts, 10. baskı, Wiley, 2018 — Bölüm 20: The Linux System.
  • R. Love, Linux Kernel Development, 3. baskı, Addison-Wesley, 2010.
  • M. Kerrisk, The Linux Programming Interface, No Starch Press, 2010; man7.org kılavuz sayfaları.
  • The Linux Kernel Documentation, docs.kernel.org — scheduler (EEVDF, sched-ext), admin-guide/mm (MGLRU, zswap), block (blk-mq), filesystems (vfs, ext4), userspace-api (seccomp, landlock).
  • Android Open Source Project, source.android.com — mimari, Binder, uygulama korumalı alanı.
  • D. M. Ritchie, K. Thompson, “The UNIX Time-Sharing System”, Communications of the ACM, 1974.

Son

Bölüm 15: Linux
Dersin son bölümü — İşletim Sistemleri dersi burada tamamlanıyor. · Terim sözlüğü
1 / 1