File Descriptors

File Descriptors konusuna değinilen kısım.

File Descriptors Nedir?

File Descriptor, dosyalarla veya diğer giriş/çıkış kaynaklarıyla (örneğin, soketler, borular vb.) etkileşim kurmak için kullanılan bir ifadedir. Bu dosya tanımlayıcıları, işletim sistemi tarafından yönetilir ve genellikle tam sayılarla temsil edilirler. Standart giriş (stdin), standart çıkış (stdout) ve standart hata (stderr) gibi özel dosyalar da dosya tanımlayıcıları aracılığıyla temsil edilir.

3 adet standart dosya tanımlayıcısı vardır;

  1. Stdin(0): Klavyeden bir veri girişi sağlandığında bunu okuyan yerdir. Örneğin, scanf() fonksiyonu standart girişi kullanarak kullanıcıdan girdi alır.

  2. Stdout(1): Ekrana bir çıktı yazıldığında bunu yazdıran yerdir. Örneğin, printf() fonksiyonu standart çıkışı kullanarak veriyi ekrana yazdırır.

  3. Stderr(2): Ekrana bir çıktı yazıldığında bunu yazdıran yerdir ancak hata mesajlarını veya hata bilgilerini bir hata günlüğüne veya başka bir çıkışa yönlendirir.

Genel olarak hata mesajları ve buna benzer işler stderr'e verilmelidir. Bunun nedeni stdout çıkışı bazı durumlarda meşgul olabilir bu yüzden ekrana yazdırmak istenilen şeyin yazdırılması işlem önceliğini baz alarak geç olabilir veya hiç olmayabilir. Bu yüzden farklı bir çıkış ile örneğin hata mesajlarını ekrana yazdırmak için stderr kullanılması önerilir.

Örneğin write() fonksiyonunun ilk parametresi bir fd dosya tanımlayıcısı alır. Bu parametreye argüman olarak genellikle stdout yani 1 verilir. Bu yüzden verdiğimiz argüman ekrana yazdırılır. Ancak bu parametreye stderr yani 2 veya bir dosyaya yazdırılacaksa şayet verilen argüman o halde o dosyanın fd'si verilmelidir. Bu sayede yazdırılmak istenen argüman dosyaya yazılır.

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* str = "Ekrana yazdirilacak\n";
    char* str2 = "Ekrana yazdirilamayacak\n";
    write(1, str, strlen(str));
    write(2, str, strlen(str));
    write(3, str2, strlen(str));
    return 0;
}

Burada write() fonksiyonu aracılığıyla 2 argüman standart çıkışa ve err'e verildiğinden ekrana yazdırıldı. Ancak diğeri bir standart dosya tanımlayıcısı olmadığından yazdırılamadı.

Input/Output System Calls

Temel olarak toplam 5 tip G/Ç sistem çağrısı vardır;

  1. Create(): Bu fonksiyon yeni bir boş dosya oluşturmak için kullanılır.

int create(char *filename, mode_t mode);

Parametreleri:

  • filename: oluşturmak istenilen dosyanın adı

  • mode: yeni dosyanın izinlerini gösterir.

Dosya izinleri mode_t;

#define S_IRWXU 0000700    /* RWX mask for owner */
#define S_IRUSR 0000400    /* R for owner */
#define S_IWUSR 0000200    /* W for owner */
#define S_IXUSR 0000100    /* X for owner */

#define S_IRWXG 0000070    /* RWX mask for group */
#define S_IRGRP 0000040    /* R for group */
#define S_IWGRP 0000020    /* W for group */
#define S_IXGRP 0000010    /* X for group */

#define S_IRWXO 0000007    /* RWX mask for other */
#define S_IROTH 0000004    /* R for other */
#define S_IWOTH 0000002    /* W for other */
#define S_IXOTH 0000001    /* X for other */

#define S_ISUID 0004000    /* set user id on execution */
#define S_ISGID 0002000    /* set group id on execution */
#define S_ISVTX 0001000    /* save swapped text even after use */

---

S_IRWXU  00700 user (file owner) has read, write, and execute permission
S_IRUSR  00400 user has read permission
S_IWUSR  00200 user has write permission
S_IXUSR  00100 user has execute permission
S_IRWXG  00070 group has read, write, and execute permission
S_IRGRP  00040 group has read permission
S_IWGRP  00020 group has write permission
S_IXGRP  00010 group has execute permission
S_IRWXO  00007 others have read, write, and execute permission
S_IROTH  00004 others have read permission
S_IWOTH  00002 others have write permission
S_IXOTH  00001 others have execute permission

According to POSIX, the effect when other bits are set in mode is unspecified. On Linux, the following bits are also honored in mode:

S_ISUID  0004000 set-user-ID bit
S_ISGID  0002000 set-group-ID bit
S_ISVTX  0001000 sticky bit

Kaynak ve fazlası için: Gist

Dönüş Değeri:

  • ilk kullanılmayan dosya tanımlayıcıyı döndür (0, 1, 2 fd ayrılmış olduğundan, süreçte ilk kullanım oluşturulurken genellikle 3 verilir)

  • hata oluştuğunda -1 değerini döndür

  1. Open(): Bu fonksiyon, dosyayı okumak, yazmak veya her ikisi için de açmak için kullanılır. Ayrıca mevcut değilse dosyayı oluşturma yeteneğine de sahiptir.

