tmpfs ve ramfs ile Bellek Tabanlı Geçici Dosya Sistemi Oluşturma ve Kullanım Senaryoları

Performans testi yapıyorsunuz, uygulama sürekli disk I/O bekliyor, profiler ekrana “write latency” diye bağırıyor. İşte tam bu noktada aklınıza gelmesi gereken şey: neden bu geçici verileri diske yazıyoruz ki? RAM’de tutamaz mıyız? Linux’un tmpfs ve ramfs mekanizmaları tam bu soruya cevap veriyor ve doğru kullanıldığında ciddi performans kazanımları sağlıyor.

Bu yazıda tmpfs ve ramfs arasındaki farkları, kurulum adımlarını ve gerçek dünya senaryolarını ele alacağım. Teorik değil, çalışırken karşılaştığım durumlardan örnekler vereceğim.

tmpfs ve ramfs Nedir, Aralarındaki Fark Ne?

Her ikisi de RAM’i dosya sistemi olarak kullanan mekanizmalar. Ama aralarında kritik farklar var.

ramfs, Linux çekirdeğinin ilk dönemlerinden beri var. Çok basit bir yapısı var: RAM’den alan alır, gerektiğinde büyür. Ancak büyümek için bir üst sınır yok. Yani ramfs’e veri yazmaya devam ederseniz, sistem RAM’i bitene kadar bu işlemi durdurmuyor. Bu ciddi bir tehlike. Sistemin swap’ı bile yoksa OOM killer devreye giriyor ve süreçleri öldürmeye başlıyor.

tmpfs, ramfs’in bu sorununu çözmek için geliştirilmiş daha akıllı bir versiyon. İki temel farkı var:

  • Boyut sınırı belirleyebilirsiniz. Dolduğunda “No space left on device” hatası alırsınız, sistem askıya girmez.
  • Swap kullanabilir. Bellek baskısı olduğunda tmpfs içeriği swap’a taşınabilir. ramfs asla swap’a gitmez.

Pratikte neredeyse her zaman tmpfs kullanmalısınız. ramfs’in kullanım alanı çok daha niş: önyükleme sürecinin başlarında, swap henüz aktif değilken ihtiyaç duyulan initramfs gibi senaryolar.

Sistem üzerinde halihazırda çalışan tmpfs bağlantı noktalarını görmek için:

mount | grep tmpfs
# veya daha temiz çıktı için:
findmnt -t tmpfs

Modern bir Linux sisteminde /tmp, /run, /dev/shm gibi dizinlerin zaten tmpfs üzerinde çalıştığını göreceksiniz. Yani bu teknoloji size yabancı değil, sadece bilinçli kullanmıyordunuz.

tmpfs Bağlamak: Temel Kullanım

En basit haliyle geçici bir tmpfs oluşturmak:

# /mnt/ramdisk dizinini oluştur
mkdir -p /mnt/ramdisk

# 512MB boyutunda tmpfs bağla
mount -t tmpfs -o size=512m tmpfs /mnt/ramdisk

# Bağlandı mı kontrol et
df -h /mnt/ramdisk

size parametresi için farklı birimler kullanabilirsiniz:

  • size=512m: 512 megabyte
  • size=2g: 2 gigabyte
  • size=50%: Toplam RAM’in yüzde ellisi

Yüzde kullanımı özellikle farklı boyutlardaki sunucularda aynı konfigürasyonu uygulamak istediğinizde işe yarıyor. 64GB RAM’li sunucuda da 8GB’lıkta da “toplam RAM’in yüzde onu” diyebiliyorsunuz.

Bağlantıyı kaldırmak için:

umount /mnt/ramdisk

Dikkat: umount komutunu çalıştırdığınızda içindeki her şey gidiyor. Kalıcı depolama değil bu. Biliyorsunuz ama yine de yazayım, zira bir kez bu hatayı yapıp saatlik işin çöpe gittiğini yaşadım.

fstab ile Kalıcı Bağlama

Sistem yeniden başladığında otomatik bağlanmasını istiyorsanız /etc/fstab dosyasına eklemeniz gerekiyor:

# /etc/fstab'a eklenecek satır
tmpfs   /mnt/ramdisk   tmpfs   defaults,size=512m,uid=1000,gid=1000,mode=0755   0 0

