15 पॉइंट द्वारा GN⁺ 2024-09-01 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • मेरा मानना है कि लोग पर्याप्त रूप से नहीं समझते कि Linux kernel API documentation कितनी अधूरी है, और Rust उस समस्या के एक हिस्से को कैसे हल करता है
  • मैंने कई subsystems के लिए Rust abstractions लिखीं, और API को सुरक्षित रूप से इस्तेमाल करने का तरीका पूरी तरह समझने के लिए लगभग हर मामले में C source code पढ़ना पड़ा
  • सिर्फ function signatures और संबंधित documentation comments या स्पष्ट दस्तावेज़ों से API के सुरक्षित उपयोग का तरीका पूरी तरह समझना कठिन है
    • क्या lock पकड़े रखना आवश्यक है
    • क्या reference count argument reference transfer करता है या खुद reference ले लेता है
    • callback call के समय lock बना रहता है या उसे सीधे acquire करना पड़ता है
    • क्या free callback में कुछ विशेष है
    • intended lock ordering क्या है
    • क्या कुछ operations में ऐसे विशेष मामले हैं जहाँ lock को conditionally इस्तेमाल किया जा सकता है
    • क्या NULL argument की अनुमति है और उसका वैध उपयोग क्या है
    • error की स्थिति में reference count का क्या होता है
    • क्या लौटाया गया reference-counted pointer पहले से incremented होता है, या दिए गए argument के reference से implicit borrow होता है
    • क्या return value हमेशा valid pointer है, NULL हो सकती है, या ERR_PTR भी हो सकती है
    • क्या indirect arguments के ज़रिए लौटाया गया pointer error पर NULL कर दिया जाता है या वैसा ही छोड़ दिया जाता है
    • अगर return pointer की ज़रूरत न हो तो NULL ** देना वैध है या नहीं
  • कभी-कभी requirements उचित थीं, लेकिन उनका documentation नहीं था
    • कभी-कभी requirements इतनी लचीली या जटिल थीं कि Rust abstraction लिखते समय सुरक्षित उपयोग तक सीमित करने के लिए subjective निर्णय लेने पड़े
    • कभी-कभी safety सुनिश्चित करने के लिए abstraction के अंदर अतिरिक्त locking लानी पड़ी
    • कभी-कभी C code को थोड़ा बदलना पड़ा ताकि वह अधिक orthogonal, logical और इस्तेमाल में आसान बने (उदाहरण: locked state में उपयोग के लिए unlock function expose करना)
    • कभी-कभी locking इतनी सूक्ष्म थी कि safe Rust abstraction लिखना संभव था, लेकिन deadlock से बचने के लिए usage और drop order पर ध्यान देने वाली बड़ी documentation comment की ज़रूरत पड़ी (Rust स्वाभाविक रूप से deadlock नहीं रोकता)
    • कभी-कभी C code को अधिक तर्कसंगत बनाए बिना समस्या हल ही नहीं हो सकती थी (drm_sched के मामले में)
  • लेकिन अधिकांश मामलों में Rust abstraction लिखते समय हुए समझौते C code design की समस्याओं और सुधार की दिशा का संकेत देते हैं
    • सामान्य तरीका यह है कि "पहले C code में जितना संभव हो उतना कम बदलाव करते हुए Rust code लिखो ताकि टकराव से बचा जा सके, फिर सीखे गए सबक के आधार पर C code changes प्रस्तावित करो" (अभी तक दूसरे हिस्से तक पहुँचा नहीं गया है)
  • नतीजतन, अधिकांश मामलों में सिर्फ Rust API देखकर सही उपयोग समझा जा सकता है
    • reference count, NULL pointers, result check छूट जाना, error पर unref करना आदि की चिंता करने की ज़रूरत नहीं रहती
    • सही locking use, reference acquire छूट जाना या double free जैसी बातों की चिंता करने की ज़रूरत नहीं रहती
    • error return values की encoding कैसे हुई है, यह सोचने की ज़रूरत नहीं रहती
    • क्योंकि अगर ये चीज़ें गलत हों तो code compile ही नहीं होगा
    • बेशक API का गलत उपयोग फिर भी संभव है, लेकिन सबसे बुरी स्थिति में error return या deadlock होगा (deadlock को lockdep से आसानी से debug किया जा सकता है, और Arc<> integration release/unref से जुड़ी locking errors पकड़ सकता है)
  • अपेक्षाकृत सख्ती से documented OpenFirmware/DeviceTree API में भी C में सभी नियमों का पालन करना उबाऊ और error-prone है
    • drivers के OF code को देखें तो reference leaks की संभावना काफ़ी ज़्यादा होती है
    • ज़्यादातर systems kernel को OF_DYNAMIC के साथ compile नहीं करते, इसलिए reference counts को अनदेखा कर दिया जाता है, और यह न तो पकड़ा जाता है न ठीक किया जाता है
    • लेकिन मैंने जो OF Rust abstraction लिखी है, वह reference counting अपने-आप संभालती है, इसलिए इसकी चिंता नहीं करनी पड़ती
  • C की तुलना में Rust में kernel coding के फायदे
    • C में kernel coding करते समय आपके पास मूलतः सिर्फ दो विकल्प होते हैं
    • बस लिखो और उम्मीद करो कि reviewer उसे पकड़ लेगा, या debugging में परेशान हो
    • या code इस्तेमाल करने की हिम्मत करने से पहले घंटों उसे समझो और उम्मीद करो कि सब कुछ पकड़ लिया है
    • इससे reviewers और maintainers का workload भी बढ़ता है
      • उन्हें submissions की जाँच करनी पड़ती है कि कहीं undocumented hidden rules का उल्लंघन तो नहीं हुआ
      • कभी-कभी वे समस्याएँ मिस कर देते हैं, और कभी समस्या इतनी बड़ी होती है कि code को बड़े पैमाने पर refactor करना पड़ता है
  • Rust में यह सब गायब हो जाता है। अगर code compile हो जाता है, तो वह safe है और उसमें misuse या reference leaks नहीं होंगी (unsafe code अपवाद है, लेकिन सिर्फ उसी की समीक्षा करनी होती है, और उसके लिए अच्छी documentation अनिवार्य मानी जाती है)
    • बेशक, code review और specific subsystem experts की मदद की ज़रूरत फिर भी रहती है। Rust कोई जादू नहीं है जो code को अपने-आप परिपूर्ण बना दे
    • लेकिन यह सभी मूर्खतापूर्ण low-level समस्याओं और गलतियों को हटा देता है, जिससे high-level समस्याओं पर ध्यान केंद्रित किया जा सकता है
  • Linux developers के बारे में दृष्टिकोण
    • मैं Linux developers की अधूरी documentation के लिए उन्हें दोष नहीं देता
    • Linux kernel बहुत जटिल है और उसे कई सूक्ष्म समस्याओं से निपटना पड़ता है
    • अधिकांश userspace APIs में सुरक्षित उपयोग के लिए कहीं अधिक सरल नियम होते हैं
    • kernel कठिन है
    • अनुभवी kernel developers भी अक्सर इन चीज़ों में गलती कर बैठते हैं
    • यह सिर्फ तकनीक की समस्या नहीं है; इंसानों के लिए इन सारे जटिल नियमों को दिमाग में रखना और हर बार सही ढंग से लागू करना असंभव है
  • समाधान
    • हमें tools की ज़रूरत है
    • समाधान Rust है। सभी नियमों को एक बार code और type system में encode कर दिया जाए, तो फिर बार-बार चिंता करने की ज़रूरत नहीं रहती
    • जैसे coding style बहस का समाधान यह है कि सभी नियमों को automatic formatter में encode कर दिया जाए
    • तब हम low-level safety, ownership और synchronization की सारी चिंता छोड़कर high-level driver और subsystem design जैसी ज़्यादा महत्वपूर्ण चीज़ों पर ध्यान दे सकते हैं
  • Rust for Linux project में code formatting
    • Rust for Linux project वास्तव में submissions पर rustfmt लागू करता है
    • kernel Rust लिखते समय code formatting या code review में format को लेकर शिकायतों की चिंता करने की ज़रूरत नहीं है
    • बस make rustfmt चला दें

