Dosya Kilitleri
Önceki XIII. Oylum - Düşük Seviyeli Girdi ve Çıktı Sonraki
Dosya Kilitleri
Kalan fcntl komutları, aynı anda çok sayıda süreci çalışabilen uygulamalarda bir sürecin aynı dosyaya hataya eğilimli bir yolla aynı anda erişimini engelleyen dosya kilitleme desteği içindir.
Bir ayrıcalıklı ya da yazma kilidi sürecin dosyanın belli bir parçasına yazma amacıyla ayrıcalıklı erişimini mümkün kılar. Bir yazma kilidi etkinken başka bir süreç dosyanın kilitli bölümünü kilitleyemez.
Bir paylaşımlı veya okuma kilidi başka bir sürecin dosyanın okuma kilitli parçasında bir yazma kilidi isteği yapmasına engel olur, ancak bir okuma kilidi isteğini engellemez.
Aslında read ve write işlevleri dosyanın bir yerinde bir kilit var mı, yok mu diye bakmaz. Çok sayıda süreç arasında dosya kilitlemesini etkili olarak kullanmak istiyorsanız, kilitlerin durumunu doğrudan fcntl çağrıları ile saptadıktan sonra işlemi yapıp yapmamaya karar vermelisiniz.
Kilitler süreçlerle ilişkilendirilir. Bir süreç belirtilen bir dosyanın her baytı için sadece bir çeşit kilitleme yapabilir. Bir dosya ile ilişkili dosya tanıtıcılardan herhangi biri kapatıldığında, diğer dosya tanıtıcılar açık bile olsa, süreçte bu dosya ile ilişkilendirilmiş tüm kilitler iptal edilir. Benzer şekilde bir süreç sonlandığında da kilitler iptal edilir, ayrıca fork ile oluşturulan alt süreçler bu kilitleri miras almazlar.
Bir kilit oluşturulurken ne çeşit kilidin nerede oluşturulacağını belirtmek için struct flock yapısı kullanılır. Bu veri türü ve kilitlerle ilgili fcntl makroları fcntl.h başlık dosyasında bildirilmiştir.
struct flock
veri türü
Bu yapı fcntl işlevi ile bir dosya kilidini yapılandırmada kullanılır. Şu üyelere sahiptir:
short int l_type
Kilidin türünü belirtir; F_RDLCK, F_WRLCK veya F_UNLCK makrolarından biri olabilir:
F_RDLCK
Bir okuma kilidi (ya da paylaşımlı kilit) belirtir.
F_WRLCK
Bir yazma kilidi (ya da ayrıcalıklı kilit) belirtir.
F_UNLCK
Bölgeden kilidin kaldırılmasını belirtir.
short int l_whence
fseek veya lseek işlevinin nereye veya nereden argümanında kullanıldığı gibi dosya konumunun nereye göre belirlendiğini belirtir. Değeri SEEK_SET, SEEK_CUR veya SEEK_END olabilir.
off_t l_start
Kilidin uygulanacağı bölümün başlangıcından uzaklığını belirler ve yapının l_whence üyesinde belirtilen noktaya göre bayt cinsinden ifade edilir.
off_t l_len
Kilitlenecek bölgenin uzunluğunu belirler. 0 değerinin özel bir anlamı vardır, bölgenin dosyanın sonuna kadar genişleyebileceğini belirtir.
pid_t l_pid
Kilidi tutan sürecin süreç kimliğidir. Bu alan kilidi oluştururken yoksayılır, sadece fcntl işlevinin F_GETLK komutu ile yapılan çağrısı ile doldurulur.
int F_GETLK
makro
Bu makro fcntl işlevinin komut argümanında kullanılır ve bir kilit hakkında bilgi istendiğini belirtir. Bu komut fcntl işlevinde struct flock * türünde üçüncü bir argüman gerektirir:
fcntl (dosyatanıtıcı, F_GETLK, kilit_gst)
kilit_gst argümanı ile belirtilen yerde bir kilit varsa, kilit ile ilgili bilgi *kilit_gst'ye yazılır. Belirtilen yeni kilitle uyumluysa mevcut kilitler raporlanmaz. Bu bakımdan, hem okuma hem de yazma ile ilgili kilitleri bulmak için F_WRLCK türünde bir kilit, sadece yazma ile ilgili kilitleri bulmak için ise, F_RDLCK türünde bir kilit belirtmelisiniz.
kilit_gst tarafından belirtilen bölgeyi etkileyen birden fazla kilit varsa bunlardan sadece biri raporlanır. kilit_gst yapısının l_whence üyesine SEEK_SET atanır, l_start ve l_len üyelerine de kilitli bölgeyi tanımlayan değerler atanır.
Bir kilit yoksa, kilit_gst yapısının sadece l_type üyesine F_UNLCK atanır.
fcntl işlevinin bu komut ile ilgili dönüş değeri hata oluştuğunu belirten -1 değeri dışında belirsizdir. Aşağıdaki errno hata durumları bu komut için tanımlanmıştır:
EBADF
dosyatanıtıcı argümanı geçersiz
EINVAL
Ya kilit_gst argümanı geçerli bir kilit belirtmiyor ya da dosyatanıtıcı kilitleri desteklemiyor
int F_SETLK
makro
Bu makro fcntl işlevinin komut argümanında bir kilit oluşturmak ya da kaldırmak amacıyla kullanır. Bu komut fcntl işlevinde struct flock * türünde üçüncü bir argüman gerektirir:
fcntl (dosyatanıtıcı, F_SETLK, kilit_gst)
Süreç dosyanın belirtilen bölgesinde bir kilide sahipse eski kilit yenisiyle değiştirilir. Mevcut bir kilidi F_UNLCK türünde bir kilit belirterek kaldırabilirsiniz.
Kilit oluşturulamazsa fcntl -1 değeriyle döner. Bu işlev başka bir sürecin kilidi bırakması için beklemez. fcntl işlevi başarılı olduğundan -1'den farklı bir değerle döner.
Aşağıdaki errno hata durumları bu komut için tanımlanmıştır:
EAGAIN
EACCES
Dosya üzerindeki başka bir kilit tarafından engellendiğinden kilit oluşturulamıyor. Bazı sistemler bu durumda EAGAIN kullanırken başkaları EACCES kullanır; yazılımınızda her ikisini de beklemelisiniz. (GNU sistemi daima EAGAIN kullanır.)
EBADF
dosyatanıtıcı argümanı geçersiz; ya okuma erişimi için açılmamış dosyatanıtıcı için bir okuma kilidi istemişsinizdir ya da yazma erişimi için açılmamış bir dosyatanıtıcı için yazma kilidi istemişsinizdir.
EINVAL
Ya kilit_gst argümanı geçerli kilit bilgisi içermiyor ya da dosyatanıtıcı ile ilişkili dosya kilitleri desteklemiyor.
ENOLCK
Sistemde dosya kilidi özkaynakları tükendi; dosya kilidi istenen yerde zaten fazlasıyla dosya kilidi var
İyi tasarlanmış dosya sistemleri bu hatayı hiç raporlamaz, çünkü dosya kilitleri ile ilgili bir sınır yoktur. Yine de, bir dosya sisteminin ağ üzerinden eriştiği başka bir dosya sistemi bu hatayı verebileceğinden bu hatayı hesaba katmanız gerekir.
int F_SETLKW
makro
Bu makro fcntl işlevinin komut argümanında bir kilit oluşturmak ya da kaldırmak amacıyla kullanır. F_SETLK komutu gibi olmakla birlikte farklı olarak kilidi ayırana ya da kilit serbest kalıncaya kadar süreci bekletir.
Bu komut da F_SETLK komutu gibi struct flock * türünde bir argüman gerektirir.
F_SETLK komutu için fcntl işlevindeki hata durumlarına ek olarak aşağıdaki hata durumları bu komut için tanımlanmıştır:
EINTR
İşlev beklerken bir sinyal ile durduruldu. Bkz. Sinyallerle Kesilen İlkeller.
EDEADLK
Belirtilen bölge başka bir süreç tarafından kilitlenmiş. Ama süreç, başka sürecin kilitlediği bölgeyi kendisi kilitleyene dek bekler, bu da kilit isteğinin sonsuza kadar beklenmesi anlamına gelebilir. Sistem tüm durumlarda bu hatanın saptanmasını garanti etmez ama eğer bu konuda uyarılmışsanız, şanslısınız demektir.
Dosya kilitlemenin faydalı olduğu bir duruma örnek olarak, bir yazılımın çok sayıda kullanıcı tarafından aynı anda çalıştırıldığını ve bu süreçlerin durum bilgisini ortak bir dosyaya yazdıklarını varsayabiliriz. Bu tür bir örnek, oyuncuların aldıkları puanları bir dosyaya kaydeden oyunlar olabilir. Buna başka bir örnek de hesap bilgilerini ve kullanımlarını kaydeden bir yazılım olabilir.
Bir yazılımın çok sayıda kopyasının bir dosyaya aynı anda yazması dosya içeriğinin karışmasına sebep olur. Bu çeşit sorunların oluşması, dosyaya yapılacak bir yazma işleminden önce bir yazma kilidi oluştururarak önlenebilir.
Yazılımın dosyayı tutarlı bir durumda iken okuması önemliyse bir okuma kilidi kullanılabilir. Bir okuma kilidinin varlığı başka bir sürecin dosyanın bir bölümünü yazmak için kilitlemesini önler.
Dosya kilitlerinin bir dosyaya erişimi denetlemek için "isteğe bağlı" bir protokol olduğunu unutmayın. Kilitleme protokolünü kullanmayan başka süreçlerin dosyaya erişimi hala mümkün olacaktır.
Önceki Üst Ana Başlık Sonraki
Dosya Durum Seçeneklerinin Saptanması Başlangıç Sinyallerle Sürülen Girdi
Bir Linux Kitaplığı Sayfası