Seçeneklerin açıklaması:

  • size=512m: Maksimum boyut 512MB
  • uid=1000: Dosya sistemi sahibi kullanıcı ID
  • gid=1000: Dosya sistemi sahibi grup ID
  • mode=0755: Dizin izinleri
  • noexec: Çalıştırılabilir dosyaların çalışmasını engeller (güvenlik için)
  • nosuid: SUID bit’li programların çalışmasını engeller
  • nodev: Cihaz dosyası oluşturmayı engeller

Güvenlik bilincini yüksek tutmak istiyorsanız /tmp için şöyle bir tanım daha sağlıklı:

tmpfs   /tmp   tmpfs   defaults,size=2g,nosuid,nodev,noexec   0 0

fstab değişikliğini yeniden başlatmadan test etmek için:

mount -a
# Hata yoksa bağlantı yapıldı
findmnt /mnt/ramdisk

tmpfs Boyutunu Dinamik Olarak Değiştirme

Bağlı bir tmpfs’in boyutunu değiştirmek için sistemin yeniden başlatılmasına gerek yok. Bu özellik production ortamında çok işe yarıyor:

# Mevcut durumu gör
df -h /mnt/ramdisk

# Boyutu 1GB'a çıkar (içindeki veriler kaybolmaz)
mount -o remount,size=1g /mnt/ramdisk

# Tekrar kontrol et
df -h /mnt/ramdisk

remount seçeneği sayesinde hem boyutu değiştirebiliyor hem de diğer mount seçeneklerini güncelleyebiliyorsunuz. Ama dikkat: boyutu küçültürken içindeki veri mevcut boyutu aşıyorsa hata alırsınız.

Gerçek Dünya Senaryosu 1: Derleme Ortamı Hızlandırma

C/C++ projelerinde, büyük Java monolitlerinde ya da Rust ile yazılmış projelerde derleme sırasındaki ara dosyalar ciddi disk I/O yükü oluşturuyor. Benim test ettiğim bir senaryoda, 200 bin satırlık bir C++ projesinin derleme süresi tmpfs kullanımıyla yaklaşık yüzde otuz kısaldı. Disk türüne göre bu oran değişiyor, NVMe SSD üzerinde fark daha az ama eski SATA SSD ya da HDD’de dramatik.

#!/bin/bash
# build_on_ram.sh - Derlemeyi RAM üzerinde yap

PROJECT_DIR="/home/user/myproject"
RAM_BUILD_DIR="/mnt/build_ram"
BUILD_SIZE="4g"

# Yeterli RAM var mı kontrol et
AVAILABLE_RAM=$(free -m | awk '/^Mem:/{print $7}')
NEEDED_RAM=4096

if [ "$AVAILABLE_RAM" -lt "$NEEDED_RAM" ]; then
    echo "Yetersiz RAM: ${AVAILABLE_RAM}MB mevcut, ${NEEDED_RAM}MB gerekli"
    exit 1
fi

# tmpfs bağla
mkdir -p "$RAM_BUILD_DIR"
mount -t tmpfs -o size="$BUILD_SIZE" tmpfs "$RAM_BUILD_DIR"

# Proje dosyalarını kopyala
cp -r "$PROJECT_DIR" "$RAM_BUILD_DIR/"

# Derle
cd "$RAM_BUILD_DIR/$(basename $PROJECT_DIR)"
make -j$(nproc)

