Linux prosesleri nasıl yönetir?

Bu flood’da Linux işletim sisteminin çalıştırdığı proseslerle etkileşiminden bahsedeceğim.

Linux programlardan prosesler oluşturur ve bu prosesleri çalıştırır. Birçok program çalıştırıldığında sadece tek bir proses oluşturur ancak bazı programlar farklı amaçlar için birden fazla proses oluşturabilirler. Örneğin Google Chrome, açılan her bir tab için yeni bir proses oluşturur. Böylece ziyaret edilen sitelerden (tab) biri kilitlendiğinde programı yeniden açıp kapatmak gerekmez, sadece ilgili tab’daki proses öldürülerek çalışmaya devam edilebilir.

Linux, bütün proseslere birer ID verir ve prosesler Parent Process adı verilen başka bir proses tarafından oluşturulur. Çalışan bütün prosesleri göstermek için ps -ef komutu kullanılabilir ve aşağıdaki gibi bir çıktı oluşturur.

Linux çekirdeği açılış sırasında gerekli hazırlıkları tamamladıktan sonra ID’si 1 olan init prosesini oluşturur o da başka prosesleri oluşturur. Aşağıda sshd (SSH Daemon) filtrelenerek sshd prosesinin init tarafından yaratıldığı gösterilmiştir.

Yukarıda çıktıda görüldüğü gibi PID'si 948 olan sshd, PID'si 1 olan init tarafından yaratılmıştır. Sonra da sırasıyla 948, 1506'yı o da 1529 PID'li prosesi yaratmıştır. ps axf veya pstree ile bahsedilen hiyerarşi aşağıdaki gibi görülebilir.

Yukarıda görüldüğü üzere ssh ile bağlanılan bash prosesi sshd tarafından yaratılmıştır. Aynı şekilde bash üzerinden çalıştırılacak bütün proseslerin parent prosesi bash olacaktır. Aşağıdaki örnekte 1'de koşturulan ping prosesinin parent prosesi bash olmuştur.

Linux, çalıştırdığı prosesin başarı ile sonuçlanıp sonuçlanmadığını çıkış koduna (Exit Code) bakarak anlayabilir. Çıkış kodu 0 olan proses başarı ile sonuçlanmış, 0 dışındaki bir çıkış kodu ile çıkan proses ise çeşitli nedenlerle başarısız olmuştur.

bash kabuğunda echo $? komutu verilerek son çalıştırılan programın çıkış kodu alınabilir. Aşağıdaki örnekte bir klasör iki kere yaratılmak istenmiştir. İlk deneme başarılı olmuş ikinci deneme ise daha önce ilgili klasör bulunduğu için başarısız olmuştur.

Programların çıkış kodları ile ilgili genel bir standart bulunmamakla birlikte yukarıdaki örnekte olduğu gibi uygulamanın iş katmanındaki hatalarda (zaten var olan bir klasörü yaratmaya çalışma veya olmayan bir dosyanın içeriğini döktürme) çıkış kodu genelde 1 olarak verilir.

Prosesin kendi isteği ile sonlanmadığı, işletim sistemi veya kullanıcı tarafından bir sinyalle sonlandırıldığı durumlarda ise çıkış kodu Linux’taki sinyal koduna 128 eklenerek bulunur. Örneğin prosese SIGKILL - 9 sinyali gönderilirse çıkış kodu 128 + 9 = 137 olur.

Aşağıda tail prosesine SIGTERM - 15 sinyali gönderildiğinde çıkış kodunun 128 + 15 = 143 olduğu görülmektedir. Ek olarak memory sınırı verildiğinde veya sistemde Swap açık değilken çok fazla memory tüketen prosesler Linux tarafından 137 yani SIGKILL ile öldürülürler.

Linux’ta her şeyin bir dosya olduğunu muhakkak duymuşsunuzdur. Prosesler de Linux tarafından /proc altındaki dosya sisteminden yönetilirler. Linux her bir proses için prosesin PID'si ile /proc klasörü altında bir klasör oluşturur, bu klasörde prosesle ilgili bilgiler bulunur.

Aşağıdaki ekran çıktısında bir session’da APP_PURPOSE=Demo ortam değişkeni verilerek başlatılan tail -f /dev/null prosesi ile ilgili bilgiler (uygulama parametreleri, bütün ortam değişkenleri) /proc dosya sisteminden ikinci ekranda döktürülmüştür.

Linux her proses için üç file descriptor - fd yaratır. İlki stdin/fd 0, ikincisi stdout/fd 1 üçüncüsü ise stderr/fd 2'dır . stdin klavyeden girdi alacak, stdout ve stderr ise ekrana çıktı verecek şekilde ayarlanır. Aşağıda bir örnek gösterilmiştir.

Linux’ta yönlendirme yapılırken kullanılan 1, 2 rakamları fd'leri ifade eder. cmd >> log-output 2>&1 ile önce cmd'nin stdout'u log-output'a, sonra da 2>&1 komutu ile stderr/fd 2, stdout/fd 1'e yönlendirilmiş böylece stdout ve stderr aynı dosyaya yazılmıştır.

En son olarak da C ile yazılan ve terminalden iki sayı okuyarak bunları toplayıp sonucu ekranda gösteren sum adlı proses çalışıyorken sum programını yanlışlıkla diskten silelim ve sonra da /proc/PID/exe adresinden kopyalayarak geri döndürelim.