Unix/Linux’ta Bir Proses Yaratmak ve Copy on Write
Bu flood’da Unix/Linux’ta yeni bir process’in nasıl yaratıldığını, Virtual Memory’yi ve akıl dolu Copy on Write kavramını anlatacağım.
Unix/Linux’ta terminalden bir programın çalıştırılması, Apache web sunucunun istekleri karşılamak için yeni bir worker yaratması durumunda yeni bir proses yaratılır. Bu işlem için öncelikle fork
sistem çağrısı ile parent proses bire bir klonlanarak child proses oluşturulur. Daha sonra ihtiyaca bağlı olarak (ve genellikle ihtiyaç bu olur) child proses exec
çağrısı ile yeni bir binary ile değiştirilir.
Örneğin bash
kabuğu üzerinden ls
komutu verdiğimizde, bash
öncelikle fork
ile kendi klonunu çıkarır, sonra exec
ile child prosesi ls
binary dosyası ile replace eder. Bu noktada parent, child'ın sonlanmasını bekleyebilir, bunu da wait
sistem çağrısı ile yapar.
Aşağıdaki görselde bu durum görselleştirilmiştir.
Bu noktada aklımıza ls
çalıştırmak için neden bash
gibi koca bir programı klonladığımız noktasının takılmış olması gerekir :) Burada bir verimsizlik var gibi ama öyle olsaydı bu flood olmazdı dediğinizi duyar gibiyim :) Aslına bakılırsa fork
ve exec
ilk uygulandığında bu verimsizlik gerçekten de vardır fakat sonradan geliştirilen Copy on Write yöntemi ile bu prosedür optimize edilmiştir.
Şimdi Copy on Write’ın ne olduğuna yukarıdaki örnek üzerinden bakalım. fork
çağrısının prosesi bir bütün olarak klonladığını söylemiştik. Copy on Write tekniği sayesinde bu klonlama işlemi çok hızlı gerçekleşir çünkü bu teknik sayesinde parent ve child proseslerden herhangi biri bir hafıza alanını değiştirmedikleri sürece (write) ortak olarak kullanırlar. Bu durumda fork
çağrısı sonucunda aslında parent prosesin kullandığı hafıza alanları ortak kullanılabilir ve read-only olarak işaretlenir. Parent veya child ortak kullandıkları hafıza alanlarında bir değişiklik yapmak istediklerinde (örneğin child exec
ile yeni bir binary yüklemek istediğinde) değişikliği yapmak isteyen proses için hafıza alanının yeni bir kopyası çıkarılır ve değişiklik kendisine tahsis edilen bu hafıza alanında yerine getirilir.
CoW tekniği için hemen hemen bütün işletim sistemleri Virtual Memory kullanmaktadır. Virtual Memory ile işletim sistemleri fiziksel hafızaya direkt ulaşmak yerine, bu hafızayı sanal hafızaya mapleyerek kullanırlar. Bu tekniğin ileride anlatacağım birçok faydası vardır.
Memory Management Unit (MMU) adı verilen hardware fiziksel ve sanal hafıza adresleri arasında dönüşüm yapar.
Virtual Memory ve CoW ile birlikte işletim sistemleri hafızayı çok etkin bir biçimde kullanabilmektedir. Benzer bağımlılıkları (Linux .so ya da Windows .dll) kullanan X ve Y uygulamaları olduğunu düşünelim. X uygulamasının A ve B’ye, Y ise B ve C’ye bağımlı olsun. Önce X uygulamasını çalıştıran işletim sistemi, Y uygulamasını hafızaya yüklerken Virtual Memory’de Y’nin bağımlılıklarınadn B’nin zaten varolduğunu görür ve ilgili hafıza sayfasını shared
ve read-only
olarak işaretleyerek yükleme işlemine devam eder.
Yukarıdaki örneğe benzer şekilde hafızada 50 MB yer kaplayan bir prosesten 10 adet çalıştırmak ortak kullanılan ve programın çalışması sırasında değişmeyen hafıza alanlarından dolayı 50 x 10 = 500 MB yerine daha az yer kaplar.
İlerleyen flood’larda Virtual Memory’ye ve sağladığı nimetlere tekrar döneceğiz.