Bölüm 3: Süreçler
Çoktan Seçmeli · Süreç Kavramı
Soru 1: Değişkenler Nereye Yerleşir?
Bir fonksiyonun içinde static int sayac; (ilk değersiz), int *p = malloc(100); ile ayrılan 100 bayt ve yerel int i; tanımlı. Bu üçü sürecin adres alanında sırasıyla nerede tutulur?
A: static yerel değişken program boyunca yaşar: ilk değersizse BSS’de, değerliyse veri bölümündedir. malloc ile ayrılan alan öbektedir; p göstericisinin kendisi ise yığındadır. Yerel i fonksiyonun yığın çerçevesindedir.
Kod Çıktısı · Süreç Kavramı
Soru 2: Aynı Adres, Farklı Değer
Program a adıyla derlendi; ASLR kapalıyken ./a 1 & ./a 10 ile iki kez aynı anda çalıştırılıyor. Çıktıdaki adresler ve değerler hakkında ne söylenebilir? Neden?
int x = 0; int main(int argc, char *argv[]) { int d = atoi(argv[1]); for (int i = 0; i < 3; i++) { x += d; printf("%s %p %d\n", argv[1], (void *)&x, x); sleep(1); } return 0; }
Cevabı göster
Örnek çıktı (satırların sırası çizelgelemeye bağlıdır):
1 0x404034 1 10 0x404034 10 1 0x404034 2 10 0x404034 20 1 0x404034 3 10 0x404034 30
- İki süreç aynı sanal adresi yazdırır: aynı program, aynı adres alanı düzeni.
- Değerler birbirini etkilemez (1, 2, 3 ve 10, 20, 30): her sürecin kendi adres alanı vardır; İS aynı sanal adresi farklı fiziksel çerçevelere eşler.
Program diskteki tek dosyadır; iki süreç onun iki ayrı, etkin örneğidir.
Adım Adım Çalıştırma · Süreç Oluşturma
Soru 3: Kısa Devre ve fork()
Tüm fork() çağrıları başarılı. Ekrana kaç X yazılır, toplam kaç süreç oluşur? Süreç ağacını çizin. (&& soldaki 0 ise sağı hiç çalıştırmaz.)
Başta tek süreç: P0.
fork(): P0, P1’i doğurur; ikisi de 3. satırdan devam eder.
İlk fork(): P0 → P2, P1 → P3. P2 ve P3’te dönüş 0 → && yanlış; ikinci fork’u ve gövdeyi atlarlar.
P0 ve P1’de ilk sonuç ≠ 0 → ikinci fork(): P0 → P4, P1 → P5. P4, P5’te sonuç 0 → koşul yanlış.
Koşul yalnızca P0 ve P1’de doğrudur: gövdedeki fork ile P0 → P6, P1 → P7.
Sekiz sürecin hepsi printf’e ulaşır: 8 X (sıra belirsiz). P0’ın 4, P1’in 3 çocuğu vardır.
int main(void) { fork(); if (fork() && fork()) fork(); printf("X\n"); return 0; }
Çoktan Seçmeli · Süreç Oluşturma
Soru 4: Çıktı Dosyaya Gidince
Aşağıdaki program ./prog > cikti.txt ile çalıştırılıyor. cikti.txt’nin içeriği nedir?
printf("A\n");
fork();
printf("B\n");B: Çıktı dosyaya yönlendirilince stdout tam tamponludur: "A\n" fork anında henüz yazılmamıştır ve tamponla birlikte çocuğa kopyalanır. Her süreç çıkarken kendi "A\nB\n" tamponunu tek seferde yazar. Terminalde satır tamponlu olduğundan A fork’tan önce yazılır ve çıktı A, B, B olurdu.
Kod Çıktısı · Süreç Oluşturma
Soru 5: Global ve Öbek Değişkenleri
Çocuk ve ebeveyn global g’yi ve öbekteki *h’yi değiştiriyor. Program ne yazdırır?
int g = 1; int main(void) { int *h = malloc(sizeof(int)); *h = 10; pid_t p = fork(); if (p == 0) { g += 5; *h += 5; printf("çocuk: %d %d\n", g, *h); return 0; } waitpid(p, NULL, 0); g *= 2; *h *= 2; printf("ebeveyn: %d %d\n", g, *h); return 0; }
Cevabı göster
çocuk: 6 15 ebeveyn: 2 20
- fork sonrası çocuğun adres alanı ebeveyninkinin kopyasıdır: veri, öbek ve yığın dahil.
hiki süreçte aynı sanal adresi gösterir ama yazınca kopyalama (COW) ile farklı fiziksel sayfalara ayrılır. - Çocuk 1 + 5 = 6 ve 10 + 5 = 15 görür; ebeveyn kendi kopyalarından 1 × 2 = 2 ve 10 × 2 = 20 hesaplar.
- Sıra kesindir: ebeveyn yazmadan önce
waitpidile çocuğu bekler.
Çoktan Seçmeli · Süreç Oluşturma
Soru 6: execv() Başarılı Olunca
Bir süreç execv("/bin/ls", args) çağırdı ve çağrı başarılı oldu. Hangisi doğrudur?
D: exec süreç oluşturmaz; var olan sürecin bellek görüntüsünü yeni programla değiştirir. PID, ebeveyn ilişkisi ve (close-on-exec işaretlenmemiş) açık tanımlayıcılar korunur; kabuğun yönlendirmesi buna dayanır. B fork’un dönüş kuralını karıştırır.
Kod Çıktısı · Süreç Sonlandırma
Soru 7: Çıkış Kodu ve Zombi
Program ne yazdırır? İlk 10 saniyede ps çocuğu hangi durumda gösterir? waitpid’den sonra ne değişir?
int main(void) { pid_t p = fork(); if (p == 0) exit(300); sleep(10); int st; waitpid(p, &st, 0); if (WIFEXITED(st)) printf("%d\n", WEXITSTATUS(st)); return 0; }
Cevabı göster
Çıktı: 44. Çıkış durumunun yalnızca alttaki 8 biti ebeveyne iletilir: 300 mod 256 = 44. Taşınabilir programlar 0–255 kullanır.
- İlk 10 saniye: çocuk bitti ama ebeveyn henüz
waitçağırmadı → zombi (ps’te Z, <defunct>). Belleği serbest; süreç tablosunda PID ve çıkış durumu bekler. waitpiddurumu alır, çekirdek girdiyi siler (biçme): zombi kalmaz.
Çoktan Seçmeli · Süreç Sonlandırma
Soru 8: Ebeveyni Önce Biten Çocuk
PID’i 500 olan ebeveyn sonlandı; çocuğu hâlâ çalışıyor ve sistemde alt biçici (subreaper) tanımlı değil. Çocuk şimdi getppid() çağırırsa ne döner?
C: Ebeveyni sonlanan çocuk yetim olur ve çekirdek onu hemen init/systemd’ye (PID 1) bağlar. init biten çocuklarını wait ile topladığı için yetim bittiğinde uzun süre zombi kalmaz. Ebeveyn sonlanınca çocuk kendiliğinden sonlanmaz.
Adım Adım Çalıştırma · Durumlar ve PCB
Soru 9: Bir Sürecin Yaşamı
Tek CPU’lu sistemde P süreci için olaylar soldaki sırayla gerçekleşiyor. Her olaydan sonra P hangi durumdadır? P hazır kuyruğuna kaç kez girer, kaç kez bekler?
Beş durumlu model: Yeni, Hazır, Çalışıyor, Bekliyor, Sonlandı.
PCB ayrılıyor, adres alanı hazırlanıyor: Yeni.
Hazır kuyruğuna girer (1. kez).
Çizelgeleyici seçti → Çalışıyor.
Süreç hiçbir şey beklemiyor, yalnızca sırası geçti: Bekliyor’a değil Hazır’a döner (2. kez).
Yeniden seçildi → Çalışıyor.
Bir olayı (çocuğun bitişi) bekliyor: CPU’yu bırakır.
Olay gerçekleşti: doğrudan Çalışıyor’a değil, önce Hazır’a geçer (3. kez). Bekliyor → Çalışıyor oku yoktur.
Seçildi → Çalışıyor.
read(): satır gelene kadar bloke olur → Bekliyor (2. kez).
Klavye kesmesi süreci uyandırır: Hazır (4. kez).
Seçildi → Çalışıyor.
Sonlandı: 4 kez hazır kuyruğuna girdi, 2 kez bekledi, 4 kez CPU’ya seçildi. Ebeveyn wait edene kadar PCB’si (zombi) durur.
İS süreci oluşturuyor (PCB, bellek) kabul edildi çizelgeleyici seçti zaman dilimi doldu yeniden seçildi waitpid: çocuk henüz bitmedi çocuk sonlandı seçildi read(): klavyeden satır bekliyor kullanıcı Enter’a bastı seçildi exit(0)
Çoktan Seçmeli · Çizelgeleme
Soru 10: Kaç Süreç Gerekir?
Süreçler zamanlarının %75’ini G/Ç bekleyerek geçiriyor ve birbirinden bağımsız. CPU kullanımı = 1 − pⁿ modeline göre kullanımın en az %90 olması için bellekte en az kaç süreç bulunmalıdır?
C: 0,75ⁿ ≤ 0,10 olmalı. 0,75⁸ ≈ 0,1001 → kullanım %89,99, sınırın hemen altında kalır; 0,75⁹ ≈ 0,0751 → %92,5. B, ln 0,1 / ln 0,75 ≈ 8,004 sonucunu aşağı yuvarlamaktır. Her ek süreç bir öncekinden daha az kazandırır.
Hesaplama · Çizelgeleme
Soru 11: Bağlam Değiştirme Yükü
Bir bağlam değiştirme 0,1 ms sürüyor; hazır kuyruğunda dönüşümlü çalışan 5 CPU’ya bağlı süreç var ve her biri dilimini tam kullanıyor. Zaman dilimi 2 ms ve 20 ms iken (a) CPU zamanının yüzde kaçı geçişlere gider, (b) bir süreç iki dilimi arasında en çok ne kadar bekler?
Cevabı göster
| dilim | ek yük = s / (q + s) | bekleme = 5s + 4q |
|---|---|---|
| 2 ms | 0,1 / 2,1 = %4,76 | 0,5 + 8 = 8,5 ms |
| 20 ms | 0,1 / 20,1 = %0,50 | 0,5 + 80 = 80,5 ms |
Bir sürecin dilimi bitince 5 geçiş ve diğer 4 sürecin dilimi geçer. Küçük dilim tepki süresini iyileştirir ama ek yükü artırır; dilim, geçiş süresinin çok üstünde seçilmelidir. Asıl dolaylı maliyet önbellek ve TLB’nin soğumasıdır.
Çoktan Seçmeli · Süreçler Arası İletişim
Soru 12: Büyük Görüntüleri Aktarmak
Bir kamera süreci saniyede 60 büyük görüntüyü aynı makinedeki bir işleme sürecine aktarıyor. Kopyalama maliyeti en düşük yöntem hangisidir ve bunun bedeli nedir?
A: Paylaşımlı bellek kurulduktan sonra veri çekirdekten geçmez; iki süreç aynı fiziksel sayfaları görür. Bedeli: kimin ne zaman yazacağını (kilit, semafor) süreçler kendisi sağlamalıdır. Boruda ve ileti kuyruğunda her ileti çekirdeğe kopyalanıp oradan alınır; buna karşılık senkronizasyonu çekirdek sağlar.
Adım Adım Çalıştırma · Süreçler Arası İletişim
Soru 13: Borudan Parça Parça Okumak
Çocuk ne yazdırır? Çocuk 6. satırdaki close(fd[1])’i unutsaydı ne olurdu?
pipe: okuma ucu 3, yazma ucu 4 (ilk boş numaralar). Tampon boş.
fork: çocuk iki ucu da miras alır; şimdi iki yazma ucu açık.
Çocuk yazma ucunu, ebeveyn okuma ucunu kapatır. Çocuk boş boruda read çağırırsa veri gelene kadar bloke olur.
Ebeveyn 11 baytı tek write ile yazar (PIPE_BUF’tan küçük yazma bölünmez).
read en çok 4 bayt alır: "isle".
Sonraki 4 bayt: "tim ".
Kalan yalnızca 3 bayt: read 3 döndürür, beklemez.
Ebeveyn yazma ucunu kapatır: borunun açık yazma ucu kalmadı. (Bu adım okumalardan önce de olabilir; çıktı değişmez.)
Boş boru ve hiç yazıcı yok → read 0 (dosya sonu), döngü biter. Çocuk 6. satırı unutsaydı kendi yazma ucu açık kalır, bu read sonsuza dek bloke olurdu.
int main(void) { int fd[2]; char buf[4]; ssize_t n; int top = 0; pipe(fd); if (fork() == 0) { close(fd[1]); while ((n = read(fd[0], buf, 4)) > 0) { top += n; printf("%zd ", n); } printf("| %d\n", top); return 0; } close(fd[0]); write(fd[1], "isletim sis", 11); close(fd[1]); wait(NULL); return 0; }
Klasik Soru · Eş Zamanlılık Sorunları
Soru 14: count++ ve count--
Paylaşılan count 5’tir. Üretici count++’ı (LOAD R1, count · ADD R1, 1 · STORE count, R1), tüketici count--’i (LOAD R2 · SUB R2, 1 · STORE) çalıştırıyor. Komutlar şu sırayla işlerse sonuç nedir: Ü.LOAD, T.LOAD, Ü.ADD, T.SUB, Ü.STORE, T.STORE? Bütün sıralamalarda olası son değerler nelerdir?
Cevabı göster
| adım | R1 | R2 | count |
|---|---|---|---|
| Ü.LOAD | 5 | 5 | |
| T.LOAD | 5 | 5 | 5 |
| Ü.ADD | 6 | 5 | 5 |
| T.SUB | 6 | 4 | 5 |
| Ü.STORE | 6 | 4 | 6 |
| T.STORE | 6 | 4 | 4 |
Sonuç 4: üreticinin artışı kayboldu. 20 olası sıralamanın tamamında son değer 4, 5 ya da 6 olur; doğru sonuç 5 yalnızca biri kritik bölgesini bölünmeden bitirirse garanti edilir: yarış durumu.
Çoktan Seçmeli · Eş Zamanlılık Sorunları
Soru 15: Peterson: Kim Girer?
Peterson çözümünde başta kimse kritik bölgede değil. Adımlar şu sırayla işliyor: P0 flag[0] = true, P1 flag[1] = true, P1 turn = 0, P0 turn = 1. Ardından ikisi de while (flag[j] && turn == j) denetimini yapıyor. Ne olur?
B: turn’e en son P0 yazdı (turn = 1). P0 için flag[1] doğru ve turn == 1 → bekler. P1 için flag[0] doğru ama turn == 0 yanlış → girer. Kibarca sırayı en son veren bekler; P1 çıkıp flag[1] = false yapınca P0 girer.
Adım Adım Çalıştırma · Eş Zamanlılık Sorunları
Soru 16: Semaforlarla Üretici-Tüketici
N = 2, tampon boş. Sıra: T bir öğe almaya çalışır; Ü A’yı ve B’yi koyar; Ü C için dener; T bir öğe alır; Ü C’yi koyar; T bir öğe daha alır. Her adımda semaforlar, tampon ve uyuyanlar nedir? (up, uyuyan varsa birini uyandırır ve değer 0 kalır.)
Tampon boş: empty = 2 boş yuva, full = 0 dolu yuva.
T: down(&full), full = 0 → T uyur. Meşgul bekleme yok.
Ü A’yı koyar: empty 2 → 1. up(&full) uyuyan T’yi uyandırır; T’nin down’ı tamamlanır, full 0 kalır.
T henüz çalışmadı; Ü B’yi de koyar: empty 0, full 1.
Ü C için down(&empty): tampon dolu → Ü uyur.
T çalışır, A’yı alır. up(&empty) uyuyan Ü’yü uyandırır; empty 0 kalır.
Ü C’yi koyar: full 2.
T: full 2 → 1, B’yi alır, empty 0 → 1. Sonda tamponda C; mutex = 1, empty = 1, full = 1. Hiçbir işlem yokken her zaman empty + full = N.
semaphore mutex = 1, empty = 2, full = 0; void uretici(void) { while (TRUE) { item = produce_item(); down(&empty); down(&mutex); insert_item(item); up(&mutex); up(&full); } } void tuketici(void) { while (TRUE) { down(&full); down(&mutex); item = remove_item(); up(&mutex); up(&empty); consume_item(item); } }
Çoktan Seçmeli · Eş Zamanlılık Sorunları
Soru 17: Okur-Yazar Çözümünün Zayıflığı
Okur-yazar çözümünde ilk okur db’yi kilitliyor, son okur bırakıyor. Okurlar aralıksız, birbirleriyle örtüşerek gelirse ne olur?
D: rc hiç 0’a inmediği için up(&db) çağrılmaz; yazar down(&db)’de açlığa düşer. Okurlar birlikte okuyabilir (A yanlış), yazar ise her zaman tek başınadır (B yanlış). Çözüm: yazar beklerken yeni okurları sıraya almak.
Çoktan Seçmeli · Mobil Sistemler
Soru 18: Arka Plandaki Uygulama
iOS’ta ses çalmayan, konum kullanmayan sıradan bir uygulama arka plana alındı. Kısa süre sonra ne olur?
A: iOS arka planda yalnızca izin verilen işleri (ses, konum, VoIP, planlanmış görevler) sürdürür; diğer uygulamalar askıya alınır, bellek darlığında sonlandırılır. Nedeni sınırlı bellek ve pildir. Android de 8. sürümden beri uzun arka plan işlerini ön plan hizmeti ya da WorkManager ile sınırlar.