GN⁺ की राय

  • यह लेख Linux kernel development में API documentation और safety की समस्याओं को अच्छे से रेखांकित करता है। यह C भाषा की सीमाओं और Rust के फायदों को स्पष्ट दिखाता है
  • हालांकि, "Rust ही एकमात्र समाधान है" जैसी बात कुछ हद तक अतिशयोक्तिपूर्ण लगती है। static analysis tools जैसी अन्य विधियों से भी कुछ सुधार संभव हो सकते हैं
  • Rust memory safety जैसी कई समस्याएँ हल करता है, लेकिन फिर भी बारीक code review और testing की ज़रूरत रहती है। यह कोई silver bullet नहीं है
  • Rust में बदलाव लाने के साथ existing C code के साथ compatibility, developers की learning curve जैसी कई कठिनाइयाँ हो सकती हैं। इसलिए क्रमिक अपनाना अधिक उपयुक्त लगता है
  • Linux kernel की पुरानी प्रथाओं और संस्कृति को सुधारने के लिए Rust के अलावा documentation, mentoring, communication आदि में भी बहुआयामी प्रयासों की ज़रूरत होगी
  • कुल मिलाकर, यह लेख Linux kernel development में Rust की क्षमता और फायदों को अच्छी तरह दिखाता है, साथ ही अति-उम्मीद या अंधविश्वास से भी सावधान करता है। Rust को अपनाना तकनीकी और सांस्कृतिक दोनों दृष्टि से कठिन हो सकता है, लेकिन लंबे समय में यह kernel code की safety और maintainability सुधारने में योगदान दे सकता है।

