---
title: Sinyaller
source: 'https://academia.sh/tr/kurslar/sistem-yonetimi/sinyaller'
course: 'Sistem Yönetimi'
language: tr
updated: '2026-08-17T18:10:04+00:00'
license: 'CC BY-SA 4.0'
---

# Sinyaller

Yedi ağır sürece sonlandırma isteği gönderildiğinde 2'si kabul ediyor, 5'i yok sayıyor; zorlayan sinyalde 7/7 bitiyor ama 2 sürecin temizliği yarıda kesiliyor. Komut her durumda 0 döndürdüğü için beklemeden verilen tanı yedi hedefin yedisinde de yanlış.

Önceki ders bir sinyalin kenarından geçti: uçtermin kapandığında kapanma sinyali oturumun
başına iletildi, kabuk onu kendi işlerine yaydı ve işlerin bir bölümü sinyali **yok saydı**.
Yok saymanın kendisi ölçülmedi. Bu ders sinyalleri doğrudan ele alır.

Ölçtüğü cümle tektir: **sonlandırma isteği bir istektir.** Komutun hatasız dönmesi hedefin
bittiği anlamına gelmez, ve aradaki fark sayılabilir.

## Sinyal Nedir, Ne Değildir

Sinyal, çekirdeğin bir sürece ilettiği **kesme bildirimidir**. İçinde veri taşımaz; yalnız
kimliği vardır. Süreç bir sinyali aldığında üç şeyden biri olur: sürecin o sinyal için
tanımladığı **işleyici** çalışır, sinyal **yok sayılır**, ya da sinyalin **varsayılan eylemi**
uygulanır. Varsayılan eylem sinyalden sinyale değişir — sonlandırmak, durdurmak, sürdürmek ya
da hiçbir şey yapmamak.

Kabuk Programlama kursundaki `trap` tam olarak birinci seçeneği kurar: betiğin sinyal
işleyicisini tanımlar. Buradaki fark bakış yönüdür — orada sinyali **alan** taraf yazıldı,
burada **gönderen** taraf ölçülür.

| Sinyal | Varsayılan eylem | Yakalanabilir mi | Ne için |
|---|---|---|---|
| `SIGHUP` | sonlandır | evet | denetleyen uçtermin gitti; birçok servis bunu yeniden okuma isteği sayar |
| `SIGINT` | sonlandır | evet | uçterminden kesme (`Ctrl+C`) |
| `SIGQUIT` | sonlandır ve döküm al | evet | uçterminden çıkış isteği |
| `SIGTERM` | sonlandır | evet | **sonlandırma isteği** — nazik biçim, varsayılan |
| `SIGKILL` | sonlandır | **hayır** | **zorlayan sinyal** — süreç söz sahibi değildir |
| `SIGSTOP` | durdur | **hayır** | süreci dondurur |
| `SIGCONT` | sürdür | evet | durdurulmuş süreci sürdürür |
| `SIGUSR1`, `SIGUSR2` | sonlandır | evet | anlamı programın kendi sözleşmesindedir |
| `SIGPIPE` | sonlandır | evet | okuyan ucu kapanmış boru hattına yazma |
| `SIGCHLD` | yok say | evet | bir çocuk süreç bitti ya da durdu |

İki satır ötekilerden ayrıdır. `SIGKILL` ve `SIGSTOP` **yakalanamaz, yok sayılamaz ve
engellenemez**; kararı çekirdek verir, süreç haberdar bile olmaz. Bunun bedeli tam olarak
budur: zorlayan sinyalle ölen bir süreç, kendi kapanış yordamını **hiç çalıştıramaz**.

Sinyallerin numaraları da vardır ama numaralar her mimaride aynı değildir. Taşınabilir yazım
**adla** yapılır: `kill -TERM` yazılır, sayı yazılmaz.

## Sinyal Göndermek

Sinyal gönderen komutun adı `kill`'dir ve adı yanıltıcıdır: komut süreç öldürmez, sinyal
iletir. Hangi sinyalin iletildiği seçeneğe bağlıdır, seçenek verilmezse sonlandırma isteği
gönderilir.

```text
$ kill -TERM 1128
$ echo $?
0
$ kill -0 1128           # sinyal gonderme , yalnizca ulasilabilir mi diye bak
$ echo $?
0
$ pkill -TERM -u uygulama kuyruk-isleyici
$ kill -TERM -1014       # eksi isaretli sayi: sinyal SUREC OBEGINE gider
```

