Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX DOSYA SİSTEMİ 2026

FUSE
Kullanıcı Alanı Dosya Sistemi Çerçevesi

FUSE kernel modülü ve libfuse ile kullanıcı alanında özel dosya sistemi geliştirme, gömülü sistemlerde uzak veri kaynağı montajı ve güvenli dosya sistemi sanallaştırması.

00 FUSE neden kullanılır?

FUSE (Filesystem in Userspace), kernel alanında çalışan geleneksel dosya sistemi sürücüsü yazmadan, standart POSIX dosya arayüzü sunan özel dosya sistemleri oluşturmayı mümkün kılar.

Geleneksel kernel FS ile karşılaştırma

Klasik bir dosya sistemi sürücüsü yazmak, kernel modülü geliştirme becerisi, VFS katmanını anlama ve çekirdek güvenliği konusunda derin bilgi gerektirir. Herhangi bir hata doğrudan kernel panikine yol açabilir. FUSE bu sorunu tersine çevirir: dosya sistemi mantığı tamamen kullanıcı alanında çalışır; kernel yalnızca istekleri iletir.

Geleneksel yol:
  Uygulama --syscall--> VFS --> ext4/btrfs.ko --> blok sürücüsü

FUSE yolu:
  Uygulama --syscall--> VFS --> fuse.ko --> /dev/fuse --> FUSE daemon (kullanıcı alanı)
    

FUSE'un tercih edildiği senaryolar

Hızlı prototiplemeKernel modülü olmadan yeni bir FS fikri denemek, CI/CD ortamında test edilebilir
Güvenlik izolasyonuFS kodu kullanıcı alanında çöktüğünde sistemi çökertemez, sandboxed çalışabilir
Uzak/sanal veri kaynaklarıS3, SSH, HTTP, veritabanı gibi kaynakları dosya sistemi olarak sunmak
Gömülü şifreleme FSÖzel şifreleme/sıkıştırma mantığını standart FS arayüzünün arkasına gizlemek
Sanal konfigürasyon FSCihaz parametrelerini dosya olarak sunan özel /proc benzeri yapılar

FUSE'un sınırlamaları

FUSE, her I/O isteği için kullanıcı alanına geçiş yapması nedeniyle geleneksel kernel FS'ye kıyasla daha yüksek gecikme sergiler. Yüksek IOPS gerektiren uygulamalar için bu fark belirleyici olabilir. Ayrıca mmap(MAP_SHARED) desteği sınırlıdır ve bazı POSIX anlam garantileri kırılgan olabilir.

ÖzellikKernel FSFUSE
Geliştirme kolaylığıDüşük (kernel API)Yüksek (C/C++/Python/Go)
Hata izolasyonuYok (kernel panic)Var (daemon çöker, mount kalır)
I/O gecikme ek yükü~0 ek yük~1–10 µs ek yük (context switch)
Root yetkisiZorunluOpsiyonel (allow_other hariç)

01 FUSE mimarisi

FUSE, üç bileşenden oluşur: kernel içindeki fuse.ko modülü, kullanıcı-kernel köprüsü olan /dev/fuse karakter aygıtı ve gerçek FS mantığını uygulayan kullanıcı alanı daemon'ı.

İstek-Yanıt Döngüsü

