00 Gömülü Geliştirmede NFS
NFS (Network File System), gömülü Linux geliştirme döngüsünde olmazsa olmaz bir araçtır. Geliştirici bilgisayarındaki rootfs dizini hedef cihaza ağ üzerinden bağlanır; böylece her değişiklik için yeni bir imaj yazmak yerine dosyayı düzenleyip hemen test edebilirsiniz.
Geleneksel iş akışında her kod değişikliği şu adımları gerektirir: çapraz derle, imaj oluştur, SD karta veya eMMC'ye yaz, cihazı yeniden başlat. Bu döngü özellikle donanım sürücüsü veya sistem kütüphanesi geliştirirken ciddi zaman kaybına yol açar. NFS bu döngüyü kırpar:
Geleneksel geliştirme döngüsü: kod değiştir -> derle -> imaj yaz -> cihazı başlat -> test [~2-10 dakika her iterasyon] NFS tabanlı geliştirme döngüsü: kod değiştir -> derle -> cihazda çalıştır [~10-30 saniye her iterasyon] (NFS bağlantısı sayesinde dosya kopyalama yok)
TFTP + NFS kombinasyonu en yaygın gömülü geliştirme düzenidir: U-Boot çekirdeği TFTP ile ağdan çeker, rootfs ise NFS paylaşımından mount edilir. Bu düzen hem çekirdek hem de kullanıcı alanı geliştirmesi için son derece verimlidir.
| Özellik | eMMC / SD geliştirme | NFS geliştirme |
|---|---|---|
| Dosya değişiklik süresi | 2–10 dakika (imaj yazma) | Anında (ağ üzerinden erişim) |
| Donanım gereksinimi | SD/eMMC programcı | Ethernet bağlantısı |
| Paralel geliştirme | Her geliştirici ayrı kart | Birden fazla hedef aynı NFS paylaşımını kullanabilir |
| Güç açma/kapama etkisi | Kalıcı (flash'ta) | Geçici (rootfs geliştirici bilgisayarında) |
| Üretim için uygunluk | Evet | Hayır (güvenlik ve bağlantı bağımlılığı) |
| Dosya sistemi boyutu | Flash kapasitesiyle sınırlı | Geliştirici diskiyle sınırlı |
NFS rootfs üretim ortamında kullanılmaz; ancak bazı gömülü uygulama senaryolarında (kiosk sistemleri, merkezi yönetimli ince istemciler) NFS bağlı uygulama dizinleri tercih edilebilir. Bu farkı akılda tutarak NFS kurulumuna geçelim.
01 NFS Sunucu Kurulumu
NFS sunucu, geliştirici bilgisayarında (Ubuntu/Debian/Fedora) kurulur. Doğru
/etc/exports yapılandırması hem güvenlik hem de işlevsellik için kritiktir.
Sunucu kurulumu:
# Ubuntu/Debian
sudo apt-get install nfs-kernel-server
# Fedora/RHEL
sudo dnf install nfs-utils
# Servisi başlat ve etkinleştir
sudo systemctl enable --now nfs-server
/etc/exports dosyası hangi dizinlerin, hangi istemcilere, hangi seçeneklerle
paylaşılacağını tanımlar:
# /etc/exports — NFS paylaşım yapılandırması
# Tekil hedef IP için geliştirme rootfs
/home/kullanici/nfs/rootfs 192.168.1.100(rw,sync,no_root_squash,no_subtree_check)
# Alt ağ için geliştirme paylaşımı
/home/kullanici/nfs/rootfs 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
# Salt okunur paylaşım (üretim benzeri test)
/opt/embedded/rootfs-ro 192.168.1.100(ro,sync,no_subtree_check)
# Birden fazla hedef için ayrı rootfs
/home/kullanici/nfs/device-a 192.168.1.101(rw,sync,no_root_squash,no_subtree_check)
/home/kullanici/nfs/device-b 192.168.1.102(rw,sync,no_root_squash,no_subtree_check)
Önemli exports seçenekleri:
# Exports dosyasını güncelledikten sonra yeniden yükle
sudo exportfs -ra
# Aktif paylaşımları kontrol et
sudo exportfs -v
# NFS durumu kontrol et
sudo systemctl status nfs-server
# Güvenlik duvarı kuralları (gerekirse)
sudo ufw allow from 192.168.1.0/24 to any port nfs
sudo ufw allow from 192.168.1.0/24 to any port mountd
sudo ufw allow from 192.168.1.0/24 to any port rpcbind
rootfs dizinini hazırlamak için Yocto veya Buildroot çıktısını doğrudan NFS dizinine açabilirsiniz:
# Yocto çıktısından NFS rootfs hazırlama
sudo mkdir -p /home/kullanici/nfs/rootfs
sudo tar -xjf core-image-minimal-TARGET.tar.bz2 -C /home/kullanici/nfs/rootfs/
# Sahiplik ve izinleri düzelt
sudo chown -R root:root /home/kullanici/nfs/rootfs/
02 Kernel ile NFS Root
Çekirdeğin NFS üzerinden boot edebilmesi için hem kernel yapılandırması hem de bootloader parametrelerinin doğru ayarlanması gerekir.
Kernel yapılandırması:
# NFS client desteği
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
# NFS root mount desteği (kritik!)
CONFIG_ROOT_NFS=y
# IP autoconfiguration (DHCP ile IP alma veya kernel param)
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# Ethernet sürücüsü (platforma göre değişir, örnek: Realtek)
CONFIG_R8169=y
CONFIG_ROOT_NFS=y ve CONFIG_IP_PNP=y modül olarak değil,
mutlaka gömülü (=y) olmalıdır; çünkü initramfs yokken çekirdek ağ
arayüzünü ve NFS bağlantısını kendi kurması gerekir.
U-Boot bootargs ile NFS root:
# Statik IP ile NFS root
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.1
setenv bootargs "console=ttyS0,115200 \
root=/dev/nfs \
nfsroot=192.168.1.1:/home/kullanici/nfs/rootfs,v3,tcp \
ip=192.168.1.100:192.168.1.1:192.168.1.1:255.255.255.0:target:eth0:off \
rw"
# DHCP ile NFS root (kernel IP autoconfiguration)
setenv bootargs "console=ttyS0,115200 \
root=/dev/nfs \
nfsroot=192.168.1.1:/home/kullanici/nfs/rootfs,v3,tcp \
ip=dhcp \
rw"
# NFSv4 ile (genellikle tercih edilir)
setenv bootargs "console=ttyS0,115200 \
root=/dev/nfs \
nfsroot=192.168.1.1:/home/kullanici/nfs/rootfs,v4.1,tcp \
ip=dhcp \
rw"
nfsroot parametresi sözdizimi:
ip= parametresi sözdizimi:
ip=ISTEMCI:SUNUCU:GATEWAY:NETMASK:HOSTNAME:ARABIRIM:OTOCONFIGÜRASYON
# Örnek: statik IP yapılandırması
ip=192.168.1.100:192.168.1.1:192.168.1.1:255.255.255.0:gömülü-hedef:eth0:off
# DHCP
ip=dhcp
# Belirli arabirim üzerinden DHCP
ip=:::::::eth0:dhcp
03 NFSv3 vs NFSv4
NFSv3 ve NFSv4 arasındaki mimari farklılıklar, gömülü sistemlerde hangi versiyonun kullanılacağını etkiler. Durumsuzluk, güvenlik modeli ve çekirdek boyutu başlıca karşılaştırma eksenleridir.
NFSv3 durumsuz (stateless) bir protokoldür: her istek kendi başına tam bir işlemdir, sunucu istemci durumunu tutmaz. Bu yaklaşım basit ve sağlamdır; ağ bağlantısı kesilip yeniden kurulursa istemci kaldığı yerden devam edebilir. Gömülü geliştirme ortamları için NFSv3 genellikle tercih edilir.
NFSv4 ise durum bilgisi tutan (stateful) bir protokoldür. Dosya kilitleme, devir teslimi (delegation) ve bileşik işlemler (compound operations) gibi özellikler eklenmiştir. Tek TCP bağlantısı ile çalışır, bu da NAT ve güvenlik duvarı ortamlarında avantaj sağlar.
| Özellik | NFSv3 | NFSv4 / v4.1 |
|---|---|---|
| Durum modeli | Durumsuz | Durum bilgili |
| TCP bağlantısı | Her işlem için ayrı | Tek kalıcı bağlantı |
| Güvenlik | AUTH_SYS (UID/GID) | AUTH_SYS veya RPCSEC_GSS/Kerberos |
| Dosya kilitleme | nlm (ayrı daemon) | Yerleşik (built-in) |
| NAT / güvenlik duvarı | Sorunlu (portmap, mountd) | Tek port (2049), kolay |
| Kernel boyutu etkisi | Küçük | Biraz daha büyük |
| Geliştirme ortamı uyumu | Yüksek (evrensel) | Yüksek (modern sistemler) |
| pNFS (paralel NFS) | Yok | v4.1+ destekler |
Gömülü geliştirme için pratik tavsiye: laboratuvar ortamında NAT yoksa ve güvenlik gereksinimleri basitse NFSv3 + TCP tercih edin; yapılandırması daha basit ve sorun gidermesi kolaydır. Üretim benzeri güvenli test ortamı için NFSv4.1 + Kerberos veya en azından NFSv4 + güvenlik duvarı kullanın.
Çekirdek NFS istemci yapılandırmasında versiyon farkı:
# Minimal NFSv3 için (küçük çekirdek)
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V4 is not set
CONFIG_ROOT_NFS=y
# NFSv4 eklemek için
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y # pNFS desteği
CONFIG_NFS_V4_2=y # NFSv4.2 sunucu tarafı kopya vb.
# NFSv4 Kerberos güvenliği için (daha büyük çekirdek)
CONFIG_RPCSEC_GSS_KRB5=y
04 Performans Ayarları
NFS rootfs üzerinde çalışan gömülü sistemlerde ağ dosya sistemi gecikmesi belirleyici olabilir. rsize/wsize, önbellek seçenekleri ve TCP ayarları ile performans önemli ölçüde iyileştirilebilir.
En kritik parametre çifti rsize ve wsize'dır. Varsayılan
değer (4096 B veya 8192 B) modern ağlar için çok küçüktür; 65536 B veya 131072 B
değerleri genellikle en iyi sonucu verir:
# /etc/fstab üzerinden NFS mount — performans odaklı
192.168.1.1:/nfs/rootfs / nfs \
rsize=65536,wsize=65536,hard,intr,tcp,noatime,nodiratime,vers=3 0 0
# Komut satırından mount (test için)
mount -t nfs \
-o rsize=65536,wsize=65536,hard,intr,tcp,noatime,vers=3 \
192.168.1.1:/nfs/rootfs /mnt/nfs
NFS mount seçenekleri — performans ve güvenilirlik:
Sunucu tarafında NFS daemon işçi sayısını artırmak çok istemcili senaryolarda yardımcı olur:
# /etc/nfs.conf veya /etc/default/nfs-kernel-server
# İşçi sayısını artır (varsayılan 8)
[nfsd]
threads=16
# Değişikliği uygula
sudo systemctl restart nfs-server
# Aktif bağlantıları ve istatistikleri izle
nfsstat -s # sunucu istatistikleri
nfsstat -c # istemci istatistikleri
TCP tampon boyutları da NFS performansını etkiler. Çekirdek ağ parametrelerini ayarlamak yüksek bant genişliği gerektiren geliştirme senaryolarında fark yaratır:
# /etc/sysctl.d/nfs-perf.conf
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
# Uygula
sudo sysctl -p /etc/sysctl.d/nfs-perf.conf
05 Güvenli NFS
Laboratuvar dışı ortamlarda veya üretim benzeri test altyapısında NFS güvenliği göz ardı edilemez. Kerberos ile NFSv4, IP tabanlı kısıtlamalar ve güvenlik duvarı kuralları temel güvenlik katmanlarını oluşturur.
Temel güvenlik ilkeleri: NFS paylaşımlarını yalnızca güvenilir ağ segmentlerine açın,
no_root_squash seçeneğini üretim ortamında kullanmayın ve mümkünse
NFSv4 + RPCSEC_GSS (Kerberos) kullanın.
IP tabanlı kısıtlama (en basit yöntem):
# /etc/exports — yalnızca belirli IP aralığına izin ver
/nfs/rootfs 192.168.10.0/24(rw,sync,no_subtree_check,root_squash)
# Dışarıdan erişimi kapat
sudo ufw default deny incoming
sudo ufw allow from 192.168.10.0/24 to any port 2049 # NFS
sudo ufw allow from 192.168.10.0/24 to any port 111 # rpcbind
NFSv4 ile Kerberos (sec=krb5) kurulumu genel akışı: Bu yapılandırma Kerberos KDC (Key Distribution Center) gerektirdiğinden kurulum daha karmaşıktır, ancak kimlik doğrulama ve şifreleme sağlar.
NFSv4 + Kerberos bağlantı akışı:
Gömülü İstemci NFS Sunucusu Kerberos KDC
| | |
|-- kinit (servis bileti iste) --->| |
|<------------------------------------ TGT --------------|
|-- nfs/sunucu@REALM için bilet iste ------------------>|
|<---------------------------------- Servis bileti ------|
|-- NFS mount isteği (RPCSEC_GSS) -->| |
|<---------- Mount onayı (şifreli) --| |
|===== Şifreli NFS veri akışı ======| |
# Sunucu: /etc/exports — Kerberos güvenliği
/nfs/secure 192.168.10.0/24(rw,sync,sec=krb5p,no_subtree_check)
# sec=krb5 : yalnızca kimlik doğrulama
# sec=krb5i : kimlik doğrulama + bütünlük
# sec=krb5p : kimlik doğrulama + bütünlük + gizlilik (şifreleme)
# İstemci kernel yapılandırması (Kerberos desteği)
CONFIG_RPCSEC_GSS_KRB5=y
# İstemcide /etc/fstab
192.168.10.1:/nfs/secure /mnt/secure nfs4 sec=krb5p,rsize=65536,wsize=65536 0 0
Üretim gömülü sistemlerde NFS kullanımı oldukça sınırlı tutulmalıdır. NFS bağımlılığı ağ bağlantı sorunlarını cihaz arızasına dönüştürür. Bu nedenle yalnızca uygulama güncellemeleri veya opsiyonel veri dizinleri için NFS kullanın; temel sistem dosyaları her zaman yerel depolamada olmalıdır.
06 Automount ile NFS
Automount, NFS paylaşımlarını yalnızca erişildiğinde bağlar ve belirli süre erişilmezse otomatik olarak ayırır. Bu yaklaşım önyükleme süresini kısaltır ve ağ bağlantısı geçici olarak kesildiğinde sistemi kilitleyen kalıcı mount sorunlarını önler.
Gömülü sistemlerde automount için iki ana yol vardır: klasik autofs
daemon'u ve systemd'nin yerleşik .automount birimleri.
autofs ile NFS automount:
# autofs kurulumu
sudo apt-get install autofs
# /etc/auto.master — ana harita
/mnt/nfs /etc/auto.nfs --timeout=60
# /etc/auto.nfs — NFS haritası
rootfs -rw,soft,intr,rsize=65536,wsize=65536 192.168.1.1:/nfs/rootfs
shared -ro,soft,intr 192.168.1.1:/nfs/shared
logs -rw,soft,intr,async 192.168.1.1:/nfs/logs
# autofs servisini başlat
sudo systemctl enable --now autofs
# /mnt/nfs/rootfs erişildiğinde otomatik mount edilir
ls /mnt/nfs/rootfs/
systemd .automount birimi:
# /etc/systemd/system/mnt-nfs-data.mount
[Unit]
Description=NFS Veri Paylaşımı
After=network-online.target
Wants=network-online.target
[Mount]
What=192.168.1.1:/nfs/data
Where=/mnt/nfs/data
Type=nfs
Options=rw,soft,intr,rsize=65536,wsize=65536,vers=3
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/mnt-nfs-data.automount
[Unit]
Description=NFS Veri Paylaşımı Otomatik Mount
After=network-online.target
[Automount]
Where=/mnt/nfs/data
TimeoutIdleSec=120
[Install]
WantedBy=multi-user.target
# Automount birimini etkinleştir (.mount birimini değil!)
sudo systemctl enable --now mnt-nfs-data.automount
# Durumu kontrol et
sudo systemctl status mnt-nfs-data.automount
sudo systemctl status mnt-nfs-data.mount
Automount zaman aşımı (TimeoutIdleSec veya autofs --timeout)
dikkatli ayarlanmalıdır. Çok kısa bir değer (10–30 sn) sürekli mount/umount döngüsüne
yol açar; çok uzun bir değer ise ağ hatası sonrası kurtarma süresini uzatır.
60–120 saniye çoğu gömülü senaryo için makuldür.
07 Yocto ile NFS rootfs
Yocto, NFS tabanlı geliştirme iş akışını destekleyen çeşitli araçlar sunar:
runqemu ile QEMU üzerinde NFS boot, devtool deploy-target
ile doğrudan hedef cihaza dosya gönderme ve IMAGE_FSTYPES ile
NFS uyumlu tar arşivi oluşturma.
NFS geliştirmesi için rootfs tar arşivi oluşturmak üzere local.conf
dosyasına aşağıdaki satırı ekleyin:
# build/conf/local.conf
IMAGE_FSTYPES += "tar.bz2"
# İsteğe bağlı: NFS hata ayıklama için debug paketleri ekle
EXTRA_IMAGE_FEATURES += "debug-tweaks tools-debug"
# Geliştirme araçlarını dahil et
EXTRA_IMAGE_FEATURES += "tools-profile ssh-server-openssh"
# Yocto imajını derle
bitbake core-image-minimal
# tar arşivini NFS dizinine aç
sudo mkdir -p /home/kullanici/nfs/rootfs
sudo tar -xjf tmp/deploy/images/TARGET/core-image-minimal-TARGET.tar.bz2 \
-C /home/kullanici/nfs/rootfs/
# NFS ihracatını güncelle
sudo exportfs -ra
runqemu ile QEMU + NFS boot: Yocto'nun runqemu aracı
NFS rootfs ile QEMU başlatmayı tek komuta indirir:
# QEMU'yu NFS rootfs ile başlat
runqemu qemux86-64 nfs
# Belirli NFS dizini ve kernel belirt
runqemu qemux86-64 nfs \
nfsdir=/home/kullanici/nfs/rootfs \
QEMU_KERNEL=/path/to/bzImage
# Ağ arabirimi ile birlikte
runqemu qemux86-64 nfs slirp
devtool deploy-target ile gerçek donanıma hızlı güncelleme: NFS rootfs üzerinde çalışan bir hedef cihaza tek tek paket güncellemesi yapılabilir:
# Hedef cihaz NFS rootfs ile çalışıyor, SSH erişimi var
# Belirli bir paketi derle ve cihaza gönder
devtool modify busybox
# ... değişiklik yap ...
devtool deploy-target busybox root@192.168.1.100
# Özel bir uygulama güncelle
devtool build myapp
devtool deploy-target myapp root@192.168.1.100
# Dağıtımı geri al
devtool undeploy-target myapp root@192.168.1.100
Yocto SDK ile çapraz derlenmiş ikili doğrudan NFS paylaşım dizinine kopyalanabilir; hedef cihazda yeniden başlatmaya gerek kalmadan test edilebilir. Bu iş akışı özellikle kullanıcı alanı daemon'ları ve sistem kütüphaneleri için çok zaman kazandırır.
08 Hata Ayıklama
NFS sorunlarını teşhis etmek için sunucu ve istemci tarafında çeşitli araçlar kullanılır:
showmount, nfsstat, rpcinfo, çekirdek RPC
hata ayıklama bayrakları ve Wireshark paket analizi.
showmount — sunucu paylaşımlarını sorgula:
# Sunucudaki tüm NFS paylaşımlarını listele
showmount -e 192.168.1.1
# Bağlı istemcileri listele
showmount -a 192.168.1.1
# Dışa aktarılan dizin ağacını göster
showmount -d 192.168.1.1
rpcinfo — RPC servislerini sorgula:
# Sunucudaki kayıtlı RPC servislerini listele
rpcinfo -p 192.168.1.1
# NFS portmapper'ının erişilebilirliğini test et
rpcinfo -t 192.168.1.1 nfs 3 # NFSv3
rpcinfo -t 192.168.1.1 nfs 4 # NFSv4
nfsstat — NFS istatistikleri:
# İstemci istatistikleri (başarısız işlemler, yeniden denemeler)
nfsstat -c
# Sunucu istatistikleri
nfsstat -s
# Ayrıntılı RPC istatistikleri
nfsstat -r
# Sürekli izleme (her 2 saniyede bir güncelle)
nfsstat -c 2
Çekirdek RPC hata ayıklama bayrakları:
# Tüm NFS istemci debug bayraklarını etkinleştir
echo 0xFFFF > /proc/sys/sunrpc/nfs_debug
# Yalnızca mount hata ayıklama
echo 0x0002 > /proc/sys/sunrpc/nfs_debug
# RPC katmanı hata ayıklama
echo 0xFFFF > /proc/sys/sunrpc/rpc_debug
# dmesg ile RPC günlüklerini izle
dmesg -w | grep -E "nfs|rpc|sunrpc"
# Hata ayıklamayı kapat
echo 0 > /proc/sys/sunrpc/nfs_debug
echo 0 > /proc/sys/sunrpc/rpc_debug
Yaygın NFS hataları ve çözümleri:
# UID/GID uyuşmazlığını teşhis et
# İstemcide:
id kullanici
# Sunucuda:
id kullanici
# Farklıysa: sunucu ve istemci arasında kullanıcı senkronizasyonu gerekli
# (LDAP, /etc/passwd kopyalama veya idmapd yapılandırması)
# Wireshark ile NFS paket analizi (geliştirici bilgisayarında)
# nfs filtresini kullan
tshark -i eth0 -f "port 2049" -w nfs_capture.pcap