2 टिप्पणियां

 
aer0700 2024-09-01

Rust... मैंने व्यक्तिगत रूप से इसे पढ़ने की कोशिश की है, लेकिन अभी हमारी कंपनी में इसे अपनाया नहीं गया है। C++ में पहले से लिखा हुआ बहुत सारा कोड है, और मौजूदा लोगों को rust फिर से सीखना पड़ेगा, यह भी एक समस्या है... मैंने सुना है कि कोरिया में भी कुछ कंपनियाँ पहले से rust को production में इस्तेमाल कर रही हैं; अच्छा होगा अगर इस बारे में अनुभव वगैरह साझा किए जाएँ।

 
GN⁺ 2024-09-01
Hacker News की राय
  • Rust और Swift जैसी भाषाओं की expressiveness अधिक होती है, इसलिए compiler data types या methods की thread safety बता देता है

    • code review के समय pointer के उपयोग की safety को एक-एक करके जाँचने की ज़रूरत नहीं पड़ती, और memory-safe language का उपयोग करने पर business logic लागू करने पर ध्यान केंद्रित किया जा सकता है
  • कई Rust libraries में documentation की कमी होती है

    • Rust अधूरे API docs की समस्या को हल नहीं करता; API documentation को अच्छी तरह लिखने वाले developers ही इस समस्या को हल करते हैं
  • Rust को C की तरह इस्तेमाल करने की कोशिश करते समय borrow checker की वजह से कठिनाई होती है

    • function signature पढ़कर &self या &mut self को देखना महत्वपूर्ण है
    • अगर &mut self है, तो instance को threads के बीच साझा करने के लिए mutex का उपयोग करना चाहिए
  • Rust API को देखकर अधिकांश मामलों में यह समझा जा सकता है कि उसे सही तरह से कैसे इस्तेमाल करना है

    • लेकिन कुछ Rust APIs में केवल function signature से यह समझ नहीं आता कि type को कैसे बनाया जाए, इसलिए Google करना पड़ता है
  • Rust का एक ठोस उदाहरण यह है कि data protection के लिए lock का उपयोग किया जाता है

    • Rust में lock संरक्षित data को wrap करता है, इसलिए lock release किए बिना data को access नहीं किया जा सकता
  • दूसरी भाषाओं में भी API को दोबारा implement करने से code और documentation की स्पष्टता बढ़ सकती है

    • हाल के अनुभव में, network stack में एक गलत बदलाव review पार कर गया और stable version में शामिल हो गया
    • ऐसी समस्याओं से बचने के लिए tools का उपयोग करना बेहतर है
  • Python extension में C का उपयोग करते समय calling convention जानने की समस्या होती है

    • Rust और PyO3 का उपयोग करने पर यह समस्या गायब हो जाती है और entry barrier कम हो जाता है
    • C++ भी similar functionality देता है, लेकिन Rust जितना safe नहीं है
  • ऐसे लोग hero हैं और शानदार काम कर रहे हैं

  • पूरी तरह self-documenting code को लागू करने की दिशा में हम एक कदम और करीब आ गए हैं