1. Uygulama: open("/mnt/myfuse/dosya.txt", O_RDONLY)
2. VFS: FUSE mount noktasını tanır, fuse.ko'ya iletir
3. fuse.ko: isteği sıraya koyar
4. /dev/fuse: daemon isteği poll()/read() ile okur
5. Daemon: isteği işler (örn. HTTP'den veri çeker)
6. /dev/fuse: daemon yanıtı write() ile kernel'e gönderir
7. fuse.ko: yanıtı VFS'e iletir
8. Uygulama: read() çağrısı veriyi alır
    

Kernel modülü

fuse.ko modülü çoğu dağıtımda yerleşik (built-in) gelir veya otomatik yüklenir. Modülün yüklü olup olmadığını şöyle kontrol edilir:

# fuse.ko durumu
lsmod | grep fuse
# fuse                  135168  3

# Yoksa yükle
modprobe fuse

# /dev/fuse karakter aygıtını doğrula
ls -la /dev/fuse
# crw-rw-rw- 1 root fuse 10, 229 ... /dev/fuse

libfuse sürümleri

libfuse 2.x (eski API)fuse_main() + struct fuse_operations — basit, tek iş parçacığı veya çok iş parçacıklı mod
libfuse 3.x (modern API)fuse_new() / fuse_mount() ayrımı, session tabanlı, asenkron low-level API
High-level APIYollar ve inode'lar otomatik yönetilir; basit FS'ler için uygun
Low-level APIinode numaraları manuel yönetilir; yüksek performans için gerekli

Kurulum

# Ubuntu/Debian
sudo apt-get install libfuse-dev fuse

# Alpine (gömülü)
apk add fuse fuse-dev

# Yocto recipe içinde
DEPENDS += "fuse"
IMAGE_INSTALL += "fuse"

02 libfuse API temelleri

fuse_operations yapısı, dosya sistemi işlemlerini (getattr, read, write, readdir vb.) uygulayan callback fonksiyon işaretçilerini tutar. Yalnızca desteklemek istediğiniz operasyonları doldurmanız yeterlidir.

fuse_operations yapısı — temel callback'ler

#define FUSE_USE_VERSION 31
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

static int myfs_getattr(const char *path, struct stat *stbuf,
                        struct fuse_file_info *fi) {
    /* Dosya/dizin meta verisi döndür */
    memset(stbuf, 0, sizeof(struct stat));
    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
        return 0;
    }
    return -ENOENT;
}

static int myfs_readdir(const char *path, void *buf,
                        fuse_fill_dir_t filler, off_t offset,
                        struct fuse_file_info *fi,
                        enum fuse_readdir_flags flags) {
    if (strcmp(path, "/") != 0) return -ENOENT;
    filler(buf, ".",  NULL, 0, 0);
    filler(buf, "..", NULL, 0, 0);
    return 0;
}

static int myfs_read(const char *path, char *buf, size_t size,
                     off_t offset, struct fuse_file_info *fi) {
    return -ENOENT;
}

static const struct fuse_operations myfs_ops = {
    .getattr = myfs_getattr,
    .readdir = myfs_readdir,
    .read    = myfs_read,
};

Temel callback sözlüğü

CallbackKarşılık gelen syscallZorunlu mu?
getattrstat(), lstat()Evet — her dizin/dosya için
readdiropendir() / readdir()Dizinler varsa
openopen()Hayır — yoksa izin kontrolü varsayılan
readread(), pread()Dosya okuma için
writewrite(), pwrite()Yazma desteği için
createcreat(), open() + O_CREATYeni dosya oluşturma için
unlinkunlink()Dosya silme için
mkdir / rmdirmkdir(), rmdir()Dizin yönetimi için
truncatetruncate(), ftruncate()Dosya boyutu değiştirme için
flush / fsyncclose(), fsync()Veri kalıcılığı için

main() — fuse_main ile başlatma

int main(int argc, char *argv[]) {
    return fuse_main(argc, argv, &myfs_ops, NULL);
}

/* Derleme */
/* gcc -Wall myfs.c -o myfs $(pkg-config fuse3 --cflags --libs) */

/* Kullanım */
/* mkdir /mnt/test */
/* ./myfs /mnt/test */
/* ls /mnt/test */
/* fusermount3 -u /mnt/test */

03 Basit bellek-içi dosya sistemi

hello-fuse örneği, statik içerikli tek bir dosyayı gösterir. Gerçek bir uygulama için başlangıç noktası olarak kullanılabilir.

hello-fuse: tam kaynak

#define FUSE_USE_VERSION 31
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

static const char *hello_path = "/merhaba.txt";
static const char *hello_str  = "Merhaba FUSE Dunyasi!\n";

static int hello_getattr(const char *path, struct stat *stbuf,
                         struct fuse_file_info *fi) {
    int res = 0;
    memset(stbuf, 0, sizeof(struct stat));

    if (strcmp(path, "/") == 0) {
        stbuf->st_mode  = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    } else if (strcmp(path, hello_path) == 0) {
        stbuf->st_mode  = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size  = (off_t)strlen(hello_str);
    } else {
        res = -ENOENT;
    }
    return res;
}

static int hello_readdir(const char *path, void *buf,
                         fuse_fill_dir_t filler, off_t offset,
                         struct fuse_file_info *fi,
                         enum fuse_readdir_flags flags) {
    if (strcmp(path, "/") != 0) return -ENOENT;
    filler(buf, ".",           NULL, 0, 0);
    filler(buf, "..",          NULL, 0, 0);
    filler(buf, "merhaba.txt", NULL, 0, 0);
    return 0;
}

