15 puan yazan GN⁺ 2024-09-01 | 2 yorum | WhatsApp'ta paylaş
  • İnsanların, Linux çekirdeği API belgelerinin ne kadar eksik olduğunun ve Rust'ın bu sorunun bir kısmını nasıl çözdüğünün yeterince farkında olmadığını düşünüyorum
  • Birden fazla alt sistem için Rust soyutlamaları yazdım ve API'yi güvenli biçimde nasıl kullanacağımı tam olarak anlamak için neredeyse her durumda C kaynak kodunu okumam gerekti
  • Yalnızca işlev imzalarından ve ilgili belge yorumlarından ya da açık belgelerden, API'nin güvenli kullanım biçimini tam olarak çıkarmak zor
    • Kilidin tutulması gerekip gerekmediği
    • Referans sayacı argümanının bir referans devredip devretmediği ya da kendi adına bir referans alıp almadığı
    • Callback çağrılırken kilidin tutulup tutulmadığı ya da doğrudan sizin almanız gerekip gerekmediği
    • free callback'inde özel bir durum olup olmadığı
    • Amaçlanan kilitleme sırasının ne olduğu
    • Bazı işlemlerin duruma göre kilit kullanabildiği özel koşullar olup olmadığı
    • NULL argümanlarına izin verilip verilmediği ve geçerli kullanım şekli
    • Hata durumunda referans sayacına ne olduğu
    • Döndürülen referans sayımlı işaretçinin zaten artırılmış olup olmadığı ya da geçirilen argümanın referansından örtük bir ödünç alma mı olduğu
    • Dönüş değerinin her zaman geçerli bir işaretçi olup olmadığı, NULL olabildiği ya da ERR_PTR de olabildiği
    • Dolaylı argümanlar üzerinden döndürülen işaretçilerin hata durumunda NULL yapılıp yapılmadığı ya da olduğu gibi bırakıldığı
    • Dönüş işaretçisine ihtiyaç yokken NULL ** geçirmenin geçerli olup olmadığı
  • Bazen gereksinimler makuldü ama belgelenmemişti
    • Bazen gereksinimler o kadar esnek ya da karmaşıktı ki, Rust soyutlaması yazarken güvenli kullanım biçimine daraltmak için öznel kararlar vermek zorunda kaldım
    • Bazen güvenliği sağlamak için soyutlamanın içine ek kilitleme koymam gerekti
    • Bazen C kodunu daha ortogonal, daha mantıklı ve daha kullanışlı yapmak için küçük değişiklikler yapmak gerekti (ör. kilitliyken kullanılacak kilit açma işlevini ortaya çıkarmak)
    • Bazen kilitleme çok incelikliydi; güvenli bir Rust soyutlaması yazmak mümkün olsa da, deadlock'tan kaçınmak için kullanım ve bırakma sırasına dikkat edilmesi gerektiğini anlatan büyük belge yorumları gerekiyordu (Rust özünde deadlock'ı engellemez)
    • Bazen C kodunu daha makul hale getirmeden çözüm imkânsızdı (drm_sched örneğinde olduğu gibi)
  • Ancak çoğu durumda Rust soyutlaması yazarken verilen tavizler, C kodu tasarımındaki sorunlara ve iyileştirme yönlerine işaret ediyor
    • Genel yaklaşım, "önce C kodunu olabildiğince az değiştirerek Rust kodunu yazmak ve çatışmadan kaçınmak, sonra da öğrenilen derslere dayanarak C kodu değişiklikleri önermek" şeklinde (henüz ikinci kısma gelemedim)
  • Sonuç olarak çoğu durumda yalnızca Rust API'sine bakarak doğru kullanım biçimini anlamak mümkün
    • Referans sayımı, NULL işaretçiler, sonuç denetimini atlama ya da hata durumunda referansı bırakma gibi şeyler için endişelenmeye gerek yok
    • Doğru kilitleme kullanımı, referans almayı unutma ya da iki kez serbest bırakma gibi konular için endişelenmeye gerek yok
    • Hata dönüş değerlerinin nasıl kodlandığını merak etmeye gerek yok
    • Çünkü bunları yanlış yaparsanız kod derlenmez
    • Elbette API yine de yanlış kullanılabilir ama en kötü durumda hata dönüşü ya da deadlock olur (deadlock lockdep ile kolayca hata ayıklanabilir ve Arc<> entegrasyonu ile serbest bırakma/referans bırakma kaynaklı kilit hataları yakalanabilir)
  • Nispeten sıkı belgelenmiş OpenFirmware/DeviceTree API'sinde bile, C'de tüm kurallara uymak sıkıcı ve hataya açık
    • Sürücülerin OF koduna bakınca referans sızıntısı olasılığı yüksek
    • Çoğu sistem çekirdeği OF_DYNAMIC ile derlemediği için referans sayımı yok sayılıyor; bu yüzden sorunlar ne bulunuyor ne de düzeltiliyor
    • Ancak yazdığım OF Rust soyutlaması referans sayımını otomatik yönettiği için bununla uğraşmak gerekmiyor
  • C'ye kıyasla Rust ile çekirdek kodlamanın avantajları
    • C ile çekirdek kodlarken aslında yalnızca iki seçenek var
    • Ya deneyip gözden geçiren kişinin hataları yakalamasını umarsınız ya da hata ayıklamayla uğraşırsınız
    • Ya da kodu kullanmaya cesaret etmeden önce saatlerce anlamaya çalışır ve her şeyi yakalamayı umarsınız
    • Bu, gözden geçirenlerin ve bakımcıların iş yükünü de artırır
      • Gönderilerin, belgelenmemiş gizli kuralların hepsine uyup uymadığını kontrol etmeleri gerekir
      • Bazen sorunlar gözden kaçar, bazen de o kadar büyüktür ki kodun kapsamlı biçimde yeniden düzenlenmesi gerekir
  • Rust'ta bunların çoğu ortadan kalkar. Derleniyorsa güvenlidir; yanlış çalışma ya da referans sızıntısı yoktur (unsafe kod hariç, ama yalnızca onun gözden geçirilmesi gerekir ve iyi belgelenmiş olması şartı vardır)
    • Elbette yine de kod incelemesi ve belirli alt sistem uzmanlarının yardımı gerekir. Rust sihirli biçimde kodu kusursuz yapmaz
    • Ancak tüm bu aptalca düşük seviye sorunları ve hataları ortadan kaldırdığı için üst düzey sorunlara odaklanmayı sağlar
  • Linux geliştiricilerine bakış
    • Linux geliştiricilerinin eksik belgelerini suçlamıyorum
    • Linux çekirdeği çok karmaşık ve pek çok incelikli sorunla uğraşmak zorunda
    • Çoğu kullanıcı alanı API'si, güvenli kullanım için çok daha basit kurallara sahip
    • Çekirdek zordur
    • Deneyimli çekirdek geliştiricileri bile bunları her zaman yanlış yapabiliyor
    • Bu bir teknoloji sorunu değil; insanın bütün bu karmaşık kuralları zihninde tutup her seferinde kusursuz uygulaması imkânsız
  • Çözüm
    • Araçlara ihtiyacımız var
    • Çözüm Rust. Tüm kurallar bir kez koda ve tür sistemine işlendiğinde, bir daha endişelenmek gerekmiyor
    • Bu, kodlama stili tartışmalarının çözümünün bütün kuralları otomatik biçimlendiriciye kodlamak olmasına benziyor
    • Böylece tüm düşük seviye güvenlik, sahiplik ve eşzamanlama sorunları hakkında endişelenmeyi bırakıp sürücü ve alt sistem tasarımı gibi daha önemli üst düzey konulara odaklanabiliriz
  • Rust for Linux projesinde kod biçimlendirme
    • Rust for Linux projesi gerçekten de gönderilerde rustfmt kullanıyor
    • Çekirdek Rust yazarken kod biçimlendirmesi ya da kod incelemesinde gelecek şikâyetler konusunda endişelenmenize gerek yok
    • Sadece make rustfmt çalıştırmanız yeterli

