3 पॉइंट द्वारा GN⁺ 2023-07-22 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Rust सीखने के लिए बनाए गए side project rjvm एक सीखने के उद्देश्य वाला toy JVM है, लेकिन इसे असली .class और jar पढ़ने और Java bytecode चलाने तक लागू किया गया है
  • जिन features का support नहीं है वे हैं threads, reflection, annotations, I/O, JIT compiler, और string interning; लेकिन control flow, object creation, method calls, exceptions, और garbage collection शामिल हैं
  • उदाहरणों में OpenJDK 7 के असली rt.jar का उपयोग किया गया है, जिससे java.lang.StackTraceElement जैसी classes असली JDK से load होती हैं
  • code को तीन Rust crates—reader, vm, vm_cli—में बांटा गया है, और यह .class parsing से लेकर call stack, native methods, values और object modeling तक को cover करता है
  • आखिरी milestone stop-the-world semispace copying collector था; लक्ष्य पूरा होने के बाद project रोक दिया गया और ज्ञात bugs ठीक करने की भी कोई योजना नहीं है

सीखने के लिए Rust JVM rjvm

  • rjvm Rust सीखने के लिए बनाया गया toy Java Virtual Machine है
  • code GitHub पर public है
  • यह किसी गंभीर JVM implementation के बजाय learning purpose की implementation है, इसलिए ये features support नहीं करता
    • threads
    • reflection
    • annotations
    • I/O
    • JIT compiler
    • string interning
  • generics शुरू में unsupported list में थे, लेकिन असल में वे काम करते हैं

कितना implement हुआ है

  • rjvm सिर्फ parser नहीं है, बल्कि कई JVM behaviors को सीधे implement करता है
    • if, for जैसे control flow
    • primitive types और object creation
    • virtual methods और static methods calls
    • exception handling
    • garbage collection
    • jar files से class resolution
  • test code में Throwable, Exception, StackTraceElement इस्तेमाल करने वाले examples शामिल हैं
  • असली I/O नहीं होने के कारण System.out.println की जगह tempPrint नाम का native method इस्तेमाल किया जाता है
  • examples OpenJDK 7 के असली rt.jar का उपयोग करते हैं, और java.lang.StackTraceElement भी असली JDK से लिया जाता है

तीन Rust crates

  • project एक standard Rust project है और तीन crates से बना है
    • reader: .class files पढ़ने और उनकी contents को model करने वाले types शामिल करता है
    • vm: code execute कर सकने वाली virtual machine को library के रूप में देता है
    • vm_cli: java executable जैसा एक simple command-line launcher शामिल करता है
  • reader crate को अलग repository में अलग करके crates.io पर publish करने पर विचार किया जा रहा है

.class file parsing

  • Java code javac से compile होकर .class file बनता है, और आम तौर पर zip format वाली .jar file के रूप में distribute होता है
  • Java code चलाने के लिए पहले compiler द्वारा बनाए गए bytecode वाली .class file load करनी होती है
  • class file में execution और type resolution के लिए जरूरी जानकारी साथ में होती है
    • class name और source file name जैसे metadata
    • superclass name
    • implemented interfaces
    • fields और field types, annotations
    • method descriptors, throws clauses, annotations, generics information
    • bytecode, exception handler table, line number table
  • reader crate class file को parse करके class और उसकी contents model करने वाला Rust struct return करता है