static int hello_open(const char *path, struct fuse_file_info *fi) {
    if (strcmp(path, hello_path) != 0) return -ENOENT;
    if ((fi->flags & O_ACCMODE) != O_RDONLY) return -EACCES;
    return 0;
}

static int hello_read(const char *path, char *buf, size_t size,
                      off_t offset, struct fuse_file_info *fi) {
    size_t len;
    if (strcmp(path, hello_path) != 0) return -ENOENT;

    len = strlen(hello_str);
    if (offset >= (off_t)len) return 0;
    if (offset + size > len) size = len - (size_t)offset;

    memcpy(buf, hello_str + offset, size);
    return (int)size;
}

static const struct fuse_operations hello_ops = {
    .getattr = hello_getattr,
    .readdir = hello_readdir,
    .open    = hello_open,
    .read    = hello_read,
};

int main(int argc, char *argv[]) {
    return fuse_main(argc, argv, &hello_ops, NULL);
}

Derleme ve test

# Derle
gcc -Wall hello_fuse.c -o hello_fuse $(pkg-config fuse3 --cflags --libs)

# Mount noktası oluştur
mkdir -p /tmp/hello_mount

# Arka planda mount et
./hello_fuse /tmp/hello_mount -f &

# Test et
ls /tmp/hello_mount
cat /tmp/hello_mount/merhaba.txt
# "Merhaba FUSE Dunyasi!"

# Unmount
fusermount3 -u /tmp/hello_mount

Bellek-içi dinamik FS — veri yapısı tasarımı

Birden fazla dosya desteklemek için bir düğüm ağacı (inode tree) tutulur. Basit bir yaklaşım, yol adını anahtar olarak kullanan bir hash tablosudur:

#include <stdlib.h>
#include <stdint.h>

#define MAX_FILES 128
#define MAX_PATH  256
#define MAX_DATA  (64 * 1024)  /* 64 KB maks dosya boyutu */

typedef struct {
    char path[MAX_PATH];
    char data[MAX_DATA];
    size_t size;
    int used;
    mode_t mode;
} memfs_node_t;

static memfs_node_t nodes[MAX_FILES];

static memfs_node_t *find_node(const char *path) {
    int i;
    for (i = 0; i < MAX_FILES; i++) {
        if (nodes[i].used && strcmp(nodes[i].path, path) == 0)
            return &nodes[i];
    }
    return NULL;
}

static memfs_node_t *alloc_node(const char *path) {
    int i;
    for (i = 0; i < MAX_FILES; i++) {
        if (!nodes[i].used) {
            nodes[i].used = 1;
            strncpy(nodes[i].path, path, MAX_PATH - 1);
            nodes[i].size = 0;
            return &nodes[i];
        }
    }
    return NULL;  /* kapasite dolu */
}

04 Gerçekçi FS: HTTP/S3 üzerinden dosya okuma

HTTP veya S3 protokolü üzerinden erişilen uzak blob'ları dosya sistemi olarak sunmak, FUSE'un en yaygın gömülü kullanım senaryolarından biridir. libcurl ile getirilen veriler bellekte önbelleğe alınır.

Mimari

ls /mnt/remoteblobs/
    |
    v
FUSE daemon (readdir callback)
    |-- Uzak index dosyasını getir (HTTP GET /index.json)
    |-- JSON'u ayrıştır, dosya adlarını listele
    v
cat /mnt/remoteblobs/veri.bin
    |
    v
FUSE daemon (read callback)
    |-- Önbellekte var mı? -- EVET --> bellekten oku
    |                      -- HAYIR--> HTTP GET /blobs/veri.bin
    |-- Yanıtı önbelleğe al
    v
uygulama veriye ulaşır
    

libcurl ile HTTP blob getirme

#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char  *data;
    size_t size;
} http_buf_t;

static size_t write_cb(void *ptr, size_t sz, size_t nmemb, void *ud) {
    http_buf_t *buf = (http_buf_t *)ud;
    size_t new_sz = buf->size + sz * nmemb;
    buf->data = realloc(buf->data, new_sz + 1);
    memcpy(buf->data + buf->size, ptr, sz * nmemb);
    buf->size = new_sz;
    buf->data[new_sz] = '\0';
    return sz * nmemb;
}