Bu döküm **örnektir ve çalıştırılmamıştır.** Dört ayrıntı taşıyor. `kill -0` hiçbir sinyal
göndermez; yalnız hedefin var olup olmadığını ve ona sinyal gönderme yetkisinin bulunup
bulunmadığını sınar — doğrulamanın aracı budur. `pkill` hedefi ada ve kullanıcıya göre seçer;
birinci dersteki ölçü burada geçerlidir, ad bir kimlik değil etikettir. Eksi işaretli sayı
hedefi **süreç öbeğine** çevirir: bir boru hattının tek üyesine değil, tamamına gönderir.
`killall` da ada göre çalışır ve davranışı sistemler arasında değişebildiği için, taşınabilir
betiklerde `pkill` yeğlenir.

En kritik ayrıntı ikinci satırdadır. `kill` komutunun çıkış kodu **sinyalin iletilip
iletilmediğini** bildirir. Hedefin sinyali nasıl karşıladığı, işleyicisinin ne yaptığı, sürecin
bitip bitmediği bu koda **hiç yansımaz**. Kodu 0 gören operatörün "iş bitti" demesi, ölçülmemiş
bir tanıdır.

- **SY15.** Hedef küme, kurgu sunucudaki **sürekli ağır** desenli süreçlerdir.
- **SY16.** Süreçlerin bir bölümü sonlandırma isteğini **yok sayar**; ortak tanımdaki
  `sinyal_yok_sayar` alanı bunu taşır. Zorlayan sinyal yok sayılamaz.
- **SY17.** İsteği kabul eden bir süreç **hemen bitmez**: önce kendi temizliğini yapar.
  Temizlik süresi süreç başına **0 ile 39 saniye** arasındadır.
- **SY18.** `kill` komutunun çıkış kodu her denemede **0**'dır; sinyal iletildi demektir.
- **SY19.** Beklemeden verilen tanı şudur: "komut döndü, hedefler bitti." Yanlış tanı sayısı,
  o anda gerçekte bitmemiş hedeflerin sayısıdır.
- **SY20.** Zorlayan sinyal bütün hedefleri bitirir; isteği kabul edip temizliği süren
  süreçlerin temizliği **yarıda kesilir**.
- **SY21.** İkinci tohum **20260219**'dur.

```python
# --- ortak tanim, birinci dersteki bicimiyle
TOHUM, IKINCI_TOHUM = 20260218, 20260219
KULLANICI = ("kok", "uygulama", "yedek", "izleme")
KOMUT = ("veri-alici", "rapor-uretici", "yedek-gorevi", "olcum-toplayici",
         "kuyruk-isleyici", "onbellek-temizleyici")


def uretec(tohum):
    d = tohum

    def sonraki(n):
        nonlocal d
        d = (d * 1103515245 + 12345) % 2147483648
        return d % n
    return sonraki


def surecler(tohum=TOHUM, sayi=24):
    r = uretec(tohum)
    liste = []
    for i in range(sayi):
        tur = r(10)
        desen = "duz" if tur < 5 else ("ani" if tur < 8 else "agir")
        liste.append({"pid": 1000 + i * 7 + r(5),
                      "kullanici": KULLANICI[r(len(KULLANICI))],
                      "komut": KOMUT[r(len(KOMUT))], "desen": desen,
                      "oncelik": r(11) - 5, "bellek": 20 + r(400),
                      "sinyal_yok_sayar": r(10) < 2})
    return liste


# --- bu dersin katmani: sinyal ve temizlik
def sinyal_gonder(surecler_, sinyal, hedefler):
    """Ortak tanim: `sonlandir` yoksayilabilir , `zorla` yoksayilamaz."""
    biten, direnen = [], []
    for s in surecler_:
        if s["pid"] not in hedefler:
            continue
        if sinyal == "zorla" or not s["sinyal_yok_sayar"]:
            biten.append(s["pid"])
        else:
            direnen.append(s["pid"])
    return {"biten": len(biten), "direnen": len(direnen),
            "direnen_pid": sorted(direnen)}


S = surecler()
HEDEF = {s["pid"] for s in S if s["desen"] == "agir"}
print("hedef:", len(HEDEF), "agir surec")
print("sonlandir:", sinyal_gonder(S, "sonlandir", HEDEF))
print("zorla    :", sinyal_gonder(S, "zorla", HEDEF))
```