method execution और call stack

  • vm crate की main API Vm::invoke है, जिसका उपयोग method execution के लिए होता है
  • execute हो रहे हर method के लिए CallStack के अंदर एक CallFrame होता है
  • main चलाते समय call stack शुरू में empty होता है, और execution के लिए नया frame बनाया जाता है
  • हर function call पर call stack में नया frame जोड़ा जाता है, और method execution खत्म होने पर वह frame हटाया जाता है
  • ज्यादातर methods Java bytecode में implement होते हैं, लेकिन rjvm native methods भी support करता है
    • native methods Java bytecode नहीं होते, बल्कि JVM खुद सीधे implement करता है
    • उदाहरण हैं System::currentTimeMillis, System::arraycopy, Throwable::fillInStackTrace
    • rjvm में इन्हें Rust functions के रूप में implement किया गया है
  • JVM एक stack-based virtual machine है, इसलिए bytecode instructions मुख्य रूप से value stack पर operate करते हैं
  • हर call frame से एक value stack और index से पहचाने जाने वाले local variables का set जुड़ा होता है

values और object modeling

  • Value local variables, stack elements, और object fields में store हो सकने वाली values को model करता है
  • Value Rust enum के रूप में implement है और इसमें ये states शामिल हैं
    • Uninitialized
    • Int(i32)
    • Long(i64)
    • Float(f32)
    • Double(f64)
    • Object(AbstractObject<'a>)
    • Null
  • Rust के enum जैसे sum types यह व्यक्त करने के लिए उपयुक्त हैं कि एक value कई types में से एक हो सकती है
  • object storage शुरू में class reference और field values रखने वाले Vec<Value> based simple Object struct से शुरू हुआ था
  • garbage collector implement होने के बाद यह pointers और casts का बहुत उपयोग करने वाली lower-level implementation में बदल गया
  • फिलहाल AbstractObject वास्तविक objects या arrays को model करता है, और header words के कुछ हिस्सों तथा field values वाले byte array pointer के रूप में है

bytecode instructions execution

  • method execution bytecode instructions को एक-एक करके process करने की प्रक्रिया है
  • JVM instructions 200 से अधिक हैं, और bytecode में 1 byte में encoded होते हैं
  • कई instructions के बाद arguments आते हैं और कुछ instructions variable length के होते हैं
  • rjvm Java bytecode instructions को Instruction type से model करता है
  • method execution के समय value stack और local variables array maintain किए जाते हैं, और अगली execute होने वाली instruction का address, यानी program counter, 0 पर initialize किया जाता है
  • आम तौर पर instruction execution के बाद program counter अगली instruction पर जाता है, लेकिन jump instructions उसे किसी दूसरी position पर ले जा सकते हैं
  • jump instructions if, for, while जैसे flow control statements implement करने में इस्तेमाल होते हैं
  • दूसरे methods call करने वाली instructions की अलग series होती है
    • कौन सा method call करना है, इसे तय करने के तरीकों में virtual lookup और static lookup आदि शामिल हैं
    • target method resolve करने के बाद call stack में नया frame जोड़ा जाता है और execution शुरू होता है
    • अगर return value void नहीं है, तो return value stack पर push होती है और execution resume होता है

exception handling

  • exceptions सामान्य control flow को तोड़ते हैं, method से early return करते हैं और call stack के साथ propagate हो सकते हैं, इसलिए implementation जटिल होती है
  • हर catch block method की exception table की एक entry से correspond करता है
  • exception table entry में handler खोजने के लिए जरूरी information होती है
    • लागू होने वाली program counter range
    • catch block की पहली instruction का address
    • उस block द्वारा catch की जाने वाली exception class का नाम
  • CallFrame::execute_instruction instruction execution result को व्यक्त करने के लिए Rust के Result का उपयोग करता है
  • instruction execution result चार states में बंटता है
    • successful और current method execution जारी रहता है
    • successful और return instruction होने के कारण current method return value के साथ समाप्त होता है
    • internal VM error के कारण execution fail हुआ
    • Java exception throw होने के कारण execution fail हुआ
  • method execution loop instruction parse करता है, program counter को अगले address पर ले जाता है, फिर instruction execute करता है
  • exception होने पर current instruction location के अनुसार exception handler खोजा जाता है
    • handler न हो तो exception caller तक propagate होती है
    • handler हो तो exception object फिर से stack पर push होता है और catch handler location से execution जारी रहता है
  • Rust का Result और pattern matching इस behavior को code structure में व्यक्त करने के लिए अच्छे से फिट बैठते हैं

garbage collection

  • rjvm का आखिरी बड़ा milestone garbage collector implementation था
  • चुना गया algorithm stop-the-world semispace copying collector है
  • threads नहीं होने के कारण stop-the-world तरीका स्वाभाविक रूप से लागू हो जाता है
  • implementation Cheney's algorithm का सरल variant है, और code gc.rs में है
  • यह तरीका उपलब्ध memory को दो semispace में बांटता है
    • एक active area होता है, जिसका उपयोग object allocation के लिए होता है
    • दूसरा unused area के रूप में रहता है
    • active area भर जाने पर live objects को दूसरे semispace में copy किया जाता है
    • सभी object references को नए copy की ओर point करने के लिए update किया जाता है
    • दोनों semispace की roles swap हो जाती हैं
  • इस प्रक्रिया को blue-green deployment जैसी approach से तुलना करके समझाया गया है
  • algorithm के pros और cons स्पष्ट हैं
    • maximum memory का आधा उपयोग नहीं किया जा सकता, इसलिए memory waste बड़ा है
    • pointer increment करने वाला तरीका होने से allocation बहुत fast है
    • objects को copy और compact करता है, इसलिए memory fragmentation handle करने की जरूरत नहीं होती
    • object compaction cache line usage बेहतर करके performance बढ़ा सकता है
  • वास्तविक Java VM आम तौर पर G1 या parallel GC जैसे अधिक sophisticated generational garbage collectors का उपयोग करते हैं

project का endpoint

  • rjvm बनाते हुए Rust और virtual machine implementation के बारे में बहुत कुछ सीखा गया, खासकर वास्तव में काम करने वाले garbage collector implementation से संतुष्टि मिली
  • garbage collector बहुत polished नहीं है, लेकिन असल में काम करता है
  • मूल लक्ष्य पूरा हो जाने के कारण project यहीं रोक दिया गया
  • ज्ञात bugs हैं, लेकिन उन्हें ठीक करने की कोई योजना नहीं है
  • JVM implementation में Rust इस्तेमाल करना आनंददायक रहा, और आगे के posts में rjvm implementation और JVM के काम करने के तरीके पर अधिक detail में चर्चा करने की योजना है

1 टिप्पणियां

 
GN⁺ 2023-07-22
Hacker News टिप्पणियाँ
  • garbage collection को implement करने में मुश्किल हिस्सा यह सुनिश्चित करना है कि सभी references ठीक से roots के रूप में पकड़े जाएँ, खासकर moving collector में यह और भी ज़्यादा कठिन होता है
    do_garbage_collection मेथड को unsafe के रूप में चिह्नित किया गया है[1], लेकिन इसे कॉल करने वाली side को इसे सुरक्षित रूप से कॉल करने के लिए क्या guarantee देनी होगी, इसकी कोई व्याख्या नहीं है
    जिज्ञासा है कि heap के सभी references roots के रूप में पकड़े जाते हैं, यह कैसे सुनिश्चित किया जाता है, और यह कोई मामूली समस्या नहीं है[2][3][4]
    साथ ही repository को clone करके cargo test चलाया, तो सभी tests should be able to add entries to the classpath: InvalidEntry(".../vm/rt.jar") त्रुटि के साथ fail हो गए: vm/tests/integration/real_code_tests.rs:15:10
    [1] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...
    [2] https://manishearth.github.io/blog/2021/04/05/a-tour-of-safe...
    [3] https://without.boats/blog/shifgrethor-iii/
    [4] https://coredumped.dev/2022/04/11/implementing-a-safe-garbag...

    • यह VM native call stack की बजाय अपना खुद का virtual call stack बनाए रखता है, इसलिए यह काफ़ी intuitive है
      इसलिए उस stack को traverse करके parameters और local variables खोजे जा सकते हैं और उन्हें roots की तरह इस्तेमाल किया जा सकता है
      इस तरीके की performance cost है, लेकिन garbage collection tracing बहुत अधिक सरल हो जाती है और coroutine या continuation जैसे concurrency/control-flow primitives को implement करना भी आसान हो जाता है
    • garbage collector मूल रूप से बहुत बारीकी वाली accounting है, इसलिए यह काफ़ी आसान होती है, लेकिन जैसे ही concurrent garbage collection शुरू करते हैं, यह नर्क जैसी कठिन हो जाती है
  • यह एक अच्छा project है, और बधाई
    लेकिन “समर्थन नहीं करता: generics” वाला हिस्सा थोड़ा अजीब लगता है
    जिज्ञासा है कि JVM में generics को किस अर्थ में support करना चाहिए
    bytecode स्तर पर type erasure की वजह से क्या इसे बस Object, यानी reference type, मानकर नहीं चलना चाहिए? या फिर class definition parser की बात हो रही है? ऐसा हो तब भी basic syntax के अलावा class file के valid होने की जाँच करने वाला logic दिखता नहीं है

    • generics के बारे में reddit पर भी यही बात आई थी, और यह सही है
      वास्तव में करने लायक काम बस इतना है कि class, method और field की generic जानकारी रखने वाला Signature attribute पढ़ लिया जाए (https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.ht...)
      अभी तुरंत test करके देखा, नीचे दिया गया code भी काम करता है :-)
      public class Generic { public static void main(String[] args) { List strings = new ArrayList(10); strings.add("hey"); strings.add("hackernews"); for (String s : strings) { tempPrint(s); } } private static native void tempPrint(String value); }
    • शायद यह checkcast operation की बात हो: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.ht...
      उदाहरण के लिए, final Main value = list.get(0); जैसा code लिखें तो यह generate होता है
      http://henrikeichenhardt.blogspot.com/2013/05/how-are-java-g...
    • मोटे तौर पर सही है। generics कभी-कभी reflection को प्रभावित करते हैं, लेकिन reflection भी supported नहीं है, और कुल मिलाकर compile समय में इसे सबसे नज़दीकी class या interface से बदल दिया जाता है
      दूसरी ओर string interning का न होना बहुत अजीब है। इसे implement करना भी काफ़ी trivial है, और इसके बिना इसे JVM कहना मुश्किल है
      strings का reference के आधार पर equal हो जाना महत्वपूर्ण है और यह JLS का हिस्सा है
      threads का न होना इस पूरी कोशिश को toy project के स्तर तक सीमित कर देता है
  • वाकई बहुत शानदार। 1992 में जब मैं Java पर काम करने वाली टीम में शामिल हुआ था, तब इसका नाम Oak था, और जिस ग्रुप में मैं था वह Java में पूरा operating system लिखने की दिशा देख रहा था
    विचार यह था कि “machine code”, यानी native methods में सिर्फ़ न्यूनतम ज़रूरी हिस्से ही छोड़े जाएँ, ताकि embedded operating system की attack surface कम की जा सके
    मूल रूप से Java का लक्ष्य TV या घरेलू electronic devices जैसी जगहों पर चलना था, और उस समय native methods Rust नहीं बल्कि C में लिखे जाते थे
    Rust में बना JVM इस पूरी प्रक्रिया में काफ़ी मज़बूत memory safety जोड़ता है

    • व्यक्तिगत रूप से मुझे लगता है कि Android ने किसी हद तक यह हासिल किया
      इसमें operating system logic का बड़ा हिस्सा Java या Kotlin में लिखा जाता है, लेकिन साथ ही native code में लिखी गई बहुत-सी system services भी मिली-जुली रहती हैं, और उन्हें मशहूर या बदनाम Binder IPC से आपस में जोड़ा जाता है
    • इस विचार को निश्चित ही कुछ बार आज़माया गया है [0, 1]
      [0] - https://en.wikipedia.org/wiki/Singularity_(operating_system)
      [1] - https://en.wikipedia.org/wiki/Midori_(operating_system)
    • कुछ समय तक end users के लिए नहीं था, लेकिन लगता है JavaOS था: https://en.wikipedia.org/wiki/JavaOS
    • sibling comments के अलावा SavageJE, microEJ, PTC और Aonix के bare metal Java runtimes, और SunSPOT का SquawkVM जैसी चीज़ें भी हैं
  • Go में लिखे गए JVM 17 implementation के रूप में https://jacobin.org/ भी देखने लायक है

    • JVM पर चलने वाले Scala में लिखा गया JVM https://github.com/lihaoyi/Metascala भी है
    • programming project के नाम के तौर पर यह काफ़ी दिलचस्प है
      Jacobins 1790 के दशक की French Revolution के दौरान एक क्रांतिकारी political club था, और https://jacobin.com पर मौजूद पत्रिका का नाम भी यही है
  • सोच रहा हूँ कि क्या इस signature के lifetime parameter की वजह से कहीं सीमा आ गई होगी
    fn execute_instruction(&mut self, vm: &mut Vm<'a>, call_stack: &mut CallStack<'a>, instruction: Instruction) -> Result, MethodCallFailed<'a>>
    अगर Result के Err variant में lifetime जोड़ दिया जाए और वह lifetime invariant हो, जैसा यहाँ vm और call_stack की वजह से लगता है, तो आम तौर पर ? operator या early return का इस्तेमाल नहीं किया जा सकता[1]
    तब error handling ज़्यादा verbose और पढ़ने में कठिन हो जाती है; जानना चाहूँगा कि क्या व्यवहार में भी ऐसा ही अनुभव रहा
    [1] https://users.rust-lang.org/t/nll-and-early-return-not-allow...

    • सुधार करूँ तो, यहाँ immutable lifetime 'a का इस्तेमाल vm या call_stack के mutable references के लिए नहीं हो रहा, इसलिए शायद यह वही समस्या नहीं है
      समस्या invariance से ज़्यादा इस बात से जुड़ी लगती है कि Rust mutable references की lifetime कैसे infer करता है, और यह code उससे बच रहा है
      ऐसे में समझ नहीं आता कि VM और CallStack पर लगी 'a का मतलब क्या है
      अगर इसे बिना किसी सीमा वाली मनमानी lifetime, यहाँ तक कि 'static से भी बनाया जा सकता है[1][2][3], तो यह वास्तव में कोई constraint नहीं लगाती
      जानना चाहूँगा कि यह lifetime parameter यहाँ क्या कर रहा है, और इसे हटाया क्यों नहीं गया
      [1] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...
      [2] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...
      [3] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...
  • यह एक शानदार learning project है, और अच्छा लगा सुनकर कि लेखक इसे मज़े से कर रहा है
    VM को scratch से implement करना सच में बहुत मज़ेदार होता है, और मैंने भी पहले ऐसा काम करते हुए बहुत कुछ सीखा है
    अगर आप इसमें garbage collection जोड़कर देखना चाहते हैं, तो MMTk पर नज़र डाल सकते हैं (https://www.mmtk.io/)
    इसमें कई high-quality collection algorithms हैं जो अलग-अलग VM में plug करने के लिए डिज़ाइन किए गए हैं, और यह Rust में लिखा गया है

    • जानकारी के लिए, MMTK सिर्फ़ x86 के लिए है
      मैं इसे एक toy project में इस्तेमाल करना चाहता था, लेकिन Mac होने की वजह से छोड़ना पड़ा
  • बहुत बढ़िया बनाया है
    VM बनाना हमेशा मज़ेदार होता है, और Rust के type system के साथ मिलकर यह एक दिलचस्प learning experience रहा होगा
    अगर आप नौकरी ढूँढ़ रहे हैं, तो Twitter, Mastodon, या company email पर संपर्क कर सकते हैं। यहाँ user ID देखकर आपको ढूँढ़ा जा सकेगा

  • ऐसे शानदार प्रोजेक्ट्स को देखकर थोड़ा दबाव-सा महसूस होता है
    अच्छा होता अगर मूल लेखक यह बताते कि Rust कैसे शुरू करें और उसकी बुनियाद किस स्तर तक सीखनी चाहिए ताकि ऐसी चीज़ आज़माने की हिम्मत हो सके

    • मुझे भी बिल्कुल ऐसा ही लगता है
      बहुत ज़्यादा भटकना नहीं चाहता, लेकिन निजी तौर पर मैं आजकल इस भावना से काफ़ी जूझ रहा हूँ
      मैं लगभग 10 साल से प्रोफेशनल software developer के तौर पर काम कर रहा हूँ, और अपनी मौजूदा भूमिका तथा सचमुच प्रोडक्ट ship करने की क्षमता देखकर जानता हूँ कि मैं सक्षम हूँ और कोई नकली developer नहीं हूँ
      लेकिन आजकल developer blogs पढ़कर मैं दबाव में आ जाता हूँ, जैसे मुझे पर्याप्त जानकारी नहीं है और मैं “असली” developer नहीं हूँ
      लगता है कि मैंने अपने दिमाग में एक आदर्श developer की छवि बना रखी है, और उसी काल्पनिक मानक से अपनी तुलना करने पर यह भावना पैदा होती है
      जिन लोगों के पास गहरा ज्ञान है और जो साफ़ व संक्षेप में बात रख पाते हैं, उनका सम्मान करता हूँ, लेकिन फिर सोचता हूँ कि मैं वैसा क्यों नहीं हूँ
      काम खत्म होने के बाद परिवार की देखभाल कर लूँ तो मेरे पास कुछ और करने की ऊर्जा लगभग नहीं बचती, और यह भी जानता हूँ कि programming ही सब कुछ नहीं है, फिर भी और सीखने तथा बढ़ने की इच्छा रहती है
      पता है कि यह न तो स्वस्थ है न ही तर्कसंगत, लेकिन इन दिनों इस भावना को झटकना मुश्किल हो रहा है
    • सच कहूँ तो HN खोलते ही लगभग आधी बार impostor syndrome महसूस होता है
      पहले VM का थोड़ा अनुभव था, और कुछ साल पहले ब्लॉग पर छोटी-सी एक शृंखला भी लिखी थी
      पिछली नौकरी में ग्राहकों की एक बहुत अजीब समस्या सुलझाने के लिए JVM bytecode के साथ थोड़ा छेड़छाड़ भी की थी
      और कुछ साल पहले शानदार https://craftinginterpreters.com/ पढ़ी थी, वहीं से कुछ ideas मिले थे
      लेकिन यह प्रोजेक्ट निश्चित ही बड़ा और जटिल था
      इसमें बहुत समय लगा, और मेरी कई side projects की तरह इसे भी कुछ बार छोड़ दिया गया, लेकिन आखिरकार पूरा कर लेने की खुशी है :-)
    • मैं Rust expert नहीं हूँ और न ही मूल लेखक हूँ, लेकिन एक दूसरी तकनीक sockets का उदाहरण दे सकता हूँ
      हाल ही में मैंने sockets को गहराई से पढ़ा, जबकि 2 हफ्ते पहले तक manual pages, docs, blog posts वगैरह को सरसरी तौर पर पढ़कर मिली बस ऊपरी समझ ही थी
      networking की बुनियाद समझनी थी, इसलिए तय किया कि जितना हो सके उतना पढ़ूँ, और एक हफ्ते बाद मैं Python और C में socket code लिख सकने लायक सीख गया
      Python मुझे काफ़ी अच्छी तरह आती है, इसलिए गहराई में जाने के बाद sockets library को देखना कहीं बेहतर समझ आया
      अगर आप तकनीक A को भाषा X में बेहतर करना चाहते हैं, तो मैं सलाह दूँगा कि तकनीक A के बारे में जितना हो सके पढ़ें या देखें, और भाषा Y में कुछ बनाकर देखें
      उसके बाद जब भाषा X में लौटेंगे, तो तकनीक A के आसपास के concepts से आप पहले ही काफ़ी परिचित हो चुके होंगे
    • इसे छोटे-छोटे हिस्सों में बाँटिए
      एक साधारण language VM में memory के अंदर object representation, bytecode interpreter, एक simple garbage collector, और loader होगा
      bytecode interpreter को एक stack, उस stack पर functions को दर्शाने के तरीके, और हर bytecode को interpret करके program counter आगे बढ़ाने वाले loop के रूप में देखा जा सकता है
    • फुर्सत के समय आप कितनी coding करते हैं, यह महत्वपूर्ण है। औसतन हफ्ते में कितने घंटे
      अगर 0 घंटे हैं, तो यह निश्चित ही कोई दोष की बात नहीं है, क्योंकि ध्यान देने के लिए और भी बहुत चीज़ें होती हैं, लेकिन अगर कोई व्यक्ति कई सालों तक औसतन हर हफ्ते 10~20 घंटे side projects पर लगाता रहा है, तो उसका प्रभावशाली नतीजे देना हैरानी की बात नहीं है
  • इसी तरह के एक प्रोजेक्ट का बेशर्मी से प्रचार करूँ तो: https://github.com/tenaf0/rust-jvm3

  • मैं 386(486) AT clone के लिए एक मुफ़्त operating system बना रहा हूँ। बस एक hobby है, gnu जितना बड़ा और प्रोफेशनल नहीं :-)

    • Rust में demo kernel लिखने के लिए एक no-std tutorial है: https://os.phil-opp.com
      osdev.org, sandpile.org, RBIL, freevga भी देखने लायक हैं
      सबसे बड़ा सिरदर्द hardware support है
      भरोसेमंद port I/O या undocumented hardware tricks जैसी recipes वाली अच्छी पुरानी कागज़ी किताबें भी बहुत हैं
      Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4
      Microsoft MS-DOS Programmer's Reference, जिसमें real-mode BIOS calls भी शामिल हैं
      PC Interrupts
      Undocumented PC
      PC Intern
      Programmer's Guide To The EGA, VGA, And Super VGA Cards
      Graphics Programming Black Book Special Edition
      साथ ही single kernel, microkernel, और hybrid युग के बाद operating system development में हुई प्रगति पर प्रयोग करना भी सार्थक है
      seL4 जैसी capability-based संरचनाओं में capability और बेहतरीन IPC सहित performance और security के लिहाज़ से कई मूलभूत फायदे हैं
      POSIX compatibility layer भी महत्वपूर्ण है। threads या process की अवधारणा न रखने वाले embedded operating systems भी POSIX को implement कर सकते हैं
      अगर Intel VT-[xd] हो तो hypervisor को जोड़ना बहुत आसान हो जाता है, और न हो तो emulation पर वापस जाया जा सकता है। translation-based emulation की performance बहुत अच्छी होती है
      आपको interrupt handlers को generalize और तेज़ बनाने, race conditions से बचने, और lock-free patterns इस्तेमाल करने में दक्ष होना होगा
      x87 और MMX समेत unsupported instructions को rewrite या trap करना भी ज़रूरी है
      pure microkernel के विफल होने का कारण यह था कि कई resources को transactional तरीके से क्रमबद्ध और प्रबंधित करने की जटिलता बहुत बढ़ गई थी
      microkernel architecture में सैद्धांतिक रूप से security और operations के बड़े फायदे हैं, लेकिन अपने शुद्ध रूप में यह व्यापक रूप से स्थापित नहीं हो पाया