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.