```
hedef: 7 agir surec
sonlandir: {'biten': 2, 'direnen': 5, 'direnen_pid': [1014, 1043, 1092, 1108, 1128]}
zorla    : {'biten': 7, 'direnen': 0, 'direnen_pid': []}
```

Yedi ağır sürecin yalnız **2'si** sonlandırma isteğini kabul ediyor, **5'i** direniyor.
Zorlayan sinyalde **7'sinin 7'si** bitiyor. Direnen süreçlerin listesi çıktıda görünmez —
`kill` komutu bu bilgiyi vermez, veremez. Bu, kursun ortak tanımının ikinci bağlayıcı
okumasıdır.

## Beklemenin Ölçüsü

Yukarıdaki iki satır sinyalin nihai sonucudur. Operatör ise sonucu değil, **bir andaki durumu**
görür. Sonlandırma isteğini kabul eden süreç hemen bitmez; açık dosyalarını kapatır, tamponunu
boşaltır, kilidini bırakır. O sırada süreç hâlâ listede durur.

```python
# Onceki blogun uzerine: S, HEDEF, uretec, TOHUM oradan gelir.
def temizlik_ata(surecler_, tohum=TOHUM):
    """Sonlandirma istegini kabul eden surec hemen bitmez: once temizlik yapar."""
    r = uretec(tohum)
    for s in surecler_:
        s["temizlik"] = r(40)              # saniye
    return surecler_


def sonlandirma_denemesi(surecler_, hedefler, bekleme):
    """Istek gonderildi , `bekleme` saniye sonra bakildi. `kill` cikis kodu her
    durumda 0: sinyal ILETILDI demek , hedef BITTI demek degil."""
    biten, temizleniyor, yok_sayan = [], [], []
    for s in surecler_:
        if s["pid"] not in hedefler:
            continue
        if s["sinyal_yok_sayar"]:
            yok_sayan.append(s["pid"])
        elif s["temizlik"] <= bekleme:
            biten.append(s["pid"])
        else:
            temizleniyor.append(s["pid"])
    return len(biten), len(temizleniyor), len(yok_sayan)


temizlik_ata(S)
print("hedef:", len(HEDEF), "surec | `kill` cikis kodu her satirda 0")
print("bekleme  biten  temizleniyor  yok sayan  hayatta  yanlis tani")
for b in (0, 1, 5, 10, 30, 60):
    biten, tmz, yok = sonlandirma_denemesi(S, HEDEF, b)
    print(f"{b:7d}  {biten:5d}  {tmz:12d}  {yok:9d}  {tmz + yok:7d}"
          f"  {len(HEDEF) - biten:11d}")
```

```
hedef: 7 surec | `kill` cikis kodu her satirda 0
bekleme  biten  temizleniyor  yok sayan  hayatta  yanlis tani
      0      0             2          5        7            7
      1      0             2          5        7            7
      5      0             2          5        7            7
     10      1             1          5        6            6
     30      2             0          5        5            5
     60      2             0          5        5            5
```

İlk satır dersin en sert sayısıdır. Komut döndüğü anda hedeflerin **hiçbiri** bitmemiştir;
yanlış tanı **7/7**. Beş süreç isteği yok saydı, ikisi de henüz temizliğini bitirmedi. Çıkış
kodu yine de 0'dır — komut işini yapmıştır, sinyal iletilmiştir.

İkinci okuma bekleme sütunundadır. Beş saniye beklemek hiçbir şey değiştirmiyor; onuncu
saniyede **1**, otuzuncu saniyede **2** süreç bitiyor. Otuzdan sonra hiçbir şey değişmiyor:
kalan **5** süreç isteği yok sayıyor ve **ne kadar beklenirse beklensin bitmeyecek**. Beklemek
temizliği tamamlar, direnci çözmez. Bu ayrım doğru yordamı belirler.

Doğru sıra dört adımdır: **isteği gönder**, **bekle**, `kill -0` ile **doğrula**, ancak hâlâ
duranı **zorla**. Servis yöneticileri de bunu yapar ve bekleme süresi birim tanımında ayarlanır
bir değerdir; o taraf bu kursun sonraki konusudur.

