~/writing/from-keypress-to-screen $
    08/08
    intro ⏻
    LEVEL 3 — THE BRIDGESপর্ব ০৮/০৮~১৫ মিনিট

    Keyboard-এর 'A' থেকে Screen-এর 'A'

    এক keystroke-এর ভেতরে যা কিছু ঘটে — সিরিজের সব layer একসাথে

    Keyboard-এ 'A' চাপলেন। এক মুহূর্ত পর screen-এ 'A' ফুটে উঠল।

    আপনার কাছে মনে হলো instant। কোনো delay টের পাননি, কোনো অপেক্ষাও করতে হয়নি। আঙুল নামল আর অক্ষরটা চলে এল।

    কিন্তু বাস্তবে সেটা instant ছিল না। মাঝখানে প্রায় ২০ থেকে ৩০ millisecond সময় লেগেছে, আর সেই সময়ের ভেতরে আপনার laptop-এ কয়েকটা সম্পূর্ণ আলাদা system একের পর এক কাজ করে গেছে। প্রতিটার দায়িত্ব ভিন্ন, প্রতিটা ভিন্ন সময়ে ভিন্ন মানুষের হাতে design করা, কিন্তু সবাই মিলে একসাথে কাজ করেছে।

    এই সিরিজে এতদিন আমরা এই system-গুলোকে আলাদা আলাদা করে দেখেছি। আজ দেখব সবাই একসাথে কীভাবে কাজ করে। একটা মাত্র keystroke-কে follow করে পুরো পথটা হেঁটে যাব — আঙুলের চাপ থেকে শুরু করে চোখে আলো পড়া পর্যন্ত।

    01

    প্রথম চমক: keyboard-এরও নিজস্ব একটা CPU আছে

    'A' চাপলে সরাসরি laptop-এর CPU-তে কিছু যায় না। তার আগে সেই signal-কে থামতে হয় keyboard-এর নিজের ভেতরে বসে থাকা একটা ছোট্ট computer-এ।

    শুনতে অদ্ভুত লাগতে পারে। Keyboard তো একটা input device মাত্র, তার আবার নিজের computer কেন থাকবে? কিন্তু আছে। এমনকি সবচেয়ে সস্তা keyboard-এও একটা tiny chip বসানো থাকে, যার ভেতরে থাকে একটা mini CPU, সামান্য memory, আর কিছু আগে থেকে লেখা instruction।

    এই chip-এর কাজটা খুব নির্দিষ্ট। সে প্রতি কয়েক millisecond অন্তর পুরো keyboard scan করে যায়। প্রতিটা key-এর জন্য আলাদা তার নেই — সেটা করতে গেলে ১০৪টা তার লাগত। বদলে key-গুলো একটা grid-এ সাজানো, সারি আর কলাম মিলে। Chip একটা করে সারিতে current পাঠায় আর সব কলাম একসাথে পড়ে। কোন সারি আর কোন কলাম — এই দুইয়ের সংযোগ থেকেই বোঝা যায় কোন key চাপা হয়েছে।

    যতক্ষণ কোনো key চাপা না হচ্ছে, কোনো কলামেই কিছু ধরা পড়ে না। কিন্তু যেই কোনো key চাপা হয়, সেই key-এর নিচের switch-এর দুইটা metal contact একসাথে লেগে যায়, সেই সারি আর সেই কলামের মাঝে circuit complete হয়ে যায়, আর chip ঐ কলামে voltage দেখতে পায়।

    Chip সেই পরিবর্তনটা ধরে ফেলে। তারপর নিজের ভেতরের একটা lookup table থেকে খুঁজে বের করে — এই সারি আর এই কলামের সংযোগে কোন key বসে আছে? 'A' key-এর জন্য সে একটা নির্দিষ্ট byte তৈরি করে, ধরা যাক 0x04। সেই byte-টাই USB cable দিয়ে laptop-এ পাঠিয়ে দেয়। এই byte-টার নাম scancode

    মানে laptop-এর main CPU কিছু জানার আগেই keyboard-এর ভেতরে একটা পুরো computing cycle শেষ হয়ে গেছে। Voltage পড়া হয়েছে, সিদ্ধান্ত নেওয়া হয়েছে, ডেটা তৈরি হয়েছে।

    আর সেই ভেতরের CPU-ও কিন্তু আমাদের দেখা সেই একই নিয়মে চলে — fetch করে, decode করে, execute করে। শুধু scale-টা অনেক ছোট। নিচের যন্ত্রে একটা key চেপে scan cycle-টা দেখুন:

    যন্ত্র ০১ — THE SCAN
    সারি ১/৪
    KEY MATRIX · সারি × কলাম
    R1
    R2
    R3
    R4
    C1
    C2
    C3
    C4
    ৪×৪ = ১৬টা key, মাত্র ৮টা pin-এ
    CHIP
    কিছু নেই…
    LOOKUP
    USB OUT
    chip সারি ১/৪-এ current দিচ্ছে, সব কলাম একসাথে পড়ছে… সারি ৩-এ পৌঁছালে ধরা পড়বে।
    প্রতিটা key-এর আলাদা তার নেই। Chip একটা করে সারিতে current পাঠায় আর সব কলাম একসাথে পড়ে — চাপা key যেই সারিতে, সেই সারির পালা এলেই তার কলামে voltage ধরা পড়ে। সারি আর কলামের সংযোগ থেকেই scancode তৈরি হয়।
    02

    Interrupt: CPU-কে থামানোর একমাত্র উপায়

    USB cable দিয়ে signal ঢুকল laptop-এ। Motherboard-এ বসে থাকা USB controller সেটা receive করল। এই controller একটা আলাদা chip, CPU-র বাইরে, যার একমাত্র কাজ USB device-এর সাথে কথা বলা।

    Controller-এর কাছে এখন data আছে, কিন্তু CPU সেটা জানে না। CPU এই মুহূর্তে অন্য কাজে ব্যস্ত — হয়তো Chrome-এর কোনো JavaScript চালাচ্ছে, বা YouTube video decode করছে। তাকে জানাতে হবে যে নতুন কিছু এসেছে।

    জানানোর একমাত্র উপায় হলো interrupt। Controller একটা নির্দিষ্ট pin-এর voltage বদলে দেয়, আর সেই wire সরাসরি CPU-তে গিয়ে ঠেকে।

    Interrupt পাওয়ার সাথে সাথে CPU যা করছিল তা থামিয়ে দেয়। কিন্তু শুধু থামলেই তো হবে না। CPU-র register-এ এই মুহূর্তে যা কিছু আছে — কোন instruction চালাচ্ছিল, কোন value হাতে ধরা ছিল, সব সাময়িক হিসাব — সেসব হারিয়ে গেলে বিপদ। Interrupt handle করা শেষে যখন সে আগের কাজে ফিরবে, তখন সে জানতেই পারবে না কোথায় থেমেছিল।

    তাই থামার আগে CPU সব state একটা নির্দিষ্ট memory area-তে save করে রাখে। এই কাজটা আমরা Article 6-এ দেখেছিলাম — context switch-এর সময় যেভাবে process-এর "মাথার অবস্থা" PCB-তে জমা রাখা হয়, এখানেও প্রায় একই ব্যাপার, শুধু ছোট আকারে।

    State save হয়ে গেলে CPU switch করে kernel mode-এ। এতক্ষণ সে user mode-এ ছিল, Chrome-এর code চালাচ্ছিল। এখন OS-এর code চালাতে হবে, আর সেই code-এর hardware access দরকার। তাই privilege level বদলাতেই হবে।

    03

    OS-এর ভেতরে: এই event কার জন্য?

    Interrupt handler চলতে শুরু করে। এই handler আসলে কী জিনিস? এটা Linux বা Windows kernel-এর একটা অংশ, যেটা বছর কয়েক আগে কোনো developer C-তে লিখেছিলেন। তারপর সেটা compile হয়ে machine code হয়েছে, আর আপনার laptop boot হওয়ার সময় সেই machine code memory-তে load হয়েছে। এই মুহূর্তে সেই বহু পুরনো compiled code-ই চলছে।

    Handler প্রথমে USB controller থেকে scancode read করে নেয়। তারপর OS-এর keyboard driver সেই scancode দেখে বুঝে যায় — 'A' চাপা হয়েছে।

    এখন প্রশ্ন হলো, এই তথ্যটা কার কাছে যাবে? আপনার laptop-এ তো এই মুহূর্তে ৫০টা program চলছে। সবাইকে জানানোর তো মানে হয় না।

    OS জানে এই মুহূর্তে কোন window active আছে — যেটাকে বলে focused window। ধরা যাক সেটা VS Code। OS সেই window-এর সাথে যুক্ত process-টা খুঁজে বের করে, আর সেই process-এর জন্য যে event queue আছে, সেখানে event-টা রেখে দেয়।

    কিন্তু এখানে একটা সমস্যা আছে। VS Code-এর process এই মুহূর্তে CPU-তে চলছে না। CPU-তে ছিল Chrome। তাহলে VS Code জানবে কীভাবে যে তার জন্য একটা event এসেছে?

    এখানেই scheduler-এর ভূমিকা। Article 6-এ দেখেছিলাম, প্রতিটা context switch-এ scheduler ঠিক করে দেয় পরের বার CPU কে পাবে। এখন তার সামনে একটা choice — Chrome-কে আবার resume করবে, নাকি VS Code-কে জাগিয়ে তুলবে?

    Modern OS-এ interactive application-কে সাধারণত দ্রুত response দেওয়া হয়। কারণ user সরাসরি তাদের সাথে কাজ করছে, একটু দেরি হলেই "lag" মনে হবে। তাই scheduler সিদ্ধান্ত নেয় — VS Code-কে এখনই CPU দাও।

    Context switch শুরু হয়। Chrome-এর সমস্ত state তার PCB-তে জমা হয়ে যায়। VS Code-এর PCB থেকে তার আগের state আবার CPU-তে load হয়। সাথে virtual memory-র context-ও বদলে যায় — এখন থেকে CPU যেসব virtual address ব্যবহার করবে, সেগুলো VS Code-এর page table দিয়ে translate হবে, Chrome-এর নয়।

    সব প্রস্তুত হলে CPU আবার user mode-এ ফিরে আসে, আর VS Code-এর code চালাতে শুরু করে।

    04

    App জেগে উঠল

    VS Code একটা Electron application, মানে মূলত JavaScript-এ লেখা। Chrome-এর যে V8 engine, সেটাই ভেতরে বসে এই JavaScript চালাচ্ছে।

    VS Code-এর event loop-এ একটা read() system call অনেকক্ষণ ধরে pending অবস্থায় ছিল। সে user-এর input-এর অপেক্ষায় block হয়ে বসে ছিল। এখন OS-এর কাছে event ready, তাই সেই system call return করল, আর VS Code-এর হাতে 'A' character পৌঁছে গেল।

    এই keystroke handle করার যে code, সেটা JavaScript-এ লেখা। কিন্তু আগের আর্টিকেলে দেখেছি, V8 প্রথমে code-কে interpret করে চালায়, তারপর যেসব অংশ বারবার চলে সেগুলোকে JIT দিয়ে native machine code-এ compile করে ফেলে। Keystroke handler নিশ্চয়ই হাজার হাজার বার চলেছে। তাই এই মুহূর্তে সেটা আর interpret হচ্ছে না — সরাসরি compiled machine code-ই চলছে, প্রায় C-র মতো গতিতে।

    Code বলল — cursor যেখানে আছে সেখানে 'A' লেখো। কিন্তু "লেখা" মানে screen-এ pixel বসানো। কোন pixel-এ কী রং হবে, সেটা কে ঠিক করবে?

    05

    অক্ষর থেকে pixel

    এখানে font system কাজে নামে। আপনার editor-এ যে font ব্যবহার করছেন — Consolas, Fira Code, যাই হোক — সেই font file আগে থেকেই RAM-এ load করা আছে।

    Font file-এ প্রতিটা character-এর জন্য একটা করে shape-এর বর্ণনা থাকে। বেশিরভাগ modern font-এ সেই বর্ণনা vector আকারে — মানে গাণিতিক curve দিয়ে বলা থাকে অক্ষরটার আকৃতি কেমন হবে। এর সুবিধা হলো, যেকোনো size-এ scale করলেও অক্ষরটা ঝাপসা হয় না।

    কিন্তু screen তো vector বোঝে না। Screen বোঝে pixel। তাই সেই vector shape-কে আপনার current font size অনুযায়ী pixel grid-এ রূপান্তর করতে হয়। এই প্রক্রিয়ার নাম rasterization

    Rasterization শেষে 'A' character আর অক্ষর থাকে না। এখন সেটা কয়েকশো pixel-এর একটা grid, যার প্রতিটা pixel-এর জন্য R, G, B value নির্ধারিত। Article 2-তে দেখেছিলাম কীভাবে ছবি binary হয় — এখানেও ঠিক তাই ঘটল। একটা অক্ষর এইমাত্র একটা ছোট্ট ছবিতে পরিণত হলো। নিচের যন্ত্রে vector থেকে pixel-এ যাওয়াটা দেখুন:

    যন্ত্র ০২ — RASTERIZE
    VECTOR (font)
    PIXEL (screen)
    ৩৫ pixel grid
    বাঁয়ে মসৃণ vector A। "rasterize" চাপুন — screen-এর জন্য pixel-এ ভাঙবে।
    Font-এ অক্ষর থাকে মসৃণ vector curve হিসেবে, কিন্তু screen বোঝে শুধু pixel। Rasterization সেই curve-কে current size-এর pixel grid-এ ভাঙে — size যত বড়, pixel তত বেশি, অক্ষর তত পরিষ্কার।
    06

    Framebuffer থেকে আলো

    VS Code এখন আরেকটা system call করে — "এই pixel data screen-এ দেখাও।" আবার user mode থেকে kernel mode-এ transition, আবার OS-এর দরজায় কড়া নাড়া।

    OS-এর window compositor এই data receive করে। Compositor-এর কাজ হলো সব window-এর content মিলিয়ে screen-এর final চেহারা তৈরি করা। সে জানে VS Code-এর window screen-এর ঠিক কোন জায়গায় বসানো, তাই সেই অনুযায়ী pixel-গুলোর সঠিক coordinate হিসাব করে।

    তারপর সেই data লেখা হয় framebuffer-এ। Framebuffer হলো GPU-র নিজস্ব memory-তে (VRAM) একটা বিশেষ এলাকা, যেখানে screen-এ এই মুহূর্তে যা দেখাচ্ছে তার পুরো ছবিটা bit আকারে জমা থাকে।

    GPU প্রতি ১৬.৬৭ millisecond অন্তর (মানে 60Hz refresh rate-এ) সেই framebuffer পড়ে নেয় আর সেই ডেটা HDMI বা DisplayPort cable দিয়ে monitor-এ পাঠিয়ে দেয়। Cable-এর ভেতরে যা যাচ্ছে সেটা আসলে দ্রুত পরিবর্তিত voltage — high, low, high, low। সেই voltage pattern-ই pixel data-র binary রূপ।

    এই সিরিজের একদম প্রথম আর্টিকেলে আমরা যেখান থেকে শুরু করেছিলাম, ঘুরে ফিরে সেই voltage-এই ফিরে এলাম।

    Monitor-এর ভেতরের controller সেই signal receive করে। LCD screen-এ প্রতিটা pixel-এর পেছনে থাকে liquid crystal, আর controller সেই crystal-এর orientation নিয়ন্ত্রণ করে ঠিক করে দেয় কোন pixel দিয়ে কতটুকু আলো যাবে। OLED-এ ব্যাপারটা আরও সরাসরি — প্রতিটা pixel নিজেই আলো তৈরি করে।

    'A' অক্ষরের আকৃতি অনুযায়ী নির্দিষ্ট pixel-গুলোতে voltage গেল। সেই pixel-গুলো আলো ছাড়ল। Photon বেরিয়ে এসে আপনার চোখে পড়ল।

    আপনি screen-এ 'A' দেখলেন।

    07

    ২০ millisecond-এ কত কিছু

    আপনার কাছে পুরোটা instant মনে হয়েছে। এক আঙুলের চাপ, সাথে সাথে অক্ষর। নিচের যন্ত্রে পুরো relay-টা এক ধাপ এক ধাপ করে চালিয়ে দেখুন — keypress থেকে চোখে আলো পর্যন্ত:

    যন্ত্র ০৩ — THE RELAY ('A' → screen)
    ~০ms / ~২০ms
    HW'A' চাপলেন — switch-এর contact লাগল
    HWkeyboard chip scan করে byte 0x04 বানায়, USB-তে পাঠায়
    HWUSB controller পায়, একটা interrupt তোলে
    KCPU state save করে, kernel mode-এ যায়
    Kinterrupt handler USB থেকে scancode পড়ে
    Kkeyboard driver বোঝে — 'A'
    KOS event-টা focused window (VS Code)-এর queue-তে রাখে
    Kscheduler ঠিক করে — VS Code-কে জাগাও
    Kcontext switch: Chrome→VS Code, page table বদলায়
    Uuser mode-এ ফিরে read() 'A' ফেরত দেয়
    UJIT-compiled handler চলে — "cursor-এ A লেখো"
    Ufont system 'A'-কে pixel-এ rasterize করে
    Ksyscall → compositor → framebuffer (VRAM)
    HWGPU cable দিয়ে voltage পাঠায় monitor-এ
    HWpixel জ্বলে উঠল — photon চোখে পড়ল, 'A' দেখলেন
    HWKERNELUSER
    context switch: ০
    mode flip: ০
    HW hardware · K kernel · U user। ধাপ ১/১৫
    এক keypress: keyboard CPU, interrupt, kernel-এ ঢোকা, scheduler, context switch, দুটো system call, JIT, font rasterization, GPU — সব মিলিয়ে ~২০ms-এ কয়েক ডজন ধাপ, আর মাঝে OS conducting।

    কিন্তু এই সময়টুকুর ভেতরে ঘটে গেছে অনেক কিছু। Keyboard-এর নিজস্ব CPU একটা পুরো scan cycle চালিয়েছে। USB controller signal তৈরি করেছে। Main CPU একটা interrupt সামলেছে, নিজের state save করেছে, privilege level বদলেছে। OS-এর driver ডেটা পড়েছে, ঠিক করেছে কোন application এই event পাবে। Scheduler সিদ্ধান্ত নিয়েছে কাকে CPU দেওয়া হবে। একটা full context switch হয়েছে, page table বদলেছে। JIT-compiled JavaScript চলেছে। Font system একটা অক্ষরকে ছবিতে রূপান্তর করেছে। GPU framebuffer update করেছে। Cable-এ voltage-এর ঢেউ গেছে। Monitor-এর pixel জ্বলে উঠেছে।

    এই সময়ে CPU-তে কয়েক বিলিয়ন instruction execute হয়েছে। Cache line RAM থেকে L3, L2 হয়ে L1-এ এসেছে বহুবার। Page table lookup হয়েছে প্রতিটা memory access-এ। দুই-তিনটা context switch হয়েছে।

    আর সবচেয়ে আশ্চর্যের ব্যাপার হলো, এই পুরো chain-এর প্রতিটা অংশ আলাদা আলাদা মানুষ, আলাদা কোম্পানি, আলাদা সময়ে তৈরি করেছে। Keyboard-এর firmware লিখেছে এক দল, USB protocol design করেছে আরেক দল, kernel-এর driver লিখেছে অন্য কেউ, V8 engine বানিয়েছে Google-এর একটা team, font rendering library লিখেছে আরও কেউ। কেউ কারো সাথে বসে আলোচনা করেনি।

    তবু সবাই মিলে flawlessly কাজ করেছে। কারণ প্রতিটা layer পরের layer-এর জন্য একটা পরিষ্কার contract রেখে গেছে — "তুমি আমাকে এই format-এ ডেটা দাও, আমি এই কাজটা করে দেব।" ভেতরে কী হচ্ছে সেটা জানার দরকার নেই।

    এটাই abstraction। এবং এটাই আধুনিক computing-এর সবচেয়ে বড় শক্তি।

    // এই আর্টিকেলে কী শিখলাম
    • Keyboard-এর নিজের একটা CPU আছে — সে সারি-কলামের grid scan করে, byte বানায়, তারপর USB-তে পাঠায়।
    • Interrupt-ই CPU-কে থামানোর একমাত্র উপায়; থামার আগে সে নিজের state save করে kernel mode-এ যায়।
    • OS event-টা focused window-এর queue-তে রাখে, scheduler সেই app-কে CPU দেয় — একটা context switch।
    • App-এর JIT-compiled code অক্ষরটা নেয়; font system সেটাকে rasterize করে pixel বানায়।
    • Compositor → framebuffer → GPU → cable-এ voltage → monitor-এর pixel জ্বলে ওঠে। ঘুরে সেই voltage-এ ফেরত।
    • প্রতিটা layer আলাদা মানুষ বানিয়েছে, তবু contract মেনে সবাই একসাথে কাজ করে — এটাই abstraction।
    08

    সিরিজের শেষে

    আটটা আর্টিকেল আগে শুরু করেছিলাম একটা সহজ প্রশ্ন দিয়ে — x = 5 লিখলে সেই ৫ সংখ্যাটা কম্পিউটারের কোথায় যায়?

    উত্তরটা খুঁজতে গিয়ে আমাদের অনেক দূর যেতে হয়েছে। Transistor থেকে শুরু করে logic gate, gate থেকে latch, latch থেকে register। তারপর binary encoding, CPU-র ভেতরের ALU আর bus, fetch-decode-execute-এর অবিরাম চক্র। এরপর memory hierarchy, cache-এর চতুরতা, locality-র সৌন্দর্য। তারপর operating system, যে সবার মাঝখানে বসে সবকিছু সামলায়। আর শেষে compiler, interpreter আর JIT — যারা মানুষের ভাষাকে machine-এর ভাষায় অনুবাদ করে।

    এই সিরিজ পড়ে আপনি নতুন CPU design করতে পারবেন না। সেটা উদ্দেশ্যও ছিল না। উদ্দেশ্য ছিল অন্য কিছু।

    আমরা প্রতিদিন এমন সব tool ব্যবহার করি যাদের ভেতরের কিছুই জানি না। React লিখি, কিন্তু browser কীভাবে সেটা চালায় জানি না। Docker চালাই, কিন্তু container আসলে কী তা নিয়ে ভাবি না। এই না-জানাটা এক অর্থে ভালো — abstraction-এর পুরো উদ্দেশ্যই তো এটা। কিন্তু আরেক অর্থে এটা আমাদের অসহায় করে তোলে। কিছু ভাঙলে আমরা জানি না কোথায় খুঁজতে হবে।

    এখন অন্তত একটা মানচিত্র আছে। App slow হলে বুঝবেন cache-এর কথা ভাবা যেতে পারে। Memory leak হলে জানবেন heap কী জিনিস। Deployment-এ 502 এলে অন্তত অনুমান করতে পারবেন কোন layer-এ সমস্যা।

    সবচেয়ে বড় কথা, machine আর আগের মতো রহস্যময় থাকবে না। ঢাকনা খুলে ইঞ্জিনটা একবার দেখা হয়ে গেছে। ভেতরে কোনো জাদু নেই — আছে শুধু voltage, logic, আর কয়েক দশক ধরে মানুষের জমানো চতুর কিছু ধারণা।

    সেটুকু জানাই যথেষ্ট।

    পড়ার জন্য ধন্যবাদ। ভালো থাকবেন।

    09

    আরও গভীরে যেতে চাইলে

    এই সিরিজ ছিল একটা পাখির চোখে দেখা। প্রতিটা topic-ই নিজে একটা পূর্ণ জগত। কোনো একটা layer যদি আপনার ভালো লেগে থাকে, নিচের resource-গুলো থেকে শুরু করতে পারেন। প্রায় সবগুলোই বিনামূল্যে পাওয়া যায়।

    একদম শুরু থেকে বুঝতে চাইলে
    Crash Course Computer Science — YouTube-এ ৪০ পর্বের একটা সিরিজ, প্রতিটা ১০-১৫ মিনিট। Transistor থেকে AI পর্যন্ত পুরো computing-এর মানচিত্র। ভাষা সহজ, উপস্থাপনা চমৎকার। শুরু করার জন্য এর চেয়ে ভালো কিছু নেই।
    Ben Eater — YouTube channel। এই ভদ্রলোক breadboard-এ তার দিয়ে একটা সম্পূর্ণ 8-bit computer বানিয়েছেন, আর প্রতিটা ধাপ ক্যামেরার সামনে ব্যাখ্যা করেছেন। Article 1 আর 3-এ যা পড়েছেন, সেটা চোখের সামনে তৈরি হতে দেখতে পারবেন। ধৈর্য ধরে দেখার মতো জিনিস।
    Nand2Tetris (nand2tetris.org) — শুধু একটা NAND gate থেকে শুরু করে ধাপে ধাপে একটা পুরো কম্পিউটার বানানোর কোর্স। CPU, assembler, VM, compiler, OS — সব নিজে হাতে। Coursera-তে বিনামূল্যে করা যায়। এই সিরিজের প্রায় সবকিছু এখানে হাতে-কলমে করে দেখা যাবে।
    Hardware আর CPU নিয়ে
    Computer Systems: A Programmer's Perspective — Bryant ও O'Hallaron-এর লেখা। Carnegie Mellon-এর বিখ্যাত বই। Programmer-এর দৃষ্টিকোণ থেকে লেখা, তাই আপনার কোডের সাথে hardware-এর সম্পর্ক কোথায় সেটা স্পষ্ট হয়। Article 3, 4, 5-এর গভীর version।
    Computer Organization and Design — Patterson ও Hennessy-র লেখা। Computer architecture-এর classic textbook। একটু ভারী, কিন্তু কর্তৃত্বপূর্ণ।
    Inside the Machine — Jon Stokes। আধুনিক processor-এর ভেতরটা ছবির সাহায্যে ব্যাখ্যা করা। Textbook-এর চেয়ে সহজ পাঠ।
    Memory আর Performance নিয়ে
    What Every Programmer Should Know About Memory — Ulrich Drepper-এর লেখা একটা দীর্ঘ প্রবন্ধ, বিনামূল্যে পাওয়া যায়। Article 5-এ যা ছুঁয়ে গেছি, তার সম্পূর্ণ রূপ। Cache, DRAM, NUMA — সব এখানে। খুঁজলেই PDF পাবেন।
    Latency Numbers Every Programmer Should Know — Jeff Dean-এর তৈরি একটা ছোট তালিকা, ইন্টারনেটে সহজেই পাওয়া যায়। বিভিন্ন operation-এ কত সময় লাগে তার একটা mental model তৈরি করে দেয়।
    Operating System নিয়ে
    Operating Systems: Three Easy Pieces (ostep.org) — Arpaci-Dusseau দম্পতির লেখা। সম্পূর্ণ বিনামূল্যে, PDF আকারে ওয়েবসাইটেই আছে। OS শেখার জন্য সম্ভবত সবচেয়ে ভালো বই — লেখার ধরন সহজ, উদাহরণ প্রচুর। Article 6-এর প্রতিটা বিষয় এখানে বিস্তারিত।
    Linux Kernel Development — Robert Love। Linux kernel-এর ভেতরটা কীভাবে কাজ করে জানতে চাইলে।
    Compiler আর Language নিয়ে
    Crafting Interpreters (craftinginterpreters.com) — Robert Nystrom-এর লেখা, ওয়েবসাইটে সম্পূর্ণ বিনামূল্যে পড়া যায়। নিজে হাতে দুইটা interpreter বানানোর মধ্য দিয়ে পুরো বিষয়টা শেখানো হয়। লেখার মান অসাধারণ — technical বই এত সুন্দরভাবে কম লেখা হয়।
    V8 blog (v8.dev/blog) — JavaScript engine-এর ভেতরে কী ঘটে, engineer-রা নিজেরাই লেখেন। JIT, garbage collection, optimization নিয়ে গভীর লেখা।
    হাতে-কলমে শিখতে চাইলে
    nandgame.com — ব্রাউজারেই NAND gate থেকে শুরু করে ধাপে ধাপে কম্পিউটার বানানোর একটা খেলা। বিনামূল্যে, মজার, আর শেখার জন্য চমৎকার।
    CS50 (Harvard) — YouTube আর edX-এ বিনামূল্যে। C থেকে শুরু করে পুরো computer science-এর ভিত্তি। শিক্ষকতার মান অসাধারণ।

    আমি নিজেও আসলে এখানে দেওয়া প্রত্যেকটা রিসোর্স নিজে ঘেঁটে দেখার সুযোগ পাইনি। তবুও আপনাদের আর আমার নিজের সুবিধার্তে ইন্টারনেট ঘাঁটাঘাঁটি করে রিলেটেড সব রিসোর্স এখানে দিয়ে রাখলাম, যাতে পরে আরও এক্সপ্লোর করা যায়, আরও ভালোভাবে জানা যায়, নিজের জ্ঞানের কমতিগুলো শুধরানো যায়।

    শেষ কথা — এই তালিকা দেখে অভিভূত হওয়ার কিছু নেই। সবগুলো পড়তে হবে না। যে একটা জিনিস আপনার কৌতূহল জাগিয়েছে, সেটা নিয়েই শুরু করুন। বাকিটা সময়মতো আসবে।

    এই পাতা খোলার পর থেকে আপনার device-এ আনুমানিক ২৮৮.৫ কোটি বার transistor switch হয়েছে।
    cd ~  # back to terminal