F-35 में इस्तेमाल किया गया C++ मानक - लड़ाकू विमान C++ की 90% सुविधाओं पर प्रतिबंध क्यों लगाते हैं
(youtube.com)- यह वीडियो समझाता है कि Mach 1 की गति पर एक लाइन का bug भी घातक नतीजे दे सकता है, इसलिए लड़ाकू विमान और रॉकेट software में C++ की ज़्यादातर सुविधाएँ हटाकर केवल predictable code ही क्यों छोड़ा जाता है
- F-4 के mechanical bombing computer, गोपनीय F-14 microprocessor, और Jovial·CMS-2·Ada तक चली सैन्य language war तथा code explosion का इतिहास समेटते हुए बताया गया है कि कैसे एक single safety language और strict standard की ज़रूरत पैदा हुई
- F-35 के development के दौरान Lockheed ने Ada की जगह C++ के उपयोग की अनुमति पाने के लिए जो JSF C++ standard बनाया, वह exceptions, recursion, और dynamic memory allocation पर प्रतिबंध लगाता है, और उनकी जगह return code, iterative loop, तथा pre-allocated memory जैसे विकल्पों का वास्तविक code के साथ प्रदर्शन करता है
- शुरुआती F-35 mission computer में PowerPC family architecture के इस्तेमाल का भी उल्लेख है, और X-Plane 12 तथा स्वयं बनाए गए MFD को जोड़कर यह तुलना की गई है कि JSF नियमों का उल्लंघन करने वाला code और उनका पालन करने वाला code वास्तविक उड़ान के दौरान कैसे अलग व्यवहार करता है
- बाद में JSF standard से NASA F-Prime·MISRA·AutoSAR जैसे safety standards विकसित हुए, और निष्कर्ष यह दिया गया है कि अब इस विरासत के ऊपर C++ Core Guidelines और modern C++ का उपयोग करना अधिक उपयुक्त दिशा है
वक्ता का परिचय
- एक developer जिन्होंने aerospace systems के लिए C++ code लिखा है और air force के लिए demo भी किए हैं
- उन्होंने high-safety-requirement systems में C++ के वास्तविक उपयोग के अनुभव के आधार पर यह व्याख्या प्रस्तुत की
- X-Plane 12, web API, Python UI, और C++ backend से बना स्वयं निर्मित MFD (multifunction display) इस demo environment में उपयोग किया गया
flight software और failure-अस्वीकार्य वातावरण
- सामान्य applications में crash होने पर बस restart करना पड़ता है, लेकिन Mach 1 लड़ाकू विमान और रॉकेट में एक ही failure सीधे disaster बन सकता है
- “Mach 1 पर garbage collector का इंतज़ार करने का समय नहीं होता” इस वाक्य के जरिए real-time requirement पर ज़ोर दिया गया
- ऐसी स्थिति में जहाँ code की एक गलत लाइन से घातक परिणाम हो सकते हों, वहाँ language feature का चुनाव ही safety mechanism बन जाना चाहिए
- 1996 की Ariane 5 explosion accident को प्रमुख उदाहरण के रूप में प्रस्तुत किया गया
- horizontal bias के 64-bit floating-point value को 16-bit integer में बदलते समय exception उत्पन्न हुआ, और उसे handle नहीं किया जा सका
- language ने specification के अनुसार error उठाया, लेकिन system उस exception को संभाल नहीं सका, और नतीजतन 500 million dollar का rocket तुरंत नष्ट हो गया
- इसी घटना को reference point मानते हुए F-35 design team ने वही गलती दोहराने से बचने के लिए language features को ही काट देने वाला approach अपनाया
सैन्य software का इतिहास और language war
- शुरुआती लड़ाकू विमान F-4 Phantom के दौर में वस्तुतः software था ही नहीं
- bombing computer, gears और cams से बनी एक precision mechanical device के अधिक करीब था, और “code” वास्तव में metal cam का आकार ही था
- गोपनीय naval air-superiority project VFX(F-14 Tomcat) में स्थिति बदल गई
- बाद में यह बात सामने आई कि textbooks में “पहला microprocessor” कहे जाने वाले Intel 4004 से पहले ही Garrett AiResearch ने F-14 के लिए microprocessor डिजाइन कर लिया था
- F-14 के variable sweep wing को optimally control करने के लिए high-performance microprocessor की ज़रूरत थी, और इसमें लगभग 2500 lines का microcode डालकर polynomial calculation कराई जाती थी
- इसके बाद अलग-अलग सैन्य शाखाओं ने अलग भाषाएँ अपनाईं और language fragmentation शुरू हो गई
- Air Force ने ALGOL family की Jovial(Jules Own Version of the International Algorithmic Language) का उपयोग किया
- Navy ने Air Force की language न अपनाने के लिए F-18 में CMS-2 चुना
- अलग भाषाओं और hardware architectures के कारण code reuse और verification लगभग असंभव हो गए
- इसी दौरान प्रति विमान software का आकार exponentially बढ़ता गया
- उदाहरण के तौर पर F-16A में लगभग 125,000 lines, B-1 में लगभग 1 million lines, और आधुनिक F-35 में लगभग 9 million lines बताए गए
- Department of Defense की एक जाँच में पता चला कि 450 से अधिक programming languages उपयोग में थीं, और उनमें से बहुत कम के पास सही standard था
Ada को अनिवार्य करना और उसकी सीमाएँ
- इस बिखराव को दूर करने के लिए Department of Defense ने एक single high-level language Ada बनाई और उसके उपयोग को कड़ाई से अनिवार्य किया
- किसी नए project में Ada का उपयोग न करने के लिए यह साबित करना पड़ता था कि Ada से वह संभव क्यों नहीं है, नहीं तो contract हासिल करना संभव नहीं था
- Ada को safety और reliability critical क्षेत्रों के लिए बहुत उपयुक्त language के रूप में पेश किया गया
- aerospace जैसे safety-critical systems में memory और type safety सुनिश्चित करने वाले design पर ज़ोर दिया गया
- लेकिन 1990s में वास्तविकता से इसका अंतर दिखने लगा
- दूसरी ओर internet, Windows 95, और C++ आधारित commercial games मुख्यधारा बन रहे थे
- छात्र और developers महंगे Ada compiler की बजाय स्वाभाविक रूप से free GCC और C++ की ओर बढ़े
- Ada compiler की कीमत हजारों dollar तक होती थी, इसलिए व्यक्तिगत स्तर पर उसे अपनाना कठिन था, और परिणामस्वरूप Ada विशेषज्ञों का talent pool भी सिकुड़ने लगा
F-35 और JSF C++ standard का जन्म
- F-35 (Joint Strike Fighter) को शुरू से ही software-heavy platform के रूप में डिजाइन किया गया
- sensor fusion जैसी complex computation विमान संचालन का केंद्रीय हिस्सा बन गई
- Lockheed Martin ने इन आवश्यकताओं के लिए Department of Defense से C++ उपयोग की अनुमति माँगी
- यह मूल Ada-mandate policy को व्यावहारिक रूप से “ढीला करने” जैसा अनुरोध था, और इसके लिए C++ के जोखिमों को नियंत्रित करने की विधि दिखानी ज़रूरी थी
- इस प्रक्रिया में C++ के निर्माता Bjarne Stroustrup ने भी adviser के रूप में भाग लिया और JSF C++ rules के design में योगदान दिया, ऐसा बताया गया
- उन्होंने स्वयं कहा कि उन्होंने JSF rules तैयार करने में सीधे मदद की थी, इसलिए इस standard पर उनका “bias हो सकता है”
- मूल विचार “remove before flight” टैग जैसा था
- जैसे उड़ान से पहले हटाए जाने वाले टैग होते हैं, वैसे ही C++ की खतरनाक सुविधाओं को language स्तर पर हटाकर केवल predictable subset का उपयोग किया गया
- इससे Ada जैसी safety बनाए रखते हुए developers को C++ की कुछ expressiveness इस्तेमाल करने की अनुमति मिली
वास्तविक hardware और GameCube तुलना
- शुरुआती F-35 blocks में Motorola G4 PowerPC processor आधारित mission computer उपयोग किया गया था
- यह जानकारी 2003 के Aviation Today article आदि में सार्वजनिक हुई थी
- GameCube में भी PowerPC family processor इस्तेमाल हुआ था, इसलिए instruction set level पर यह मिलते-जुलते generation का hardware माना जा सकता है
- अधिक सटीक generation match के लिए कोई और console बेहतर हो सकता है, लेकिन सिद्धांत समझाने के लिए GameCube की तुलना पर्याप्त है
JSF C++ demo environment: X-Plane 12 + MFD
- X-Plane 12 के आधार पर F-35B addon (AOA Simulations) का उपयोग करके flight simulator environment तैयार किया गया
- X-Plane के नए web API से real-time flight data subscribe करके उसे MFD पर दिखाने वाली संरचना बनाई गई
- frontend Python में है, और backend C++ plugin के रूप में लिखा गया है, जिसमें JSF rules का पालन करने और उनका उल्लंघन करने वाले code की तुलना दिखाई गई
- altitude, speed, wind, flight envelope, navigation data जैसी कई जानकारियाँ C++ calculation results के रूप में प्रदर्शित होती हैं
- उड़ान के दौरान जानबूझकर exception throw करने वाला non-standard C++ code चलाकर दिखाया गया कि MFD crash हो जाता है और उड़ान में समस्या आती है, फिर JSF rules लागू करके इसे चरणबद्ध तरीके से ठीक किया जाता है
JSF की तीन मुख्य पाबंदियाँ: exceptions, recursion, dynamic memory
- JSF C++ standard में ज़ोर दिए गए तीन मुख्य प्रतिबंध हैं: exceptions, recursion, और dynamic memory allocation
- इसके अलावा function की Cyclomatic Complexity की upper limit भी तय की गई है
1) exceptions पर प्रतिबंध – AV Rule 208
- JSF AV Rule 208: “exceptions का उपयोग नहीं किया जाएगा(exceptions shall not be used)”
- try, catch, throw जैसे exception-related keywords पूरी तरह प्रतिबंधित हैं
- मुख्य कारण है control flow की non-determinism
- Ariane 5 की तरह, exception होने पर अगर handling छूट जाए या timing बिगड़ जाए, तो पूरा system unpredictably fail हो सकता है
- Bjarne आधुनिक C++ exception handling के समर्थक हैं, लेकिन उन्होंने समझाया कि JSF के design के समय tool maturity और real-time guarantee की समस्याओं के कारण exceptions को support करना व्यावहारिक नहीं था
“JSF++ hard real-time और safety-critical application (flight control) के लिए है; यदि computation बहुत देर तक चले तो लोग मर सकते हैं, और exceptions के साथ response time guarantee नहीं की जा सकती”
- JSF में exceptions की जगह return code का उपयोग किया जाता है
- density altitude calculation के उदाहरण में, हर error condition के लिए अलग return code सेट किया जाता है और caller उसे interpret करके handle करता है
- इससे calculation failure या timeout होने पर भी पूरा program crash नहीं होता, और calling side सुरक्षित तरीके से “error state” व्यक्त कर सकती है
2) recursion पर प्रतिबंध – AV Rule 119
- AV Rule 119 function को प्रत्यक्ष या अप्रत्यक्ष रूप से स्वयं को call करने, यानी recursion, से रोकता है
- हर recursive call के साथ नया stack frame जुड़ता है, और maximum depth का upper bound जानना कठिन होता है, इसलिए stack overflow का जोखिम बढ़ता है
- उदाहरण के लिए flight planning में alternate airport calculation के लिए उपयोग होने वाले binomial coefficient का ज़िक्र किया गया
- non-standard version में
C(n, k) = C(n-1, k-1) + C(n-1, k)रूप वाली recursive implementation इस्तेमाल की गई - इससे input के अनुसार call depth बदलती है, और memory upper bound का अनुमान कठिन हो जाता है
- non-standard version में
- JSF-compliant version में उसी calculation को loop आधारित iterative implementation में बदला गया
- code लंबा और कम elegant है, लेकिन स्वयं को call नहीं करता, इसलिए बिना recursion वही result देता है
- इससे function call depth और memory usage की upper bound को statically infer करना आसान हो जाता है
3) dynamic memory allocation पर प्रतिबंध – AV Rule 206
- AV Rule 206: initialization के बाद memory allocate या free नहीं की जाएगी
- runtime में
new,delete, या smart pointer के अंदर होने वाला internalnewजैसे heap allocation प्रतिबंधित हैं
- runtime में
- इसके पीछे दो प्रमुख कारण हैं
- heap allocation में समय की non-determinism होती है, यानी इसमें कितना समय लगेगा यह निश्चित नहीं
- heap fragmentation होने पर कुल memory बची होने के बावजूद बड़ा contiguous block न मिलने से allocation fail हो सकता है
- उदाहरण के तौर पर gust calculation के लिए IAS (indicated airspeed) history buffer को
std::unique_ptr+ dynamic array से बनाने वाला non-standard code दिखाया गया- यह runtime में नई array allocate करता है और JSF rule तोड़ता है
- JSF-compliant version में constant के रूप में निर्धारित maximum size वाली fixed-size array का उपयोग किया गया
MAX_IAS_HISTORYजैसे constant define करके initialization पर केवल एक बार memory reserve की जाती है, और बाद में सिर्फ index घुमाए जाते हैं- इससे runtime में कोई अतिरिक्त allocation नहीं होता और time तथा memory दोनों के मामले में predictability मिलती है
4) Cyclomatic Complexity की सीमा – AV Rule 3
- AV Rule 3 के अनुसार किसी function की Cyclomatic Complexity 20 से अधिक नहीं होनी चाहिए
- function declaration स्वयं 1 point होता है, और if·while·for·switch·logical AND/OR आदि हर एक complexity में 1 जोड़ते हैं
- binomial coefficient की iterative implementation के उदाहरण से दिखाया गया कि हर if, logical operation, और for loop complexity points कैसे बढ़ाते हैं
- complexity बढ़ने पर testing, verification, और analysis कठिन हो जाते हैं, इसलिए standard का लक्ष्य इसे एक निश्चित सीमा के नीचे रखना है
JSF की विरासत: NASA F-Prime, MISRA, AutoSAR
- JSF C++ standard के विचार बाद में अन्य safety-critical क्षेत्रों में फैल गए
- NASA का flight software framework F-Prime 2017 में public हुआ, और इसमें भी dynamic memory allocation पर रोक, exceptions पर रोक, और recursion पर रोक जैसे नियम मिलते हैं
- automotive industry में भी इसी तरह का रुझान जारी रहा
- MISRA C++ और AutoSAR(Automotive Open System Architecture) जैसे standards सामने आए, जिन्होंने automotive software safety rules परिभाषित किए
- यह भी कहा गया कि AutoSAR C++14 guide ने JSF का स्पष्ट रूप से संदर्भ लिया, जो दिखाता है कि JSF का प्रभाव automotive software तक पहुँचा
- आधुनिक कारें वस्तुतः “पहियों पर चलने वाले computer” जैसी हो गई हैं, इसलिए ऐसे language subset और coding rules सुरक्षा की बुनियादी नींव बन जाते हैं
निष्कर्ष: आज C++ इस्तेमाल करें तो क्या अपनाएँ
- JSF C++ standard को उस समय के संदर्भ में एक जटिल language को predictable subset में सीमित करके fighter aircraft flight-control स्तर की safety हासिल करने वाली engineering achievement के रूप में प्रस्तुत किया गया
- साथ ही Bjarne Stroustrup आज के developers को C++ Core Guidelines और modern C++ अपनाने की सलाह देते हैं
- क्योंकि पिछले कई दशकों में C++ language और toolchain दोनों विकसित हुए हैं, और exceptions तथा smart pointers जैसी सुविधाओं को सुरक्षित रूप से उपयोग करने के लिए बेहतर environment उपलब्ध हैं
- फिर भी JSF आज भी language को जोड़कर नहीं, बल्कि “हटाकर” नियंत्रित करने वाली सोच का एक महत्वपूर्ण उदाहरण बना हुआ है
- समापन संदेश यही है कि क्या जोड़ना है, इससे अधिक महत्वपूर्ण यह है कि remove before flight सूची में क्या रखना है — और यही safety-critical system design का मूल है
अभी कोई टिप्पणी नहीं है.