Bekleme süresinin seçimi bu tabloya bakılarak yapılır ve iki yönde de bedeli vardır. Kısa
seçilirse temizliğini sürdüren süreçler gereksiz yere zorlanır; tabloda beş saniyede zorlamak,
onuncu ve otuzuncu saniyede kendiliğinden bitecek iki süreci kesmek demektir. Uzun seçilirse
direnen süreçler boşuna beklenir: otuzuncu saniyeden sonra tabloda hiçbir sütun değişmez,
altmış saniye beklemek yalnız arızayı uzatır. Ölçülmüş bir eşik yoksa seçilen süre bir varsayım
olarak kalır ve o varsayım her iki yönde de yanlış tanı üretir.

## Ulaşmayan ve Bekleyen Sinyal

Direnç, sinyalin işe yaramamasının tek nedeni değildir. Üç durum daha vardır ve üçü de aynı
görüntüyü üretir: komut 0 döndürür, hedef durur.

Birincisi **bekleyen sinyaldir**. Durdurulmuş bir sürece gönderilen sonlandırma isteği hemen
işlenmez; süreç kod yürütmediği için sinyal **bekler**. Önceki dersteki durdurulmuş işler tam
olarak bu durumdadır: istek iletilir, kuyruğa yazılır ve süreç `SIGCONT` ile sürdürülene kadar
orada kalır. Zorlayan sinyal bu kuralın dışındadır; onu çekirdek uygular ve sürecin kod
yürütmesini beklemez. Bir işi gerçekten durdurmanın taşınabilir yolu bu yüzden önce sürdürüp
sonra istek göndermektir.

İkincisi **engellenmiş sinyaldir**. Bir süreç kritik bir bölüme girerken belirli sinyalleri
geçici olarak engelleyebilir; engel kalkana kadar sinyal bekler. Dışarıdan bakan operatör
engellenmiş sinyal ile yok sayılmış sinyali ayırt edemez — ikisinde de hiçbir şey olmaz.

Üçüncüsü **yanlış hedeftir**. Süreç numaraları yeniden kullanılır: bir süreç bittikten sonra
aynı numara başka bir sürece verilebilir. Numarayı bir dosyadan okuyup gönderen betikler bu
yüzden numarayı doğrulamadan kullanmamalıdır; `kill -0` ile varlığı sınamak yeterli değildir,
sınanan şey numaranın **kime** ait olduğudur.

Bu üç durumun ortak sonucu şudur: sinyal göndermek bir olay değil, bir **istektir** ve isteğin
sonucu yalnız hedefe bakarak öğrenilir. Bir kapanış yordamının doğru yazılmış olması da
gönderen tarafı ilgilendirir — servislerin yeniden yapılandırılmasında `SIGHUP` kullanılması
bu yüzden yaygındır: servis yeniden başlatılmadan yapılandırmasını yeniden okur ve açık
bağlantıları düşürmez. Aynı sinyalin başka bir programda varsayılan eylemi sonlandırmaktır;
anlamı sinyalin değil, **programın sözleşmesinindir**.

## Zorlamanın Bedeli

Bekleme adımını atlayıp doğrudan zorlayan sinyali göndermek çekici bir kısayoldur: sonuç
kesindir, hedeflerin hepsi biter. Kesinliğin bir bedeli vardır ve o da sayılabilir.

```python
# Onceki bloklarin uzerine: S, HEDEF, sonlandirma_denemesi, sinyal_gonder,
# temizlik_ata, surecler, IKINCI_TOHUM.
z = sinyal_gonder(S, "zorla", HEDEF)
kesilen = [s["pid"] for s in S if s["pid"] in HEDEF
           and not s["sinyal_yok_sayar"] and s["temizlik"] > 0]
print("dogrudan zorlayan sinyal:", z["biten"], "/", len(HEDEF), "bitti")
print("  yarida kesilen temizlik:", len(kesilen), "surec")
print("dogru sira (istek , bekle , dogrula , zorla):")
biten, tmz, yok = sonlandirma_denemesi(S, HEDEF, 30)
print("  30 saniye sonra kendiliginden biten:", biten,
      "| zorlanmasi gereken:", tmz + yok)
print()
for tohum in (TOHUM, IKINCI_TOHUM):
    S2 = temizlik_ata(surecler(tohum), tohum)
    H2 = {s["pid"] for s in S2 if s["desen"] == "agir"}
    g = sinyal_gonder(S2, "sonlandir", H2)
    b0 = sonlandirma_denemesi(S2, H2, 0)[0]
    b30 = sonlandirma_denemesi(S2, H2, 30)[0]
    print(f"tohum {tohum}: hedef {len(H2)} | istegi kabul eden {g['biten']}"
          f" | 0 sn sonra biten {b0} | 30 sn sonra biten {b30}"
          f" | yanlis tani {len(H2) - b0}")
```