# Çıktıyı geri kopyala
cp -r build/output/* "$PROJECT_DIR/build/"

# Temizle
cd /
umount "$RAM_BUILD_DIR"

echo "Derleme tamamlandı, geçici dosyalar temizlendi"

Gerçek Dünya Senaryosu 2: Veritabanı Performans Testi

Geliştirme ya da yük testi sırasında veritabanını RAM üzerinde çalıştırmak isteyebilirsiniz. MySQL/MariaDB için tmpfs kullanımı:

# Test veritabanı için tmpfs oluştur
mkdir -p /mnt/mysql_test
mount -t tmpfs -o size=2g,uid=mysql,gid=mysql tmpfs /mnt/mysql_test

# MySQL konfigürasyonunu güncelle (test instance için)
# /etc/mysql/conf.d/test.cnf
cat > /etc/mysql/conf.d/ramtest.cnf << 'EOF'
[mysqld]
datadir=/mnt/mysql_test
innodb_flush_method=nosync
innodb_doublewrite=0
EOF

# Test veritabanını başlat
mysqld --initialize-insecure --datadir=/mnt/mysql_test --user=mysql

Uyarı: Bu kurulum production için kesinlikle uygun değil. Sunucu kapanırsa tüm veriler gidiyor. Sadece performans testleri için, bunu bilerek kullanıyorsunuz.

Gerçek Dünya Senaryosu 3: /dev/shm ile Süreçler Arası İletişim

/dev/shm zaten tmpfs üzerinde çalışıyor ve POSIX shared memory için kullanılıyor. Yüksek frekanslı veri işleyen uygulamalar için bu kritik:

# /dev/shm boyutunu kontrol et
df -h /dev/shm

# Varsayılan boyut genellikle RAM'in yarısı, bunu değiştirebilirsiniz
mount -o remount,size=4g /dev/shm

# Python ile shared memory örneği
python3 << 'EOF'
from multiprocessing import shared_memory
import numpy as np

# 100MB'lık shared memory bloğu oluştur
shm = shared_memory.SharedMemory(create=True, size=100*1024*1024)
array = np.ndarray((25000000,), dtype=np.float32, buffer=shm.buf)

print(f"Shared memory adı: {shm.name}")
print(f"Boyut: {shm.size / 1024 / 1024:.1f} MB")
print(f"Konum: /dev/shm/{shm.name}")

shm.close()
shm.unlink()
EOF

Gerçek Dünya Senaryosu 4: Log Geçici Tamponu

Yoğun log yazan bir uygulama var, disk I/O bu nedenle tıkanıyor. Logları önce RAM’e yazıp periyodik olarak diske aktarmak bir çözüm:

#!/bin/bash
# log_buffer.sh - Log tamponu için tmpfs + rsync

LOG_RAM="/mnt/log_buffer"
LOG_DISK="/var/log/myapp"
SYNC_INTERVAL=60  # saniye

# Başlangıç kurulumu
mkdir -p "$LOG_RAM" "$LOG_DISK"
mount -t tmpfs -o size=500m tmpfs "$LOG_RAM"

# Mevcut logları RAM'e kopyala
rsync -a "$LOG_DISK/" "$LOG_RAM/"

echo "Log tamponu hazır: $LOG_RAM"
echo "Senkronizasyon aralığı: ${SYNC_INTERVAL}s"

# Periyodik senkronizasyon döngüsü
while true; do
    sleep "$SYNC_INTERVAL"
    rsync -a --delete "$LOG_RAM/" "$LOG_DISK/"
    echo "$(date): Loglar diske senkronize edildi"
done

Bu yaklaşım özellikle SSD ömrünü korumak için de kullanılıyor. Sık yazma yapan sistemlerde SSD’nin yazma döngüsünü harcamamak için logları RAM’de tutup daha seyrek aralıklarla diske aktarabilirsiniz.

ramfs Kullanımı: Ne Zaman Mantıklı?

Dediğim gibi, ramfs kullanımı çok niş. Ama bazı senaryolar var:

# ramfs bağlama (boyut sınırı YOK, dikkatli kullanın)
mkdir -p /mnt/ramfs_test
mount -t ramfs ramfs /mnt/ramfs_test

# Swap'a gitmesin istediğiniz kritik veriler için
# Örneğin: şifreleme anahtarları, geçici kimlik bilgileri
echo "gizli_veri" > /mnt/ramfs_test/secret.key
# Bu veri asla swap'a gitmeyecek

# Kullanım sonrası mutlaka temizleyin
shred -uz /mnt/ramfs_test/secret.key
umount /mnt/ramfs_test

Güvenlik açısından bakıldığında ramfs’in swap’a gitmemesi bir avantaj. Kriptografik anahtarlar veya şifreler gibi veriler swap üzerinden disk’e sızmasın istiyorsanız ramfs tercih edilebilir. Ama boyut kontrolü olmadığı için uygulama seviyesinde çok dikkatli olmak gerekiyor.

İzleme ve Troubleshooting

tmpfs kullanırken neleri izlemeniz gerekiyor?

# Tüm tmpfs bağlantı noktalarının durumu
df -h -t tmpfs

# Daha detaylı bilgi
findmnt -t tmpfs -o TARGET,SIZE,USED,AVAIL,USE%

# Belirli bir tmpfs'in inode kullanımı
df -i /mnt/ramdisk

# Sistemdeki toplam RAM kullanımını izle
watch -n 1 'free -h && echo "---" && df -h -t tmpfs'

Bir sorun yaşandığında ilk bakılacak yer:

# tmpfs doldu mu?
df -h /mnt/ramdisk
# "Use%" 100 gösteriyorsa yer kalmamış

# Hangi süreçler dosya açmış?
lsof /mnt/ramdisk

# Kernel mesajlarında OOM var mı?
dmesg | grep -i "out of memory"
dmesg | grep -i "oom"

# Mount seçeneklerini kontrol et
cat /proc/mounts | grep tmpfs

Güvenlik Notları

tmpfs kullanırken göz ardı edilen birkaç güvenlik konusu var:

İzinler: tmpfs bağlarken mode, uid, gid ayarlarını mutlaka belirtin. Aksi halde herkes yazabilir.

noexec ve nosuid: /tmp gibi herkesin yazabildiği alanlarda bu seçenekler olmazsa olmaz. Bir saldırgan oraya executable koyup çalıştırabilir.

# Güvenli /tmp yapılandırması
mount -t tmpfs -o size=2g,nosuid,nodev,noexec,mode=1777 tmpfs /tmp

Hassas veri temizliği: tmpfs’deki veri umount sonrası kayboluyor, doğru. Ama umount öncesinde açık kalan file descriptor’lar üzerinden erişim mümkün. Hassas verileri açıkça silmek iyi pratik:

# Hassas dosyayı sil
shred -uz /mnt/ramdisk/sensitive_file

Hibernate dikkat: Sistem hibernate olduğunda (suspend to disk) RAM içeriği diske yazılıyor. tmpfs’deki veriler de bu sürece dahil. Gizli veri için bunu dikkate alın.

systemd ile tmpfs Entegrasyonu

Modern sistemlerde systemd-tmpfiles mekanizmasını kullanarak tmpfs yönetimini daha temiz yapabilirsiniz:

# /etc/tmpfiles.d/myapp.conf
cat > /etc/tmpfiles.d/myapp.conf << 'EOF'
# Type Path            Mode UID  GID  Age Argument
d     /run/myapp       0755 root root -   -
d     /tmp/myapp_work  0750 myapp myapp 1d -
EOF

# Yapılandırmayı hemen uygula
systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf

# systemd mount unit ile tmpfs yönetimi
cat > /etc/systemd/system/mnt-ramdisk.mount << 'EOF'
[Unit]
Description=RAM Disk for Build Cache
DefaultDependencies=no

[Mount]
What=tmpfs
Where=/mnt/ramdisk
Type=tmpfs
Options=defaults,size=2g,mode=0755

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now mnt-ramdisk.mount
systemctl status mnt-ramdisk.mount

systemd mount unit kullanmanın avantajı: diğer servisler bu mount’a bağımlılık tanımlayabiliyor. Ramdisk bağlanmadan uygulama başlamıyor, temiz bir bağımlılık zinciri kurulmuş oluyor.

Boyut Planlaması

Pratikte en çok sorulan soru: “Ne kadar boyut ayarlamalıyım?”

Benim yaklaşımım:

  • Kullanım senaryosunun maksimum veri boyutunu tahmin edin
  • Üzerine yüzde yirmi buffer ekleyin
  • Mevcut RAM’in yüzde ellisini geçmeyin (genel kural olarak)
  • Yüklü sistemlerde yüzde otuzla sınırlı tutun
# Sistem RAM durumunu analiz et
free -h
echo "---"
echo "Önerilen maksimum tmpfs boyutu:"
awk '/MemTotal/{printf "Toplam: %.0fGBnYüzde 30: %.0fGBnYüzde 50: %.0fGBn", 
    $2/1024/1024, 
    $2/1024/1024*0.3, 
    $2/1024/1024*0.5}' /proc/meminfo

Sonuç

tmpfs ve ramfs, doğru senaryoda kullanıldığında performansı dramatik biçimde artırabilen araçlar. Ama bu araçları kullanırken iki temel gerçeği aklınızdan çıkarmayın: veriler kalıcı değil ve sistem kaynaklarından yiyorlar.

Hangi durumlarda kesinlikle kullanın: derleme geçici dosyaları, test veritabanları, yoğun log tamponlama, süreçler arası paylaşımlı bellek, hassas geçici veriler.

Hangi durumlarda dikkatli olun: boyut planlamasını iyi yapın, izleme mutlaka ekleyin, güvenlik seçeneklerini atlama, ve asla production veritabanı için birincil depolama olarak kullanma.

Son olarak: Bu mekanizmaları production’a almadan önce geliştirme ortamında kapsamlı test edin. RAM dolduğunda uygulamanız nasıl davranıyor? OOM durumunu simüle ettiniz mi? Bunları önceden yanıtlamak, gece yarısı bir incident’la uğraşmaktan çok daha az stresli.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir