[Makale] C’nin Standart Dosya Fonksiyonlarının Uyguladığı Tamponlama Mekanizması
Standart C fonksiyonlarını kullanmadan bir dosyanın her byte’ı üzerinde sırasıyla işlem yapmak isteyelim. Herhalde ilk akla gelecek yöntem doğrudan işletim sisteminin sistem fonksiyonlarını çağırmak olacaktır. Örneğin UNIX/Linux sistemlerinde dosyayı read fonksiyonuyla (Windows sistemlerinde ReadFile fonksiyonuyla) byte byte aşağıdaki gibi okuyabiliriz:
int fd;
ssize_t result;
unsigned char ch;
if ((fd = open("test", O_RDONLY)) < 0) {
perror("open");
exit(EXIT_FAILURE);
}
while ((result = read(fd, &ch, 1)) > 0) {
/* Okunan byte işleniyor */
}
if (result < 0) {
perror("read");
exit(EXIT_FAILURE);
}
close(fd);
[Makale] Programların Komut Satırı Argümanları
İşletim sistemi tarafından prosese geçirilen komut satırı argümanları program içerisinden çeşitli biçimlerde elde edilebilmektedir. En yaygın yöntem komut satırı argümanlarının programın başlangıç fonksiyonunun parametrelerinden elde edilmesidir. Örneğin, C ve C++’ta komut satırı argümanları main fonksiyonuna parametre olarak geçirilirler. Bu dillerin standartlarına göre programın başlangıç noktasını (entry point) belirten main fonksiyonunun parametrik yapısı ve geri dönüş değeri aşağıdaki iki durumdan biri biçiminde olmalıdır:
int main(void) { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }
[Makale] UNIX/Linux ve Windows Sistemlerinde Stdin, Stdout ve Stderr Dosyaları
Yalnızca UNIX/Linux sistemlerinde değil modern işletim sistemlerinin çoğunda aygıtlar birer dosyaymış gibi ele alınmaktadır. Örneğin klavye ve ekran -aslında birer dosya olmadığı halde- işletim sistemi tarafından sanki birer dosyaymış gibi işleme sokulurlar. Aygıtlara ilişkin bu tür dosyalar için de birer dosya betimleyicisi ve dosya nesnesi vardır. Bu betimleyicilerle işlem yapıldığında işletim sisteminin dosya alt sistemi aslında bu dosyaların birer aygıta ilişkin olduğunu anlar ve okuma/yazma amacıyla o aygıtlara yönelir. UNIX türevi sistemlerdeki çokbiçimliliği (polymophism) andıran bu tasarıma Sanal Dosya Sistemi (Virtual File System) denilmektedir.
[Blog] C#'taki Yapı ve Sınıf Nesneleri Nerede Yaratılıyor?
Pek çok C# programcısının sınıf ve yapı kavramlarıyla stack ve heap kavramlarını yanlış bir biçimde ilişkilendirdiğini görüyorum. Örneğin, “yapı nesneleri stack’te sınıf nesneleri heap’te tutulur” biçiminde yanlış anlaşılmaya yol açacak bilgiler veren yerli ve yabancı çok sayıda yazı ve makaleyle karşılaştım. Konuya biraz açıklık getirmek istiyorum.
[Makale] UNIX/Linux Sistemlerinde Dosya Betimleyicilerinin Anlamı
UNIX/Linux sistemlerinde her prosesin proses tablosu yoluyla erişilen bir dosya betimleyici tablosu (file descriptor table) vardır. Dosya betimleyici tablosu bir gösterici dizisi biçimindedir. Betimleyci tablo içersindeki her gösterici açılmış bir dosyanın bilgilerinin tutulduğu ve ismine dosya nesnesi (file object) denilen bir veri yapısını gösterir. open fonksiyonundan elde edilen dosya betimleyicisi (file descriptor) prosesin dosya betimleyici tablosunda bir indeks belirtmektedir.
[Makale] Proseslerin Çevre Değişkenleri
Modern işletim sistemlerinde her prosesin bir çevre değişken bloğu vardır. Prosesin çevre değişken bloğu çevre değişkenlerinden ve onların değerlerinden oluşmaktadır. Örneğin, MESAJ bir çevre değişkeninin ismi olabilir, “Merhaba Dunya” ise onun değeri olabilir. Çevre değişkenleri pek çok işletim sisteminde proses yaratılırken belirlenebilmekte ya da üst prosesten (parent process) aktarılabilmektedir. Çevre değişkenlerinin üst prosesten aktarılması en çok karşılaşılan tipik durumdur.
Nedense dizinlerin erişim hakları pek çok UNIX/Linux programcısına karmaşık geliyor. Geçen haftalarda bu konuyla ilgili birkaç soruyla karşılaştım. Genel bir açıklama yaparsam tereddütleri olanların kafalarındaki soru işaretlerini belki biraz azaltabilirim diye düşünüyorum.
Bir dizininin opendir fonkiyonuyla açılabilmesi için o prosesin o dizine ‘r’ hakkının bulunması gerekir. Eğer ‘r’ hakkına sahip olmadığımız bir dizini açmaya çalışırsak opendir fonksiyonu başarısız olur ve errno değişkeni EACCESS değeri ile doldurulur. Dizinlerde ‘x’ hakkı içinden geçme anlamına gelmektedir. Yine bir dizini açabilmek için bu işi yapmak isteyen prosesin o dizine ilişkin yol ifadesindeki her bir yol bileşeninin (hedef dizin de dahil olmak üzere) ‘x’ hakkına sahip olması gerekir. Örneğin opendir fonksiyonuyla /a/b/c yol ifadesine ilişkin c dizinini açmak isteyelim. Bu dizini açabilmemiz için prosesimizin a, b ve c dizinlerine ‘x’ hakkına sahip olması gerekir. Eğer prosesimiz yol bileşenlerinden biri için bile ‘x’ hakkına sahip değilse opendir fonksiyonu başarısız olur ve errno değişkenine EACCESS değeri doldurulur. Peki, örneği biraz daha somutlayayım. İç içe bulunan a, b ve c dizinlerinin erişim hakları, kullanıcı ve grup isimleri şöyle olsun:
drwxr-xr-x kaan project a
drwxr-xr-x gurbuz project b
drwxr-xr-x ali study c
opendir fonksiyonunu çağıran prosesin etkin kullanıcı id'sinin kaan, etkin grup id'sinin project olduğunu varsayalım. a dizinin kullanıcı id'si kaan olduğuna göre a dizininin sahiplik haklarına bakılacaktır. Bu dizinin sahiplik hakları “rwx” biçiminde olduğu için a dizininin içerisinden geçilebilir. b dizininin ise kullanıcı id'si gurbuz grup id'si project biçimindedir. O halde b dizini için grup bilgilerine bakılır. Bu dizinin grup bilgileri “r-x” olduğuna göre b dizininin içinden de geçilebilir. Nihayet c dizininin ne kullanıcı id'si ne de grup id'si prosesin etkin kullanıcı ve grup id'si ile uyuşmamaktadır. O halde c dizini için diğer haklara bakılacaktır. Diğer haklar “r-x” biçiminde olduğuna göre bu proses c dizininini opendir fonksiyonuyla açabilir.
‘r’ hakkı ilgili dizinin listelenebileceğini belirtir. Her türlü listeleme işlemi için dizin opendir ile açıldığına göre, örneğin ls komutu ile dizin listesini alabilmemiz için prosesimizin dizin için ‘r’ ve ‘x’ haklarına sahip olması gerekir. Dizini bir dosya gibi düşünebiliriz. Dizin için ‘w’ hakkı dizin dosyasına yazma anlamına gelir. Dizin dosyası dizin girişlerinden oluştuğuna göre dizin dosyalarına yazma yeni bir dizin girişi oluşturabilme anlamındadır.Bir dizin içerisinde bir dosyayı yaratabilmemiz için dizin üzerinde ‘w’ hakkına sahip olmamız gerekir. ‘w’ hakkına sahip olmadığımız bir dizinde dosya yaratmak istendiğimizde open fonksiyonu başarısız olur ve errno değişkeni de EACCESS değeri ile doldurulur.
Bir dosyanın silinmesi o dosyanın içerisinde bulunan dizin içerisinde değişiklik yapmayı gerektirdiğine göre dosyanın silinmesi için bu işlemi yapacak prosesin dosyanın içinde bulunduğu dizine yazma hakkının olması gerekir. Bu durum sağlanmazsa dosyayı silmekte kullanılan unlink ya da remove fonksiyonları başarısız olur. Dosyanın isminin değiştirilmesi de benzer bir durumdur. İsmin değiştirilmesi işlemi sırasında hem kaynak hem de hedef (kaynak ve hedef dizinler farklı olabilir) dizin üzerinde değişiklik yapılması gerekmektedir. Fakat gerek dosyanın silinmesi gerekse isminin değiştirilmesi işlemlerinde dosyanın içinde bulunduğu dizine 'r' hakkının bulunması gerekmez.
Dosyanın düğüm (i-node) bilgilerinin dizin girişlerinde saklanmadığını, düğüm bloğunda (i-node block) saklandığını biliyorsunuzdur. Dosyanın düğüm bilgilerinin değiştirilmesi dizin girişlerinde bir değişikliğe yol açmadığından düğüm bilgileri üzerinde değişiklik yapabilmek için prosesin dizin üzerinde ‘w’ hakkına sahip olması gerekmez. Örneğin biz dosyanın içinde bulunduğu dizine yazma hakkına sahip olmadan da dosyanın düğüm bilgilerinin değiştirilmesine yol açan fonksiyonları kullanabiliriz. Dosyanın tarih ve zaman bilgileri, erişim bilgileri, büyüklüğü gibi bilgileri bunlara örnek olarak verilebilir.
CSD C ve Sistem Programcıları Derneği