Dosya İşlemleri

Unix tabanlı sistemlerde genel olarak, bir şey okunabiliyor veya yazılabiliyorsa, dosya arayüzü üzerinden de kullanılabilir. Örnek olarak ağ iletişiminde kullanılan soketler, seri port, dizinler, pipe, timer, sinyal vb. pek çok bileşen üzerinde dosya arayüzü ile işlem yapmak mümkündür.

Dosya arayüzünü açmak için öncelikle ilgili dosyayı açmak ve dosya betimleyiciyi file descriptor elde etmek gereklidir.

File descriptor elde etme yolları kullanılan sisteme göre değişir. Örneğin standart bir dosya için open() sistem çağrısı kullanılırken soket açmak istiyorsak socket(), timer oluşturmak istiyorsak timerfd_create() gibi ilgili sisteme özgü özel bir sistem çağrısı kullanılır.

Tüm bu çağrıların ortak özelliği, başarılı olunması durumunda geriye int tipinde bir file descriptor dönülüyor olmasıdır. File descriptor elde edildikten sonra artık bu dosya ile ilgili tüm işlemlerde, dosya kapatılana kadar ilgili int değeri kullanılıyor olacaktır.

Proses Dosya Tablosu

İşletim sistemindeki proses tablosunda, her proses ile ilgili açık dosyaların listesi tutulur. Bu liste yapısı içerisinde açık dosyalarla ilgili ek bir takım bilgiler de saklanır (örneğin normal bir dosya ise inode numarası, erişim yetkileri, son erişim zamanı, geçerli file position vb.)

Çekirdek içerisinde yer alan bu proses tablosunun daha basit bir haline /proc dosya sistemi üzerinden erişmek de mümkündür. Her bir proses id (PID) için aşağıdaki bilgilerin alınması mümkündür:

/proc/PID/fd

İlgili PID için açık dosyaların int descriptor numaralarını içeren sembolink linkler bulunur. Bu sembolink linklerin bulunduğu dizine ls -l komutuyla bakılacak olursa veya uygulamanızda readlink() fonksiyonuyla sembolik linkin işaret ettiği yerle ilgili bilgileri okumaya çalıştığınızda type:[inode] formatında bir yanıt gelir.

Dosya sistemi üzerinde fiziksel bir inode olmadığı senaryolar için de inode sistematiği içinde kalınarak özgün bir numara verilir.

Örnek olarak açık soket bağlantıları için readlink() sonrasında socket:[205846] şeklinde bir yanıt döner. Burada tip olarak soket bağlantısını olduğunu görmekteyiz, inode bilgisi olarak da 205846 numarası dönülmüştür. Bu numaranın soketler için anlamlandırılması /proc/net altındaki ilgili dosyaların okunmasıyla yapılır. Eğer bu soket bağlantısı bir TCP soketine aitse, /proc/net/tcp dosyasında, UDP soketine aitse /proc/net/udp dosyasında vb. burada görülen inode numarasıyla eşleşecek şekilde kayıtlar bulunduğu görülecektir.

Eğer inode konseptiyle henüz ilişkilendirilemeyen epoll_create(), inotify_init(), signalfd() gibi bir fonksiyonla elde edilmiş file descriptor söz konusu ise bu durumda anon_inode:<file type> formatında bir çıktı verecektir.

/proc/PID/fdinfo

Linux 2.6.22 versiyonu ve sonrasında bu dizin yapısı üzerinden ek bilgiler elde edilmesi mümkündür. Dizin içerisinde her bir int file descriptor ile aynı isimde dosyalar bulunur. Herhangi bir dosyanın içerisinde baktığımızda aşağıdaki bilgiler elde edilir:

pos:    0
flags:  02
mnt_id: 7

Bu dosyada file pointer pozisyonu, dosya açılırken kullanılan flag'ler, dosyanın ilişkili olduğu mount point referansı yer almaktadır.

Açık Dosya Limitleri

Unix tabanlı sistemlerde, bir prosesin aynı anda açabileceği dosya sayısının bir limiti bulunmaktadır.

Bu limitler soft limit ve hard limit adında 2 başlıkta toplanır. Açık dosya limitini ulimit uygulamasıyla veya setrlimit() fonksiyonuyla artırmak mümkündür. Ancak bu değer hard limit'i aşamaz. Bu limit ancak root kullanıcısı tarafından değiştirilebilir.

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15234
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15234
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

$ ulimit -n 2048
$ ulimit -n
2048

Aşağıdaki örnek uygulama ile parametre vererek aynı anda kaç dosya açabileceğini test edebilir, ulimit -n komutuyla limitleri değiştirip tekrar testi gerçekleştirebilirsiniz.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include "../common/debug.h"

int main (int argc, char *argv[])
{
    int opened = 0;
    int wanted;
    int i;

    if (argc != 2) {
        printf("Usage: %s NumberOfFiles\n", argv[0]);
        exit(1);
    }

    wanted = atoi(argv[1]);
    for (i = 0; i < wanted; i++) {
        if (open("/dev/zero", O_RDONLY) < 0) {
            errorf("Couldn't open file");
            break;
        }
        opened++;
    }
    debugf("Total of %d files opened", opened);

    return 0;
}

Proses başına ayarlanan bu limitin haricinde, sistem genelinde maksimum açık dosya sayısının da bir limiti mevcuttur. Bu değer /proc/sys/fs/file-max dosyasından veya fs.file-max parametresi ile sysctl üzerinden okunabilir ve değiştirilebilir:

$ cat /proc/sys/fs/file-max
389794
$ sudo sysctl fs.file-max=400000
fs.file-max = 400000
$ cat /proc/sys/fs/file-max 
400000

results matching ""

    No results matching ""