int http_get(const char *url, http_buf_t *out) {
    CURL *curl = curl_easy_init();
    if (!curl) return -1;

    out->data = malloc(1);
    out->size = 0;

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, out);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);

    CURLcode rc = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return (rc == CURLE_OK) ? 0 : -1;
}

read callback — HTTP ile entegrasyon

#define BASE_URL   "https://ornek-sunucu.yerel/blobs"
#define CACHE_SIZE 16

typedef struct {
    char  name[256];
    char *data;
    size_t size;
} cache_entry_t;

static cache_entry_t cache[CACHE_SIZE];

static cache_entry_t *cache_get(const char *name) {
    int i;
    for (i = 0; i < CACHE_SIZE; i++) {
        if (cache[i].data && strcmp(cache[i].name, name) == 0)
            return &cache[i];
    }
    return NULL;
}

static int remfs_read(const char *path, char *buf, size_t size,
                      off_t offset, struct fuse_file_info *fi) {
    const char *fname = path + 1;  /* baştaki / karakterini atla */
    cache_entry_t *entry = cache_get(fname);

    if (!entry) {
        /* Önbellekte yok — HTTP'den getir */
        char url[512];
        snprintf(url, sizeof(url), "%s/%s", BASE_URL, fname);

        http_buf_t hbuf = {0};
        if (http_get(url, &hbuf) != 0) return -EIO;

        /* Önbelleğe ekle (round-robin slot seçimi) */
        static int slot = 0;
        free(cache[slot].data);
        strncpy(cache[slot].name, fname, 255);
        cache[slot].data = hbuf.data;
        cache[slot].size = hbuf.size;
        entry = &cache[slot];
        slot = (slot + 1) % CACHE_SIZE;
    }

    if (offset >= (off_t)entry->size) return 0;
    size_t avail = entry->size - (size_t)offset;
    if (size > avail) size = avail;

    memcpy(buf, entry->data + offset, size);
    return (int)size;
}

05 Write işlemleri ve tutarlılık

Yazma desteği eklemek, okumaya göre daha karmaşık tutarlılık garantileri gerektirir. WAL (Write-Ahead Logging) yaklaşımı, güç kesintilerinde veri kaybını en aza indirir.

write ve create callback'leri

static int memfs_create(const char *path, mode_t mode,
                        struct fuse_file_info *fi) {
    memfs_node_t *node = find_node(path);
    if (!node) {
        node = alloc_node(path);
        if (!node) return -ENOSPC;
    }
    node->mode = mode;
    node->size = 0;
    return 0;
}

static int memfs_write(const char *path, const char *buf,
                       size_t size, off_t offset,
                       struct fuse_file_info *fi) {
    memfs_node_t *node = find_node(path);
    if (!node) return -ENOENT;

    size_t end = (size_t)offset + size;
    if (end > MAX_DATA) return -ENOSPC;

    memcpy(node->data + offset, buf, size);
    if (end > node->size) node->size = end;
    return (int)size;
}

static int memfs_truncate(const char *path, off_t size,
                          struct fuse_file_info *fi) {
    memfs_node_t *node = find_node(path);
    if (!node) return -ENOENT;
    if ((size_t)size > MAX_DATA) return -EFBIG;
    if ((size_t)size > node->size)
        memset(node->data + node->size, 0, (size_t)size - node->size);
    node->size = (size_t)size;
    return 0;
}

fsync ve flush

/* flush: dosya kapatılırken çağrılır — tamponları diske yaz */
static int myfs_flush(const char *path, struct fuse_file_info *fi) {
    /* Burada veriyi kalıcı depolamaya yaz */
    /* Örnek: SQLite veritabanına commit */
    return persist_to_storage(path);
}

/* fsync: açık dosyayı güvenli yap (uygulamadan explicit çağrı) */
static int myfs_fsync(const char *path, int isdatasync,
                      struct fuse_file_info *fi) {
    /* isdatasync != 0: yalnızca veri (metadata hariç) yeterli */
    return myfs_flush(path, fi);
}

WAL tabanlı yazma tutarlılığı

Güç kesintisine dayanıklı bir FUSE FS için Write-Ahead Log yaklaşımı uygulanır: her yazma işlemi önce bir log dosyasına sıralı olarak kaydedilir, ardından asıl veri yapısına uygulanır. Başlangıçta log yeniden oynatılarak tutarlılık sağlanır.