int open(const char* Path, int flags);

Parametreleri:

  • Path: açmak istediğimiz dosyanın yolu/adı.

  • flags: dosyanın nasıl açılmasını istediğinizi belirtmek için bayraklar kullanılır.

Aşağıda ki bayraklar kullanabilir;

BayraklarAçıklama

O_RDONLY

Dosyayı salt 'read-only' modunda açar.

O_WRONLY

Dosyayı salt 'write-only' modunda açar.

O_RDWR

Dosyayı okuma ve yazma modunda açar.

O_CREAT

Mevcut değilse bir dosya oluşturun.

O_EXCL

Zaten mevcutsa, oluşturulmasını engelleyin.

O_ APPEND

Dosyayı açar ve imleci içeriğin sonuna yerleştirir.

O_ASYNC

Sinyale göre giriş ve çıkış kontrolünü etkinleştirin.

O_CLOEXEC

Açık dosyada yakın yürütme modunu etkinleştirin.

O_NONBLOCK

Açılan dosyanın engellenmesini devre dışı bırakır.

O_TMPFILE

Belirtilen yolda adsız bir geçici dosya oluşturun.

Dönüş Değeri:

  • Dosyayı açtıysa o dosyanın fd'sini dosya tanımlayıcısını döndürür.

  • Dosyayı açamama ve hata durumlarında -1 değerini döndürür.

  1. Read(): dosya tanıtıcısı fd tarafından belirtilen dosyadan, read() işlevi, buf ile gösterilen bellek alanına belirtilen miktardaki byte kadar (cnt) okur.

size_t read(int fd, void* buf, size_t cnt);

Parametreleri:

  • fd: verinin okunacağı dosyanın dosya tanımlayıcısı.

  • buf: verinin okunacağı tampon

  • cnt: Okunacak byte (karakter) sayısı

Dönüş Değeri:

  • başarı durumunda okunan byte sayısı

  • dosyanın sonuna ulaşıldığında 0 değerini döndür

  • hata durumunda -1 değerini döndür

  • sinyal kesintisinde -1 dönüşü

  1. Close(): İşletim sistemine bir dosya tanımlayıcıyla işinizin bittiğini bildirir ve dosya tanımlayıcının işaret ettiği dosyayı kapatır.

int close(int fd);

Parametreleri:

  • fd: Kapatmak istediğiniz dosyanın dosya tanımlayıcısı.

Dönüş Değeri:

  • Başarı durumunda 0.

  • Hata durumunda -1.

  1. Write(): Okunacak bayt sayısı kadar (cnt) buf'tan fd ile ilişkili dosyaya veya yuvaya yazar. cnt, INT_MAX'tan büyük olmamalıdır. Eğer cnt sıfır ise, write() başka bir işlem yapmaya kalkışmadan basitçe 0 değerini döndürür.

size_t write (int fd, void* buf, size_t cnt);

Parametreleri:

  • fd: dosya tanımlayıcı

  • buf: verinin yazılacağı tampon.

  • cnt: Okunacak byte (karakter) sayısı.

Dönüş Değerleri:

  • başarı durumunda üzerine yazılan byte sayısını döndürür.

  • dosyanın sonuna ulaşıldığında 0 değerini döndürün.

  • hata durumunda -1 değerini döndürür.

  • sinyal kesintilerinde -1 döndürür.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main() 
{
    // Dosya adı
    const char *dosya_adi = "ornek.txt";

    // Dosya oluşturma ve açma (O_CREAT, O_WRONLY, O_TRUNC)
    int dosya_fd = open(dosya_adi, O_CREAT | O_WRONLY | O_TRUNC, 0666);

    if (dosya_fd == -1) 
    {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // Dosyaya yazılacak veri
    const char *veri = "Bu bir C örneğidir.\n";

    // Dosyaya veriyi yazma
    ssize_t yazilan = write(dosya_fd, veri, strlen(veri));

    if (yazilan == -1) 
    {
        perror("write");
        close(dosya_fd);
        exit(EXIT_FAILURE);
    }

    printf("%zd byte yazıldı.\n", yazilan);

    // Dosyayı kapatma
    if (close(dosya_fd) == -1) 
    {
        perror("close");
        exit(EXIT_FAILURE);
    }

    // Dosyayı okuma (O_RDONLY)
    dosya_fd = open(dosya_adi, O_RDONLY);

    if (dosya_fd == -1) 
    {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // Dosyadan okunan veriyi depolamak için bir tampon
    char okunan_veri[1024];

    // Dosyadan veriyi okuma
    ssize_t okunan = read(dosya_fd, okunan_veri, sizeof(okunan_veri));

    if (okunan == -1) 
    {
        perror("read");
        close(dosya_fd);
        exit(EXIT_FAILURE);
    }

    // Okunan veriyi ekrana yazdırma
    write(STDOUT_FILENO, okunan_veri, okunan);

    // Dosyayı kapatma
    if (close(dosya_fd) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
    return 0;
}

Last updated