GN⁺ görüşü

  • Bu yazı, Linux çekirdek geliştirmesinde API belgelendirme ve güvenlik sorunlarını iyi işaret ediyor. C dilinin sınırlarını ve Rust'ın avantajlarını iyi gösteriyor
  • Ancak "Rust tek çözüm" ifadesi biraz abartılı görünüyor. Statik analiz araçları gibi başka yöntemlerle de bazı iyileştirmeler yapılabilir
  • Rust bellek güvenliği gibi birçok sorunu çözüyor olsa da, dikkatli kod incelemesi ve test hâlâ gerekli. Bu bir gümüş kurşun değil
  • Rust'a geçiş, mevcut C koduyla uyumluluk ve geliştirici öğrenme eğrisi gibi çeşitli zorluklar içerebilir. Kademeli benimseme daha uygun görünüyor
  • Linux çekirdeğinin eski alışkanlıklarını ve kültürünü iyileştirmek için Rust'ın yanında belgelendirme, mentorluk ve iletişim gibi birçok alanda da çaba gerekebilir
  • Genel olarak bu yazı, Rust'ın Linux çekirdek geliştirmesindeki potansiyelini ve avantajlarını iyi gösterirken, aşırı beklenti ya da kör inanç konusunda da temkinli davranarak dengeli bir bakış sunuyor. Rust'ın benimsenmesi teknik ve kültürel olarak zor olabilir ama uzun vadede çekirdek kodunun güvenliği ve bakım kolaylığının artmasına katkı sağlayabilir.

2 yorum

 
aer0700 2024-09-01

Rust... Ben de kişisel olarak biraz çalıştım ama şirketimizde henüz kullanmaya başlamadık. Zaten C++ ile yazılmış yığınla şey var ve mevcut ekiplerin rustu yeniden öğrenmesi gerektiği gibi bir sorun da var... Rust'ı hâlihazırda production'da kullanan şirketlerin Kore'de de olduğunu duydum; bu konuda deneyimlerin paylaşılması güzel olur diye düşünüyorum.

 
GN⁺ 2024-09-01
Hacker News görüşü
  • Rust ve Swift gibi dillerin ifade gücü yüksektir; derleyici veri türlerinin veya metotların thread safety durumunu gösterebilir

    • Kod incelemesi sırasında pointer kullanımının güvenli olup olmadığını tek tek kontrol etmeye gerek kalmaz ve memory-safe bir dil kullanıldığında iş mantığını uygulamaya odaklanılabilir
  • Rust kütüphanelerinin birçoğunda dokümantasyon yetersiz olabiliyor

    • Rust, eksik API dokümantasyonu sorununu çözmez; bu sorunu API dokümantasyonunu titizlikle hazırlayan geliştiriciler çözer
  • Rust'ı C gibi kullanmaya çalışırken borrow checker sorunları nedeniyle zorlanıldı

    • Fonksiyon imzasını okuyup &self veya &mut self olup olmadığını kontrol etmek önemlidir
    • &mut self varsa, instance'ı thread'ler arasında paylaşmak için mutex kullanmak gerekir
  • Rust API'sine bakınca çoğu durumda onu doğru kullanma yöntemi anlaşılabilir

    • Ancak bazı Rust API'lerinde, yalnızca fonksiyon imzasına bakarak türün nasıl oluşturulacağını anlamak mümkün olmadığından Google'da arama yapmak gerekir
  • Rust'ta somut bir örnek olarak veriyi korumak için lock kullanma yaklaşımı vardır

    • Rust'ta lock, korunan veriyi sarar; bu yüzden lock'u bırakmadan veriye erişmek mümkün değildir
  • Diğer dillerde de API'yi tekrar uygulamak kodun ve dokümantasyonun açıklığını artırabilir

    • Yakın tarihli bir deneyimde, network stack'te hatalı bir değişiklik incelemeden geçip kararlı sürüme dahil edilmişti
    • Bu tür sorunlardan kaçınmak için araçlardan yararlanmak iyi olur
  • Python extension'larında C kullanırken calling convention'ı bilme zorunluluğu gibi bir sorun vardır

    • Rust ve PyO3 kullanıldığında bu sorun ortadan kalkar ve giriş bariyeri düşer
    • C++ da benzer işlevler sunar, ancak Rust kadar güvenli değildir
  • Bu insanlar kahraman ve harika işler yapıyor

  • Tam anlamıyla kendi kendini belgeleyen kodu hayata geçirmeye bir adım daha yaklaşılıyor