/* WAL giriş yapısı */
typedef struct {
    uint32_t magic;    /* 0xWAL1 */
    uint32_t op;       /* 1=write, 2=delete, 3=create */
    char     path[256];
    off_t    offset;
    size_t   size;
    /* data[size] takip eder */
} wal_entry_t;

int wal_append(int wal_fd, wal_entry_t *entry, const char *data) {
    /* Atomic: entry + data aynı write() çağrısıyla yaz */
    struct iovec iov[2];
    iov[0].iov_base = entry;
    iov[0].iov_len  = sizeof(*entry);
    iov[1].iov_base = (void *)data;
    iov[1].iov_len  = entry->size;
    return (writev(wal_fd, iov, 2) > 0) ? 0 : -1;
}

06 Performans optimizasyonu

FUSE'un context-switch maliyeti, doğru seçenekler ve zero-copy teknikler kullanılarak önemli ölçüde azaltılabilir.

Kritik mount seçenekleri

-o direct_ioVFS sayfa önbelleğini devre dışı bırakır; FUSE daemon her okuma isteğini alır (taze veri garantisi)
-o kernel_cacheSayfa önbelleği etkin; dosya değişmeyecekse okuma hızını artırır
-o auto_cachemtime değişince önbellek otomatik geçersiz kılınır; dinamik içerik için önerilir
-o writeback_cacheKernel write tamponlaması etkin — küçük yazmaları birleştirerek büyük I/O bloğu üretir
-o max_read=NTek read isteğinde maksimum bayt sayısı; varsayılan genellikle 128 KB

splice ile zero-copy

splice() sistem çağrısı, kullanıcı alanı tamponu olmadan çekirdek arasında veri transferi sağlar. FUSE low-level API ile birleştirildiğinde yüksek bant genişlikli okumalar için kullanışlıdır:

/* Low-level FUSE read callback — splice ile */
static void ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
                    off_t off, struct fuse_file_info *fi) {
    int fd = (int)(uintptr_t)fi->fh;
    struct fuse_bufvec buf = FUSE_BUFVEC_INIT(size);

    buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
    buf.buf[0].fd    = fd;
    buf.buf[0].pos   = off;

    /* fuse_reply_data: kernel splice'ı kullanır, kullanıcı kopyası yok */
    fuse_reply_data(req, &buf, FUSE_BUF_SPLICE_MOVE);
}

Çok iş parçacıklı mod

/* Çok iş parçacıklı FUSE oturumu başlatma */
struct fuse_loop_config config;
memset(&config, 0, sizeof(config));
config.clone_fd         = 1;
config.max_idle_threads = 10;

ret = fuse_loop_mt(fuse, &config);

/* Ya da komut satırından: */
/* ./myfs /mnt/test -o clone_fd */

Performans karşılaştırma tablosu

SeçenekSıralı okumaRastgele okumaAçıklama
VarsayılanOrtaDüşükHer istek için context switch
direct_ioOrtaOrtaÖnbellek bypass, taze veri
kernel_cacheYüksekYüksekTekrar okumalarda önbellekten
writeback_cacheYazma gecikmeyi azaltır
splice + ll APIÇok yüksekYüksekZero-copy, en yüksek verim

07 Güvenlik

FUSE varsayılan olarak yalnızca mount işlemini yapan kullanıcının erişimine izin verir. Gömülü sistemlerde çok kullanıcılı erişim, CAP_SYS_ADMIN gereklilikleri ve daemon izolasyonu dikkatli tasarlanmalıdır.

allow_other ve allow_root

/* Mount seçenekleri */
/* -o allow_other: mount sahibi dışındaki kullanıcılara erişim */
/* -o allow_root:  yalnızca root ve mount sahibi erişebilir */

/* /etc/fuse.conf içinde etkinleştirme (sistem geneli) */
/* user_allow_other */

./myfs /mnt/test -o allow_other

/* Güvenlik notu: allow_other olmadan diğer kullanıcılar EACCES alır */

CAP_SYS_ADMIN gereklilikleri

Root mountRoot olmayan kullanıcılar /etc/fuse.conf'da user_allow_other olmadan allow_other kullanamaz
nodev / nosuidRoot olmayan FUSE mount'larına kernel otomatik olarak nodev ve nosuid uygular
Namespace izolasyonuMount namespace'ler kullanılarak FUSE mount'u konteynere hapsedilebilir