```
dogrudan zorlayan sinyal: 7 / 7 bitti
  yarida kesilen temizlik: 2 surec
dogru sira (istek , bekle , dogrula , zorla):
  30 saniye sonra kendiliginden biten: 2 | zorlanmasi gereken: 5

tohum 20260218: hedef 7 | istegi kabul eden 2 | 0 sn sonra biten 0 | 30 sn sonra biten 2 | yanlis tani 7
tohum 20260219: hedef 5 | istegi kabul eden 5 | 0 sn sonra biten 0 | 30 sn sonra biten 4 | yanlis tani 5
```

Doğrudan zorlamak **7/7** sonuç veriyor, ve **2 sürecin temizliği yarıda kesiliyor**. Kesilen
temizlik soyut bir kayıp değildir: tamponu boşaltmamış bir süreç yazdığını sanan veriyi
kaybeder, kilidini bırakmamış bir süreç geride bir kilit dosyası bırakır, geçici dizinini
silmemiş bir süreç onu diskte bırakır. Bu üç sonucun hiçbiri `kill` çıktısında görünmez ve
üçü de sonraki çalıştırmada başka bir arıza olarak ortaya çıkar.

Bekleyerek yapılan sıralamada aynı iki süreç kendiliğinden bitiyor ve yalnız **5** hedef
zorlanıyor. Fark iki süreçlik değildir; **iki temiz kapanışlıktır.**

İkinci tohumda hedef sayısı 5'e iniyor ve isteği kabul edenlerin sayısı 2 yerine **5** oluyor
— kompozisyon tamamen değişiyor. Değişmeyen tek şey ilk sütundur: **her iki tohumda da komut
döndüğü anda biten hedef sayısı 0'dır** ve beklemeden verilen tanı bütün hedeflerde yanlıştır.
Kaç sürecin direneceği kurguya bağlıdır; komutun dönmesinin hiçbir şey söylemediği değildir.

Modelin dışında kalan bir sınır da not edilmelidir: zorlayan sinyal burada her hedefi
bitiriyor, ama gerçek bir sistemde çekirdek çağrısının içinde kesilemez uykuda bekleyen bir
süreç ona da yanıt vermez. O durumda süreç `D` durumunda görünür ve tek çare bekleyişin
nedenini gidermektir.

## Özet

- Sinyal veri taşımayan bir kesme bildirimidir; süreç onu yakalayabilir, yok sayabilir ya da
  varsayılan eyleme bırakabilir. `SIGKILL` ve `SIGSTOP` yakalanamaz, engellenemez.
- `kill` komutunun çıkış kodu sinyalin **iletildiğini** bildirir, hedefin bittiğini değil.
  Doğrulamanın aracı `kill -0`'dır.
- Yedi ağır hedeften sonlandırma isteğini yalnız **2'si** kabul ediyor, **5'i** yok sayıyor;
  zorlayan sinyalde **7/7** bitiyor.
- Komut döndüğü anda biten hedef sayısı **0**'dır: yanlış tanı **7/7**. Onuncu saniyede 1,
  otuzuncu saniyede 2 süreç biter; otuzdan sonra hiçbir şey değişmez.
- Doğrudan zorlamak **2 sürecin temizliğini yarıda keser**; beklemeli sırada aynı iki süreç
  temiz kapanır ve yalnız 5 hedef zorlanır. Doğru sıra istek, bekleme, doğrulama, zorlamadır.

## Sonraki Adım

Bu ders süreci durdurmayı ölçtü. Durdurmak her zaman doğru yanıt değildir: ağır bir süreç
gerekli bir iş yapıyor olabilir ve istenen şey onu bitirmek değil, **yavaşlatmaktır**. Sonraki
ders öncelik değerini ele alır ve tek bir soruyu sayar: bir sürecin önceliğini değiştirmenin
gerçekten görülebilir etkisi ne kadardır, ve değişen sütun ile değişen davranış aynı şey midir.
