Bölüm 3: Süreçler

İşletim Sistemleri · Çalışma Soruları
Süreç kavramıfork ve execSonlandırmaDurumlar ve PCBÇizelgelemeIPC ve borularYarış durumuSemaforlar
Sercan KÜLCÜ

Ç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.)

P0

Başta tek süreç: P0.

P0P1

fork(): P0, P1’i doğurur; ikisi de 3. satırdan devam eder.

P0P1P2P3

İlk fork(): P0 → P2, P1 → P3. P2 ve P3’te dönüş 0 → && yanlış; ikinci fork’u ve gövdeyi atlarlar.

P0P1P2P3P4P5

P0 ve P1’de ilk sonuç ≠ 0 → ikinci fork(): P0 → P4, P1 → P5. P4, P5’te sonuç 0 → koşul yanlış.

P0P1P2P3P4P5P6P7

Koşul yalnızca P0 ve P1’de doğrudur: gövdedeki fork ile P0 → P6, P1 → P7.

P0P1P2P3P4P5P6P7

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. h iki 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 waitpid ile ç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.
  • waitpid durumu 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?

YeniSonlandıHazırÇalışıyorBekliyor

Beş durumlu model: Yeni, Hazır, Çalışıyor, Bekliyor, Sonlandı.

YeniSonlandıHazırÇalışıyorBekliyor

PCB ayrılıyor, adres alanı hazırlanıyor: Yeni.

YeniSonlandıHazırÇalışıyorBekliyor

Hazır kuyruğuna girer (1. kez).

YeniSonlandıHazırÇalışıyorBekliyor

Çizelgeleyici seçti → Çalışıyor.

YeniSonlandıHazırÇalışıyorBekliyor

Süreç hiçbir şey beklemiyor, yalnızca sırası geçti: Bekliyor’a değil Hazır’a döner (2. kez).

YeniSonlandıHazırÇalışıyorBekliyor

Yeniden seçildi → Çalışıyor.

YeniSonlandıHazırÇalışıyorBekliyor

Bir olayı (çocuğun bitişi) bekliyor: CPU’yu bırakır.

YeniSonlandıHazırÇalışıyorBekliyor

Olay gerçekleşti: doğrudan Çalışıyor’a değil, önce Hazır’a geçer (3. kez). Bekliyor → Çalışıyor oku yoktur.

YeniSonlandıHazırÇalışıyorBekliyor

Seçildi → Çalışıyor.

YeniSonlandıHazırÇalışıyorBekliyor

read(): satır gelene kadar bloke olur → Bekliyor (2. kez).

YeniSonlandıHazırÇalışıyorBekliyor

Klavye kesmesi süreci uyandırır: Hazır (4. kez).

YeniSonlandıHazırÇalışıyorBekliyor

Seçildi → Çalışıyor.

YeniSonlandıHazırÇalışıyorBekliyor

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
dilimek yük = s / (q + s)bekleme = 5s + 4q
2 ms0,1 / 2,1 = %4,760,5 + 8 = 8,5 ms
20 ms0,1 / 20,1 = %0,500,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?

boru tamponu (çekirdekte)açık yazma ucu: 1

pipe: okuma ucu 3, yazma ucu 4 (ilk boş numaralar). Tampon boş.

boru tamponu (çekirdekte)açık yazma ucu: 2

fork: çocuk iki ucu da miras alır; şimdi iki yazma ucu açık.

boru tamponu (çekirdekte)açık yazma ucu: 1

Çocuk yazma ucunu, ebeveyn okuma ucunu kapatır. Çocuk boş boruda read çağırırsa veri gelene kadar bloke olur.

boru tamponu (çekirdekte)isletim␣sisaçık yazma ucu: 1

Ebeveyn 11 baytı tek write ile yazar (PIPE_BUF’tan küçük yazma bölünmez).

boru tamponu (çekirdekte)isletim␣sisaçık yazma ucu: 1read → 4buf:isle

read en çok 4 bayt alır: "isle".

boru tamponu (çekirdekte)isletim␣sisaçık yazma ucu: 1read → 4buf:tim␣

Sonraki 4 bayt: "tim ".

boru tamponu (çekirdekte)isletim␣sisaçık yazma ucu: 1read → 3buf:sis

Kalan yalnızca 3 bayt: read 3 döndürür, beklemez.

boru tamponu (çekirdekte)isletim␣sisaçık yazma ucu: 0

Ebeveyn yazma ucunu kapatır: borunun açık yazma ucu kalmadı. (Bu adım okumalardan önce de olabilir; çıktı değişmez.)

boru tamponu (çekirdekte)isletim␣sisaçık yazma ucu: 0read → 0buf:

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ımR1R2count
Ü.LOAD55
T.LOAD555
Ü.ADD655
T.SUB645
Ü.STORE646
T.STORE644

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.)

mutex1empty2full0tampon (N = 2)uyuyan:yok

Tampon boş: empty = 2 boş yuva, full = 0 dolu yuva.

mutex1empty2full0tampon (N = 2)uyuyan:T (full’de)

T: down(&full), full = 0 → T uyur. Meşgul bekleme yok.

mutex1empty1full0tampon (N = 2)Auyuyan:yok

Ü A’yı koyar: empty 2 → 1. up(&full) uyuyan T’yi uyandırır; T’nin down’ı tamamlanır, full 0 kalır.

mutex1empty0full1tampon (N = 2)ABuyuyan:yok

T henüz çalışmadı; Ü B’yi de koyar: empty 0, full 1.

mutex1empty0full1tampon (N = 2)ABuyuyan:Ü (empty’de)

Ü C için down(&empty): tampon dolu → Ü uyur.

mutex1empty0full1tampon (N = 2)Buyuyan:yok

T çalışır, A’yı alır. up(&empty) uyuyan Ü’yü uyandırır; empty 0 kalır.

mutex1empty0full2tampon (N = 2)BCuyuyan:yok

Ü C’yi koyar: full 2.

mutex1empty1full1tampon (N = 2)Cuyuyan:yok

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.

Son

Bölüm 3: Süreçler: Çalışma Soruları
Konu anlatımı: Süreçler sunumu · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.