Gömülü güvenlik önerileri

# FUSE daemon'ı ayrıcalık düşürme ile çalıştırma
# Gerçek root ile başla, mount sonrası ayrıcalıkları bırak

int main(int argc, char *argv[]) {
    /* Mount işlemi öncesi hazırlık (root gerekiyorsa) */
    setup_privileged_resources();

    /* ayrıcalıkları düşür */
    if (setuid(DAEMON_UID) != 0 || setgid(DAEMON_GID) != 0) {
        perror("setuid/setgid");
        return 1;
    }

    /* Root olmayan kullanıcı olarak FUSE çalıştır */
    return fuse_main(argc, argv, &myfs_ops, NULL);
}

# Systemd service ile güvenli çalıştırma:
# [Service]
# User=fuseuser
# AmbientCapabilities=
# NoNewPrivileges=true
# PrivateTmp=true

Güvenli dosya izinleri

/* getattr içinde gömülü cihaza özel izin kısıtlaması */
static int myfs_getattr(const char *path, struct stat *stbuf,
                        struct fuse_file_info *fi) {
    memset(stbuf, 0, sizeof(*stbuf));

    if (strcmp(path, "/config") == 0) {
        /* Konfigürasyon dizini: yalnızca sahip okuyabilir/yazabilir */
        stbuf->st_mode  = S_IFDIR | 0700;
        stbuf->st_nlink = 2;
        stbuf->st_uid   = getuid();
        return 0;
    }
    if (strcmp(path, "/firmware.bin") == 0) {
        /* Firmware dosyası: salt okunur, herkes okuyabilir */
        stbuf->st_mode  = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size  = firmware_size();
        return 0;
    }
    return -ENOENT;
}

08 Hata ayıklama

FUSE sorunlarını tespit etmenin en hızlı yolu -d veya -f seçenekleri ve strace ile mount sürecini izlemektir. /sys/fs/fuse/connections/ dizini bağlantı istatistiklerini sunar.

Debug modunda çalıştırma

# -f: ön planda çalış (daemon olmadan)
./myfs /mnt/test -f

# -d: debug modu — her FUSE isteğini yazdırır (en ayrıntılı)
./myfs /mnt/test -d

# Örnek -d çıktısı:
# LOOKUP  /dosya.txt
# GETATTR /dosya.txt
# OPEN    /dosya.txt fi->flags=0x8000
# READ    /dosya.txt off=0 size=4096

strace ile mount izleme

# Uygulamanın FUSE mount'una yaptığı syscall'ları izle
strace -e trace=openat,read,write,getdents64 \
       cat /mnt/test/dosya.txt

# FUSE daemon sürecini izle
strace -p $(pidof myfs) -e trace=read,write

/sys/fs/fuse/connections/

# Aktif FUSE bağlantılarını listele
ls /sys/fs/fuse/connections/
# 42/  (bağlantı ID)

# Bağlantı istatistiklerini oku
cat /sys/fs/fuse/connections/42/waiting
# 0  (bekleyen istek sayısı)

cat /sys/fs/fuse/connections/42/max_background
# 12  (eş zamanlı arka plan istek sınırı)

# Bağlantıyı zorla kapat (donmuş FUSE kurtarma)
echo 1 | sudo tee /sys/fs/fuse/connections/42/abort

Yaygın sorunlar ve çözümleri

SorunNedenÇözüm
Transport endpoint not connectedDaemon çöktü, mount noktası asılı kaldıfusermount3 -u -z /mnt/test ile lazy unmount
ls: cannot access: Permission deniedallow_other yok veya sahip farklı/etc/fuse.conf'a user_allow_other ekle
FUSE mount sonrası dosyalar görünmüyorreaddir NULL döndürüyorfiller çağrılarını ve dönüş değerini kontrol et
Yüksek CPU kullanımıBusy-wait veya spinlock daemon içindelibfuse poll ile olay tabanlı döngüye geç
Veri tutarsızlığıflush/fsync implement edilmemişflush callback'inde kalıcı yazmayı zorla

valgrind ile bellek sızıntısı tespiti

# FUSE daemon'ı valgrind altında çalıştır
valgrind --leak-check=full --track-origins=yes \
         ./myfs /mnt/test -f -s

# -s: tek iş parçacıklı mod — valgrind ile daha temiz izleme
# Bir sonraki terminalde test et, ardından fusermount3 -u ile kapat