<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bhushitha Hashan</title>
    <description>The latest articles on Forem by Bhushitha Hashan (@bhushitha_hashan).</description>
    <link>https://forem.com/bhushitha_hashan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3028340%2F229d3073-ab95-48de-8c07-906d8099f5fc.png</url>
      <title>Forem: Bhushitha Hashan</title>
      <link>https://forem.com/bhushitha_hashan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bhushitha_hashan"/>
    <language>en</language>
    <item>
      <title>Stop Wondering How Virtual Memory Works!!!</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Tue, 07 Apr 2026 05:55:15 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/stop-wondering-how-virtual-memory-works-55ma</link>
      <guid>https://forem.com/bhushitha_hashan/stop-wondering-how-virtual-memory-works-55ma</guid>
      <description>&lt;p&gt;It’s 9:45 PM on a Tuesday. The office lights are dimmed, and the only thing illuminating &lt;strong&gt;Arjun’s&lt;/strong&gt; face is the harsh white glare of a terminal filled with a nasty kernel backtrace. He’s slumped in his chair, hands over his face, looking like he’s about to lose it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya&lt;/strong&gt;, a Senior SRE who lives off black coffee and complex systems, walks by his desk on her way to the breakroom. She stops, seeing the "I’m fucked" energy radiating off him.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Scene: Late Night at the SRE Lab
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Yo, Arjun. You still here? You look like you just watched a server rack fall over. What’s up?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; (Groans) Maya, man... I’m losing my mind. I’ve been trying to debug this C program for four hours. I keep getting a &lt;code&gt;SIGSEGV&lt;/code&gt; at an address that looks like &lt;code&gt;0x0000800000001234&lt;/code&gt;. I thought I understood memory, but this just looks like a random number. My pointers are tripping, and I don't even know where this data is actually &lt;em&gt;going&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; (Leans over, looking at the screen) Ah, the classic "I think I know pointers" crisis. Don't sweat it. everyone hits this wall. You’re looking at a virtual address, but you’re stressed because you can’t see the "real" memory, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; Exactly. It feels like magic. I know the CPU does &lt;em&gt;something&lt;/em&gt; with page tables and the MMU, but it feels like a black box.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Alright, pull up a chair. Let’s strip the magic away. Think about it like this: your program is a spoiled brat. It thinks it owns the entire memory space,yes from zero to the max. That’s the &lt;strong&gt;Virtual Address Space&lt;/strong&gt;. But the actual RAM (the &lt;strong&gt;Physical Address&lt;/strong&gt;) is a shared resource the OS manages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; So the CPU translates them on the fly?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Yeah, via the &lt;strong&gt;MMU (Memory Management Unit)&lt;/strong&gt;. But it doesn't translate byte by byte.that would be insane. It does it in 4KB chunks called &lt;strong&gt;Pages&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; Okay, so a virtual address is just an index?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Sort of. Look at your 64-bit address. Even though we call it 64-bit, x86_64 CPUs usually only use 48 bits for addressing right now. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; Wait, why only 48?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Because 48 bits gives you 256 Terabytes of RAM. We don't exactly have that sitting in the server room yet. But here’s the kicker: bits 48 through 63 &lt;strong&gt;must&lt;/strong&gt; be a copy of bit 47. If bit 47 is 0, the top bits must be 0. If it's 1, the top bits must be 1. This is called &lt;strong&gt;Canonical Form&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; (Looking at his code) Wait... bit 47 in my address &lt;code&gt;0x000080...&lt;/code&gt; is 0, but bit 48 is a 1. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Bingo. That’s why you’re fucked. You broke the canonical rule. The CPU didn't even look at the page table; it just saw that bit 48 didn't match bit 47 and threw a &lt;strong&gt;General Protection Fault&lt;/strong&gt;. &lt;code&gt;SIGSEGV&lt;/code&gt;. Game over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; Holy shit. So the address space is basically split in half?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Exactly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lower half (bit 47=0):&lt;/strong&gt; User space (&lt;code&gt;0x0000...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upper half (bit 47=1):&lt;/strong&gt; Kernel space (&lt;code&gt;0xffff...&lt;/code&gt;)
Anything in that "hole" in the middle is radioactive. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; Okay, so if I fix my pointer math and stay in the lower half, how does it get to the actual RAM chip?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; This is where it gets cool. The MMU takes your virtual address and splits it. The lowest 12 bits (bits 0–11) are the &lt;strong&gt;Offset&lt;/strong&gt;. Since 2 to the power 12 = 4096, that offset points to the exact byte inside a 4KB page. The rest of the bits are the &lt;strong&gt;Virtual Page Number (VPN)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; And the MMU uses that VPN to "walk" the page table?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Right. It’s a 4 level tree. It’s like a scavenger hunt. The CPU starts at a base address in the &lt;code&gt;CR3&lt;/code&gt; register, uses bits from your address to find the next level, and finally lands on a &lt;strong&gt;PTE (Page Table Entry)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsb6f1v73mwg6bw26nvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsb6f1v73mwg6bw26nvm.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; (Squinting) So the PTE is the final answer?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Yes, you’ve got it exactly right. But the PTE is a compact little structure, not just a plain address. Look at this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bits 0–11:&lt;/strong&gt; These are your &lt;strong&gt;Permission and Status Flags&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bits 12–51:&lt;/strong&gt; This is the &lt;strong&gt;PFN (Physical Frame Number)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bit 63:&lt;/strong&gt; This is the &lt;strong&gt;NX (No Execute) bit&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; Wait, so you’re saying the first 12 bits are just used for permissions and shit, and the other bits do the actual pointing?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Yes, exactly! The &lt;strong&gt;PTE&lt;/strong&gt; contains the &lt;strong&gt;physical frame number (PFN)&lt;/strong&gt; , which is the real, physical address of the page in RAM, but it's shifted right by 12 bits to save space. &lt;/p&gt;

&lt;p&gt;When the CPU confirms you have permission (checking those flags in bits 0-11 like "is it writable?" or "is it user-accessible?"), it takes that &lt;strong&gt;PFN&lt;/strong&gt;, shifts it left by 12 bits (which is just adding twelve zeros at the end) to get the base physical address, and then it &lt;strong&gt;adds the offset&lt;/strong&gt; from your original virtual address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; So: Virtual address -&amp;gt; PTE -&amp;gt; PFN (real physical page address) -&amp;gt; + offset -&amp;gt; real physical byte address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1l8uoki36tgoznpv7r2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1l8uoki36tgoznpv7r2.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Exactly. No more indirection. That’s the final translation. The address that comes out of that math is what goes out on the memory bus to actually grab the data from the RAM stick.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkijwylxvnb7idsyd36xg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkijwylxvnb7idsyd36xg.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; Man, that bit shifting is clever. It’s like they reused the 12 bits of the offset to store the permissions in the PTE because they knew the physical frame address would always end in twelve zeros anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Spot on. You’ve mastered the PTE layout. Now, what happens if the &lt;strong&gt;Present bit&lt;/strong&gt; (bit 0) is 0?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; The MMU can’t find the page?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Right. &lt;strong&gt;Page Fault&lt;/strong&gt;. The CPU stops what it's doing and screams for the OS. The kernel's page fault handler looks at the &lt;code&gt;CR2&lt;/code&gt; register to see where you were trying to go. If you were just trying to access a page that got swapped to the SSD, the kernel quietly loads it into RAM, updates the PTE, and lets your program continue like nothing happened.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; But if I’m trying to write to a read-only page or a null pointer?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Then the kernel realizes you’re doing something illegal and sends you a &lt;code&gt;SIGSEGV&lt;/code&gt;. Which is exactly what happened to you tonight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; (Laughs) Because I was hitting a non-canonical address. I didn't even make it to the page table check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; Exactly. And one last thing,don't forget the &lt;strong&gt;TLB (Translation Lookaside Buffer)&lt;/strong&gt;. Walking a 4-level page table for &lt;em&gt;every single&lt;/em&gt; memory access would make the computer slow as hell. The TLB is a tiny, super fast cache in the CPU that remembers recent "Virtual -&amp;gt; Physical" translations. It's the only reason modern computers are fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; So: Check TLB -&amp;gt; if miss, walk Page Tables -&amp;gt; check PTE flags -&amp;gt;calculate physical address -&amp;gt; fetch data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; You got it. Now, quit staring at that backtrace, fix your pointer math, and let's get some food. My treat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arjun:&lt;/strong&gt; (Closing the laptop) Thanks, Maya. I actually feel like I know what's happening under the hood now. I’m not just "fucked",I’m "educated and fucked."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maya:&lt;/strong&gt; (Laughing) That’s the spirit  kid. Let’s go.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sre</category>
      <category>linux</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Speed vs Truth: Understanding Redis the Way Engineers Actually Do</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Wed, 18 Mar 2026 16:01:12 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/speed-vs-truth-understanding-redis-the-way-engineers-actually-do-2p2b</link>
      <guid>https://forem.com/bhushitha_hashan/speed-vs-truth-understanding-redis-the-way-engineers-actually-do-2p2b</guid>
      <description>&lt;h2&gt;
  
  
  Late Afternoon, Real System, Real Confusion
&lt;/h2&gt;

&lt;p&gt;The office was quieter than usual. Most people had already left, but one corner still had life in it.&lt;/p&gt;

&lt;p&gt;A whiteboard covered in boxes, arrows, and half-erased notes.&lt;/p&gt;

&lt;p&gt;And in front of it,Arjun.&lt;/p&gt;

&lt;p&gt;A few weeks into his internship, he had reached that stage where things no longer looked simple… but also didn’t fully make sense yet.&lt;/p&gt;

&lt;p&gt;Behind him, leaning on the desk with a coffee mug that had clearly been refilled too many times, stood Maya,the senior systems engineer.&lt;/p&gt;

&lt;p&gt;She watched him stare at the diagram for a while before speaking.&lt;/p&gt;

&lt;p&gt;“Alright,” she said, calm and direct. “You’ve been staring at that same box for five minutes. What’s bothering you?”&lt;/p&gt;

&lt;p&gt;Arjun didn’t turn immediately. He pointed at the whiteboard.&lt;/p&gt;

&lt;p&gt;A box labeled:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“I get that this is for speed,” he said slowly. “Like… we put it in front of the database so things don’t get slow.”&lt;/p&gt;

&lt;p&gt;Maya nodded. “Good. That’s the surface-level answer. Keep going.”&lt;/p&gt;

&lt;p&gt;Arjun hesitated, then turned.&lt;/p&gt;

&lt;p&gt;“But it feels… fake.”&lt;/p&gt;

&lt;p&gt;Maya raised an eyebrow. “Fake?”&lt;/p&gt;

&lt;p&gt;“Yeah,” he said. “Like it’s not real storage. It’s just… temporary. So why are we trusting it at all?”&lt;/p&gt;

&lt;p&gt;Maya smiled.&lt;/p&gt;

&lt;p&gt;“Good,” she said. “Now we can actually start.”&lt;/p&gt;




&lt;h1&gt;
  
  
  What Redis Actually Is (Explained Like You Mean It)
&lt;/h1&gt;

&lt;p&gt;Maya walked to the whiteboard and drew two boxes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Redis ] -------- [ Database ]
   (RAM)             (Disk)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;She tapped the first box.&lt;/p&gt;

&lt;p&gt;“Redis lives in memory. RAM. That’s why it’s fast.”&lt;/p&gt;

&lt;p&gt;Then she tapped the second.&lt;/p&gt;

&lt;p&gt;“The database lives on disk. That’s why it’s slower,but reliable.”&lt;/p&gt;

&lt;p&gt;Arjun nodded. “Yeah, I get that part.”&lt;/p&gt;

&lt;p&gt;“No,” Maya said, shaking her head slightly. “You understand the words. Not the implication.”&lt;/p&gt;

&lt;p&gt;She turned back and wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Redis = Speed, Not Permanence&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;“Everything about Redis is optimized for one thing.responding fast,” she continued. “Not guaranteeing your data will exist forever.”&lt;/p&gt;

&lt;p&gt;Arjun frowned slightly. “So… it can lose data?”&lt;/p&gt;

&lt;p&gt;“It &lt;em&gt;will&lt;/em&gt; lose data,” Maya corrected.&lt;/p&gt;

&lt;p&gt;She started listing on the board:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory limit → eviction&lt;/li&gt;
&lt;li&gt;Crash → possible data loss&lt;/li&gt;
&lt;li&gt;Restart → partial recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then she turned.&lt;/p&gt;

&lt;p&gt;“So if you think of Redis as your database, you’ve already made a mistake.”&lt;/p&gt;




&lt;h1&gt;
  
  
  The First Mental Breakthrough
&lt;/h1&gt;

&lt;p&gt;Arjun crossed his arms, thinking.&lt;/p&gt;

&lt;p&gt;“So then what is it actually?”&lt;/p&gt;

&lt;p&gt;Maya didn’t answer immediately. Instead, she erased a small section and drew this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → App → Redis → Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Most requests stop here,” she said, pointing to Redis.&lt;/p&gt;

&lt;p&gt;Then she added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → App → Redis ❌ (miss) → Database → Redis → User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“This is what happens when Redis doesn’t have the data.”&lt;/p&gt;

&lt;p&gt;She stepped back.&lt;/p&gt;

&lt;p&gt;“Redis is not the source of truth,” she said.&lt;br&gt;
“It’s a &lt;strong&gt;temporary, fast copy of reality&lt;/strong&gt;.”&lt;/p&gt;

&lt;p&gt;Arjun repeated it quietly.&lt;/p&gt;

&lt;p&gt;“…temporary copy.”&lt;/p&gt;

&lt;p&gt;“Exactly.”&lt;/p&gt;


&lt;h1&gt;
  
  
  Why We Even Need Redis
&lt;/h1&gt;

&lt;p&gt;Arjun turned back to the board.&lt;/p&gt;

&lt;p&gt;“Okay, but why not just make the database faster?”&lt;/p&gt;

&lt;p&gt;Maya laughed softly.&lt;/p&gt;

&lt;p&gt;“Everyone asks that at some point.”&lt;/p&gt;

&lt;p&gt;She drew two timelines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RAM access  → nanoseconds
Disk access → milliseconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then she circled them.&lt;/p&gt;

&lt;p&gt;“This difference is massive,” she said. “You don’t ‘optimize’ your way out of physics.”&lt;/p&gt;

&lt;p&gt;She drew another diagram:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without Redis:
User → App → Database (every request)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;With Redis:
User → App → Redis (most requests)
                ↓
             Database (rare)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Redis exists so your database doesn’t collapse under load.”&lt;/p&gt;




&lt;h1&gt;
  
  
  Where Things Start Getting Dangerous
&lt;/h1&gt;

&lt;p&gt;Arjun nodded, following along.&lt;/p&gt;

&lt;p&gt;“Okay… so we cache stuff. Makes sense.”&lt;/p&gt;

&lt;p&gt;Maya tilted her head slightly.&lt;/p&gt;

&lt;p&gt;“That works when data doesn’t change often,” she said. “But what about things that change constantly?”&lt;/p&gt;

&lt;p&gt;She wrote:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page views&lt;/li&gt;
&lt;li&gt;likes&lt;/li&gt;
&lt;li&gt;active users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then added:&lt;/p&gt;

&lt;p&gt;“Where do those updates happen?”&lt;/p&gt;

&lt;p&gt;Arjun answered quickly.&lt;/p&gt;

&lt;p&gt;“In Redis… because it’s fast.”&lt;/p&gt;

&lt;p&gt;Maya nodded.&lt;/p&gt;

&lt;p&gt;“And now you’ve just moved the problem.”&lt;/p&gt;




&lt;h1&gt;
  
  
  The Fear Kicks In
&lt;/h1&gt;

&lt;p&gt;She wrote on the board:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;views:article:123 → 10,482
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“This number keeps increasing,” she said.&lt;/p&gt;

&lt;p&gt;Arjun nodded.&lt;/p&gt;

&lt;p&gt;Then she asked:&lt;/p&gt;

&lt;p&gt;“What happens if Redis runs out of memory?”&lt;/p&gt;

&lt;p&gt;Arjun paused.&lt;/p&gt;

&lt;p&gt;“…it deletes something?”&lt;/p&gt;

&lt;p&gt;“Yes.”&lt;/p&gt;

&lt;p&gt;“And if that key gets deleted?”&lt;/p&gt;

&lt;p&gt;“…we lose the count.”&lt;/p&gt;

&lt;p&gt;Maya crossed her arms.&lt;/p&gt;

&lt;p&gt;“Now you see the problem.”&lt;/p&gt;




&lt;h1&gt;
  
  
  The Second Mental Shift: Not All Data Is Equal
&lt;/h1&gt;

&lt;p&gt;Arjun leaned back slightly.&lt;/p&gt;

&lt;p&gt;“So we shouldn’t store important stuff there.”&lt;/p&gt;

&lt;p&gt;“Exactly,” Maya said. “But let’s define ‘important’ properly.”&lt;/p&gt;

&lt;p&gt;She split the board into two sections.&lt;/p&gt;




&lt;h2&gt;
  
  
  Left Side
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Critical Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;payments&lt;/li&gt;
&lt;li&gt;orders&lt;/li&gt;
&lt;li&gt;balances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;She underlined it.&lt;/p&gt;

&lt;p&gt;“Lose this, and your system is broken.”&lt;/p&gt;




&lt;h2&gt;
  
  
  Right Side
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;High-Speed Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;analytics&lt;/li&gt;
&lt;li&gt;counters&lt;/li&gt;
&lt;li&gt;sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;“Lose a bit of this?” she shrugged. “System still works.”&lt;/p&gt;




&lt;p&gt;“Now the rules change,” she said.&lt;/p&gt;




&lt;h1&gt;
  
  
  Two Ways to Write Data
&lt;/h1&gt;

&lt;p&gt;Maya drew two flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Write-Through
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App → Database → Redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Safe,” she said. “Slower, but correct.”&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Write-Behind
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App → Redis → (later) Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Fast,” she said. “But risky.”&lt;/p&gt;




&lt;p&gt;Arjun looked at both.&lt;/p&gt;

&lt;p&gt;“So we just pick one?”&lt;/p&gt;

&lt;p&gt;Maya shook her head.&lt;/p&gt;

&lt;p&gt;“No. We use both. Based on the data.”&lt;/p&gt;




&lt;h1&gt;
  
  
  The Trade-Off Nobody Escapes
&lt;/h1&gt;

&lt;p&gt;She turned to him.&lt;/p&gt;

&lt;p&gt;“You can’t have perfect speed and perfect safety at the same time.”&lt;/p&gt;

&lt;p&gt;Arjun nodded slowly.&lt;/p&gt;

&lt;p&gt;“Yeah… that makes sense.”&lt;/p&gt;




&lt;h1&gt;
  
  
  The Data Loss Gap (This One Matters)
&lt;/h1&gt;

&lt;p&gt;Maya drew a timeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Time →
[ Redis updated ] ---- (delay) ---- [ DB updated ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“This gap,” she said, tapping the space in between, “is where things can go wrong.”&lt;/p&gt;

&lt;p&gt;Arjun leaned forward.&lt;/p&gt;

&lt;p&gt;“If the system crashes there…”&lt;/p&gt;

&lt;p&gt;“…you lose data,” Maya finished.&lt;/p&gt;




&lt;h1&gt;
  
  
  So We Add a Queue
&lt;/h1&gt;

&lt;p&gt;She erased part of the board and drew a new flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;App&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;→ Update Redis&lt;/span&gt;
  &lt;span class="s"&gt;→ Push event → Queue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Worker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;→ Read Queue&lt;/span&gt;
  &lt;span class="s"&gt;→ Update Database&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arjun looked at it.&lt;/p&gt;

&lt;p&gt;“So now even if Redis crashes…”&lt;/p&gt;

&lt;p&gt;“The queue still has the data,” Maya said.&lt;/p&gt;

&lt;p&gt;“And if the worker crashes?”&lt;/p&gt;

&lt;p&gt;“It resumes from the queue.”&lt;/p&gt;

&lt;p&gt;Arjun nodded.&lt;/p&gt;

&lt;p&gt;“…okay, that’s solid.”&lt;/p&gt;




&lt;h1&gt;
  
  
  When Things Go Wrong (And They Will)
&lt;/h1&gt;

&lt;p&gt;Maya didn’t respond immediately.&lt;/p&gt;

&lt;p&gt;Instead, she tilted her head slightly.&lt;/p&gt;

&lt;p&gt;“Solid… but not perfect,” she said.&lt;/p&gt;

&lt;p&gt;Arjun frowned. “What do you mean?”&lt;/p&gt;

&lt;p&gt;“Walk it through again,” Maya said.&lt;/p&gt;

&lt;p&gt;Arjun looked back at the board.&lt;/p&gt;

&lt;p&gt;“Okay… we write to Redis, push to the queue…”&lt;/p&gt;

&lt;p&gt;He paused.&lt;/p&gt;

&lt;p&gt;“What if Redis evicts the key before the worker runs?”&lt;/p&gt;

&lt;p&gt;Maya nodded. “Keep going.”&lt;/p&gt;

&lt;p&gt;“And then… what if the worker fails before writing to the database?”&lt;/p&gt;

&lt;p&gt;Now he stopped completely.&lt;/p&gt;

&lt;p&gt;“…then the data never reaches the database.”&lt;/p&gt;

&lt;p&gt;Maya crossed her arms.&lt;/p&gt;

&lt;p&gt;“And Redis already lost it.”&lt;/p&gt;

&lt;p&gt;They both looked at the board.&lt;/p&gt;

&lt;p&gt;“So we still lose data,” Arjun said quietly.&lt;/p&gt;

&lt;p&gt;“Exactly.”&lt;/p&gt;

&lt;p&gt;Maya uncapped the marker again.&lt;/p&gt;

&lt;p&gt;She drew it out slowly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Write → Redis
2. Push → Queue
3. Redis evicts key ❌
4. Worker fails ❌
5. Data never reaches DB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;She stepped back.&lt;/p&gt;

&lt;p&gt;“This,” she said, “is the kind of failure that doesn’t crash your system.”&lt;/p&gt;

&lt;p&gt;Arjun frowned.&lt;/p&gt;

&lt;p&gt;“…it just loses data.”&lt;/p&gt;

&lt;p&gt;“Exactly.”&lt;/p&gt;




&lt;h2&gt;
  
  
  The Subtle Problem With “Safe Enough”
&lt;/h2&gt;

&lt;p&gt;Maya crossed her arms.&lt;/p&gt;

&lt;p&gt;“The queue &lt;em&gt;reduces&lt;/em&gt; risk,” she said. “But it doesn’t eliminate it.”&lt;/p&gt;

&lt;p&gt;Arjun nodded slowly.&lt;/p&gt;

&lt;p&gt;“So what do we do?”&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Things Real Systems Add
&lt;/h2&gt;

&lt;p&gt;Maya held up three fingers.&lt;/p&gt;

&lt;p&gt;“Once you reach this level, you start thinking about three things.”&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Idempotent Writes
&lt;/h3&gt;

&lt;p&gt;“If the worker retries the same update twice,” she said, “nothing should break.”&lt;/p&gt;

&lt;p&gt;She wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;Bad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;INCR&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;duplicates&lt;/span&gt; &lt;span class="n"&gt;possible&lt;/span&gt;

&lt;span class="n"&gt;Better&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“You design your writes so repeating them is safe.”&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Assume the Queue Lies
&lt;/h3&gt;

&lt;p&gt;Arjun blinked. “The queue… lies?”&lt;/p&gt;

&lt;p&gt;Maya smiled slightly.&lt;/p&gt;

&lt;p&gt;“Not maliciously. But it might deliver the same message twice. Or later than expected.”&lt;/p&gt;

&lt;p&gt;She underlined it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Always assume at-least-once delivery&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;“Your system must handle duplicates.”&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Retry Properly
&lt;/h3&gt;

&lt;p&gt;“What if the worker fails?” she continued.&lt;/p&gt;

&lt;p&gt;“Retry?” Arjun said.&lt;/p&gt;

&lt;p&gt;“Yes. But not blindly.”&lt;/p&gt;

&lt;p&gt;She wrote:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retry with delay&lt;/li&gt;
&lt;li&gt;Exponential backoff&lt;/li&gt;
&lt;li&gt;Dead-letter queue (failed forever)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;“If you don’t handle failures properly,” she said, “they disappear quietly.”&lt;/p&gt;




&lt;h2&gt;
  
  
  The Final Realization
&lt;/h2&gt;

&lt;p&gt;Arjun leaned back.&lt;/p&gt;

&lt;p&gt;“So even the ‘safe’ design isn’t actually safe.”&lt;/p&gt;

&lt;p&gt;Maya nodded.&lt;/p&gt;

&lt;p&gt;“Nothing is perfectly safe,” she said. “You just keep reducing risk.”&lt;/p&gt;




&lt;h2&gt;
  
  
  Updating the Mental Model
&lt;/h2&gt;

&lt;p&gt;Maya walked back to the board one last time and added a small note next to the system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Redis ] → fast but fragile  
[ Queue ] → safer, but needs retries  
[ Database ] → final truth  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then underneath it, she wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Design for failure, not success&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Arjun stared at the board.&lt;/p&gt;

&lt;p&gt;“…this got complicated fast.”&lt;/p&gt;

&lt;p&gt;“Yeah,” she said. “Welcome to distributed systems.”&lt;/p&gt;




&lt;h1&gt;
  
  
  But There’s Still a Subtle Problem
&lt;/h1&gt;

&lt;p&gt;Maya smiled slightly.&lt;/p&gt;

&lt;p&gt;“But There’s always one more problem.”&lt;/p&gt;

&lt;p&gt;She drew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Redis loses key
2. User requests data
3. App checks DB
4. DB is slightly outdated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arjun’s eyes narrowed.&lt;/p&gt;

&lt;p&gt;“So the user sees old data.”&lt;/p&gt;

&lt;p&gt;“Exactly.”&lt;/p&gt;




&lt;h1&gt;
  
  
  Read Repair (The Quiet Fix)
&lt;/h1&gt;

&lt;p&gt;Maya added one more layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cache miss →
  Fetch DB →
  Check queue →
  Merge updates →
  Return →
  Update Redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arjun blinked.&lt;/p&gt;

&lt;p&gt;“So reading actually fixes the data?”&lt;/p&gt;

&lt;p&gt;“Yep.”&lt;/p&gt;




&lt;h1&gt;
  
  
  Everything Comes Together
&lt;/h1&gt;

&lt;p&gt;Maya stepped back and rewrote the system cleanly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          [ Redis ]
              ↓
User → App → Cache Layer
              ↓
          [ Queue ]
              ↓
          [ Database ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;She pointed at each part.&lt;/p&gt;

&lt;p&gt;“Redis gives you speed.”&lt;/p&gt;

&lt;p&gt;“Queue gives you safety.”&lt;/p&gt;

&lt;p&gt;“Database gives you truth.”&lt;/p&gt;




&lt;h1&gt;
  
  
  The Final Understanding
&lt;/h1&gt;

&lt;p&gt;Arjun looked at the board for a long moment.&lt;/p&gt;

&lt;p&gt;Then he said quietly:&lt;/p&gt;

&lt;p&gt;“So Redis isn’t the system.”&lt;/p&gt;

&lt;p&gt;Maya smiled.&lt;/p&gt;

&lt;p&gt;“It’s part of the system.”&lt;/p&gt;

&lt;p&gt;He nodded.&lt;/p&gt;

&lt;p&gt;“And the database…”&lt;/p&gt;

&lt;p&gt;“…is reality,” she finished.&lt;/p&gt;




&lt;h1&gt;
  
  
  The One Sentence That Matters
&lt;/h1&gt;

&lt;p&gt;Maya picked up the marker one last time and wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Move fast in Redis, commit safely through queues, trust the database.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Arjun read it once.&lt;/p&gt;

&lt;p&gt;Then again.&lt;/p&gt;

&lt;p&gt;This time, the diagram didn’t feel confusing.&lt;/p&gt;

&lt;p&gt;It felt… inevitable.&lt;/p&gt;




&lt;h1&gt;
  
  
  If You Walk Away Remembering This
&lt;/h1&gt;

&lt;p&gt;Maya capped the marker and turned.&lt;/p&gt;

&lt;p&gt;“Before you leave,” she said, “tell me what you learned.”&lt;/p&gt;

&lt;p&gt;Arjun didn’t hesitate this time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis is fast but temporary
&lt;/li&gt;
&lt;li&gt;Data there can disappear
&lt;/li&gt;
&lt;li&gt;Important data goes to the database first, then update Redis
&lt;/li&gt;
&lt;li&gt;Fast changing data can go to Redis first with a queue
&lt;/li&gt;
&lt;li&gt;Queues make things safer, but not perfect
&lt;/li&gt;
&lt;li&gt;Everything is a trade off
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maya nodded.&lt;/p&gt;

&lt;p&gt;“Good. Now you’re not just using Redis anymore.”&lt;/p&gt;

&lt;p&gt;Arjun looked back at the board one last time.&lt;/p&gt;

&lt;p&gt;“It’s not just about making it fast,” he said.&lt;/p&gt;

&lt;p&gt;Maya shook her head slightly.&lt;/p&gt;

&lt;p&gt;“It’s about knowing where it can break.”&lt;/p&gt;

&lt;p&gt;She picked up her coffee.&lt;/p&gt;

&lt;p&gt;“That’s when you start thinking like a systems engineer.”&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>redis</category>
      <category>softwaredevelopment</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>A Deep Dive into Kernel Context Switching</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Fri, 06 Mar 2026 15:02:41 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/a-deep-dive-into-kernel-context-switching-2g55</link>
      <guid>https://forem.com/bhushitha_hashan/a-deep-dive-into-kernel-context-switching-2g55</guid>
      <description>&lt;p&gt;The afternoon sun was hitting the glass. Marcus, a senior engineer who had seen more kernel panics than he had hot meals, sat leaning back in his chair. Opposite him, Leo, the new intern, was staring intensely at a series of assembly snippets on his dual-monitor setup.&lt;/p&gt;

&lt;p&gt;"Marcus," Leo said, spinning around. "I’m looking at how Linux handles processes. I get the theory, but the hardware part feels like magic. There’s no &lt;code&gt;task_struct_ptr&lt;/code&gt; register on an x86 CPU. So how does the kernel actually &lt;em&gt;know&lt;/em&gt; who it is the millisecond a system call happens?"&lt;/p&gt;

&lt;p&gt;Marcus grinned. "You’ve hit the 'GPS' problem of OS design. Pull up a chair. You have to understand that the CPU is a bit of a blank slate; the OS has to carve its own landmarks into the hardware."&lt;/p&gt;




&lt;h3&gt;
  
  
  Why the GS Register is the Kernel’s North Star
&lt;/h3&gt;

&lt;p&gt;"To answer your question," Marcus began, "we have to talk about the &lt;strong&gt;GS register&lt;/strong&gt;. In the world of x86_64, OS designers decided that general-purpose registers like &lt;code&gt;RAX&lt;/code&gt; or &lt;code&gt;RBX&lt;/code&gt; were too precious to waste. If you used &lt;code&gt;RBX&lt;/code&gt; to hold the pointer to the current task, you’d have one less register for math in every single function. Plus, if a programmer accidentally overwrote it, the system would forget which task was running and crash immediately."&lt;/p&gt;

&lt;p&gt;He pointed to Leo’s screen. "Instead, Linux uses the &lt;strong&gt;GS register&lt;/strong&gt; as a stable anchor. It’s reserved specifically to point to &lt;strong&gt;Per-CPU Data&lt;/strong&gt;. Each CPU core has its own GS base address that points to a private memory area for that specific core."&lt;/p&gt;




&lt;h3&gt;
  
  
  The Transition: From User to Kernel
&lt;/h3&gt;

&lt;p&gt;"When you’re in User Mode," Marcus continued, "the GS register might be used for thread-local storage. But the moment a system call or an interrupt happens, the CPU executes a specialized instruction called &lt;code&gt;swapgs&lt;/code&gt;. This instruction flips the GS base to a kernel-specific area. Inside that area, the kernel stores the most important information: the &lt;strong&gt;Task Struct&lt;/strong&gt; and the &lt;strong&gt;Kernel Stack&lt;/strong&gt;."&lt;/p&gt;

&lt;p&gt;"So it's like a 'GPS Home' button?" Leo asked.&lt;/p&gt;

&lt;p&gt;"Exactly. When the kernel code needs to know 'Who am I?', it doesn't search a list. It just executes something like &lt;code&gt;mov rax, gs:[offset_of_current_task]&lt;/code&gt;. It’s a direct, protected lookup."&lt;/p&gt;




&lt;h3&gt;
  
  
  Entry and the Trap Frame
&lt;/h3&gt;

&lt;p&gt;"But before the kernel even thinks about switching tasks," Marcus said, "it has to protect the current one. The moment a user program triggers a &lt;code&gt;syscall&lt;/code&gt; or an interrupt, the CPU executes &lt;code&gt;swapgs&lt;/code&gt;. This flips the GS base to the kernel’s side. But then, the kernel performs its first vital ritual: &lt;strong&gt;Saving the User State&lt;/strong&gt;."&lt;/p&gt;

&lt;p&gt;"Wait, so it doesn't just jump into kernel code?" Leo asked.&lt;/p&gt;

&lt;p&gt;"Not without a backup. The kernel immediately pushes all the user's current registers—&lt;code&gt;RAX&lt;/code&gt;, &lt;code&gt;R11&lt;/code&gt;, &lt;code&gt;RCX&lt;/code&gt;, and the rest—onto the kernel stack. This collection is called the &lt;strong&gt;Trap Frame&lt;/strong&gt; (or &lt;code&gt;pt_regs&lt;/code&gt;). This ensures that no matter what the kernel does next, it has a perfect 'save-point' of exactly what the user was doing. Without this step, we could never return to the application."&lt;/p&gt;




&lt;h3&gt;
  
  
  The RSP Dillema
&lt;/h3&gt;

&lt;p&gt;"Wait,What happened to the user stack pointer ?Do we just save it too while switching?" leo asked.Marcus leaned back, laughing softly. "That’s the exact question that keeps kernel developers up at night. You're thinking about the 'Exit'the popping. But the problem is the 'Entrance'. It’s a game of musical chairs where the CPU only has one seat, and that seat is the RSP register."&lt;/p&gt;

&lt;p&gt;He grabbed a dry erase marker and drew a single box on the board labeled RSP.&lt;/p&gt;

&lt;p&gt;"Here is your problem, Leo, The RSP register can only hold one address at a time. It’s either pointing at the User Stack or the Kernel Stack. It cannot point to both."&lt;/p&gt;

&lt;p&gt;The "One-Handed" Problem&lt;/p&gt;

&lt;p&gt;"Imagine you are holding a priceless Ming vase.that's the User Stack Pointer," Marcus said, gesturing with his hands. "You need to put it into a safety deposit box.that's the Kernel Stack. But the only way to open the safety deposit box is to use the same hand that is currently holding the vase."&lt;/p&gt;

&lt;p&gt;"The moment you reach for the box (the Kernel Stack), you have to let go of the vase (the User Stack Pointer). If you let go, it smashes on the floor. You've lost it."&lt;/p&gt;

&lt;p&gt;The "Stash" Before the "Push"&lt;/p&gt;

&lt;p&gt;"To get that User RSP value into the pt_regs struct on the kernel stack, you have to perform a very specific sequence of moves. Watch the registers closely:"&lt;/p&gt;

&lt;p&gt;The Entry: You just hit syscall. RSP is currently holding the User Stack address.&lt;/p&gt;

&lt;p&gt;The Dilemma: You need to change RSP to point to the Kernel Stack so you can start pushing pt_regs.&lt;/p&gt;

&lt;p&gt;The Move: But if you just do mov rsp, gs:[top_of_stack], the User Stack address is gone. It’s overwritten in the register. You can't 'push' it later because you don't know what it was anymore.&lt;/p&gt;

&lt;p&gt;"This is why we use gs:[user_stack_ptr] as a temporary shelf," Marcus explained.&lt;/p&gt;

&lt;p&gt;"The kernel executes:&lt;/p&gt;

&lt;p&gt;mov gs:[user_stack_ptr], rsp  (Putting the vase on the shelf)&lt;/p&gt;

&lt;p&gt;mov rsp, gs:&lt;a href="https://dev.toGrabbing%20the%20key%20to%20the%20safety%20box"&gt;top_of_stack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that RSP is safely pointing to the Kernel Stack, the kernel can finally do the 'Push' you’re talking about:&lt;/p&gt;

&lt;p&gt;push gs:&lt;a href="https://dev.toTaking%20the%20vase%20off%20the%20shelf%20and%20putting%20it%20in%20the%20box"&gt;user_stack_ptr&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;"Can't we just pop?"&lt;/p&gt;

&lt;p&gt;"You're right about the end of the story," Marcus nodded. "When the system call is over, we do pop the registers from the pt_regs back into the CPU. But you can't pop something that was never pushed. And you can't push the User RSP unless you have a temporary place to hold it while you're switching the RSP register itself."&lt;/p&gt;

&lt;p&gt;Leo stared at the whiteboard. "So it's literally just a bridge? A place to hold the value for, like, three instructions?"&lt;/p&gt;

&lt;p&gt;"Exactly," Marcus said. "It’s a 'scratchpad.' Once the User RSP is safely pushed into the pt_regs structure on the kernel stack, the value sitting in pcpu_hot.user_stack_ptr isn't actually used for much else until the next time that CPU core handles a transition. It's the only way to 'teleport' the stack pointer from a register to a memory location without losing it in the process."&lt;/p&gt;

&lt;p&gt;"Why not use a general register like RAX?"You might ask: 'Why not just move RSP into RAX temporarily?'" Marcus anticipated the next question. "Because RAX is a User Register. It contains the System Call Number (like 1 for write or 0 for read). If you move the stack pointer into RAX, you just deleted the user's instructions on what they wanted the kernel to do!"&lt;/p&gt;

&lt;p&gt;"The GS-based memory is the only place in the entire universe the kernel can 100% trust to be 'clean' and available the moment a syscall starts."&lt;/p&gt;

&lt;p&gt;Marcus tossed the marker back onto the tray. "It’s all about that tiny window of time where the CPU is 'homeless' between stacks. user_stack_ptr is the kernel’s temporary roof."&lt;/p&gt;




&lt;h3&gt;
  
  
  The Great Teleportation: Updating the Identity
&lt;/h3&gt;

&lt;p&gt;Leo tapped his pen. "Okay, so we’ve saved the user registers. Now the scheduler wants to move from Task A to Task B. How does the GS area know Task B is the new king?"&lt;/p&gt;

&lt;p&gt;"This is the crucial part people often miss," Marcus said. "The scheduler doesn't just swap the stack; it has to &lt;strong&gt;re-program the identity&lt;/strong&gt; of that CPU core. Inside the context switch function, the kernel physically overwrites the memory inside the Per-CPU area.&lt;/p&gt;

&lt;p&gt;It takes Task B’s &lt;code&gt;task_struct&lt;/code&gt; address and writes it into &lt;code&gt;gs:[offset_of_current_task]&lt;/code&gt;. Then, it takes Task B’s kernel stack pointer and writes it into &lt;code&gt;gs:[offset_to_top_of_stack]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Crucially, we &lt;strong&gt;don't&lt;/strong&gt; change the GS Base address itself,that still points to the same CPU core. We just update the 'data' inside that core's private office. Once those pointers are updated, any part of the kernel that asks 'Who is the current task?' will now get Task B as the answer."&lt;/p&gt;




&lt;h3&gt;
  
  
  The Performance Shortcut: Beating the Memory Latency
&lt;/h3&gt;

&lt;p&gt;Leo frowned, tapping his pen. "Wait. If the kernel has to find the &lt;code&gt;gs&lt;/code&gt; base, then find the &lt;code&gt;task_struct&lt;/code&gt;, then find the pointer to the stack inside that struct... isn't that a lot of memory hopping? That sounds slow for something that happens thousands of times a second."&lt;/p&gt;

&lt;p&gt;"You’re right," Marcus nodded. "That's a classic bottleneck. Modern Linux engineers hate extra memory hops. To fix this, they use &lt;strong&gt;redundancy for speed&lt;/strong&gt;. They don't go to the &lt;code&gt;task_struct&lt;/code&gt; every time they need the stack."&lt;/p&gt;

&lt;p&gt;"Inside that Per-CPU area pointed to by GS, there's a structure—often called &lt;code&gt;pcpu_hot&lt;/code&gt;. The kernel stores a direct copy of the 'top of the stack' right there, just bytes away from the task pointer.&lt;/p&gt;

&lt;p&gt;When a &lt;code&gt;syscall&lt;/code&gt; triggers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The CPU is still on the User Stack (&lt;code&gt;RSP&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The kernel runs &lt;code&gt;swapgs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It immediately executes &lt;code&gt;mov rsp, gs:[0x00]&lt;/code&gt; (or whatever the stack shortcut offset is).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In one instruction, the kernel is on the correct stack. It never even had to touch the &lt;code&gt;task_struct&lt;/code&gt; to find it. Because this data is accessed constantly, it almost always lives in the &lt;strong&gt;L1 Cache&lt;/strong&gt;. It’s nearly as fast as a physical register."&lt;/p&gt;




&lt;h3&gt;
  
  
  The Great Teleportation: How Context Switching Actually Works
&lt;/h3&gt;

&lt;p&gt;"Okay," Leo said, leaning in. "So we have the pointers. But how does the scheduler actually &lt;em&gt;stop&lt;/em&gt; Task A and &lt;em&gt;start&lt;/em&gt; Task B? How does Task B know where it left off?"&lt;/p&gt;

&lt;p&gt;Marcus cleared his throat, warming up to the narrative. "This is the 'Save Game' trick. Think of a context switch as a 'handover.' When the scheduler decides to switch, it calls a function named &lt;code&gt;__switch_to()&lt;/code&gt;. This is where the magic happens."&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Freezing Task A
&lt;/h4&gt;

&lt;p&gt;Before Task A is moved aside, the kernel must 'freeze' its state. It pushes the current registers—&lt;code&gt;RBX&lt;/code&gt;, &lt;code&gt;RBP&lt;/code&gt;, and others onto Task A's own kernel stack. The very last thing it does is save the current &lt;code&gt;RSP&lt;/code&gt; (the stack pointer) into Task A's &lt;code&gt;task_struct&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. The RSP Swap
&lt;/h4&gt;

&lt;p&gt;"Now comes the moment of teleportation," Marcus said, mimicking a switch flip with his hand. "The scheduler loads the address of Task B. It takes the stack pointer that Task B saved the &lt;em&gt;last&lt;/em&gt; time it was frozen and moves it into the actual &lt;code&gt;RSP&lt;/code&gt; register."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# rax = Task B's task_struct
mov rsp, [rax + stack_offset]  # THE SWITCH: rsp now points to Task B's stack!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"The second that instruction executes, the CPU is no longer looking at Task A’s history. It is looking at Task B’s stack."&lt;/p&gt;




&lt;h3&gt;
  
  
  The Layered Timeline: Why the Stack is a Time Machine
&lt;/h3&gt;

&lt;p&gt;Leo looked puzzled. "But how does Task B know what to do next? Does the scheduler have to jump to a specific instruction?"&lt;/p&gt;

&lt;p&gt;"That’s the beauty of it," Marcus replied. "The scheduler doesn't 'jump.' It &lt;strong&gt;returns&lt;/strong&gt;. You see, every task follows the same ritual to go to sleep, so they all know how to wake up. A task’s kernel stack is a perfectly preserved timeline with two layers."&lt;/p&gt;

&lt;h4&gt;
  
  
  The Two Layers:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Layer 1 (The Trap Frame):&lt;/strong&gt; This is the &lt;strong&gt;User State&lt;/strong&gt;. It’s at the very bottom of the stack. It contains the User &lt;code&gt;RIP&lt;/code&gt; (where the app was in its own code) and the User &lt;code&gt;RSP&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer 2 (The Context):&lt;/strong&gt; This is the &lt;strong&gt;Kernel State&lt;/strong&gt;. It contains the registers the task was using &lt;em&gt;inside&lt;/em&gt; the kernel just before it was switched out.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;"Because the stack is &lt;strong&gt;First-In, Last-Out (FILO)&lt;/strong&gt;, the task just travels backward through its own history.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It pops the kernel registers (restoring its 'Kernel Self').&lt;/li&gt;
&lt;li&gt;It executes the &lt;code&gt;ret&lt;/code&gt; instruction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, here is the secret: The &lt;code&gt;ret&lt;/code&gt; instruction pops the top value of the stack into the &lt;code&gt;RIP&lt;/code&gt; (Instruction Pointer). Since Task B was frozen during a function call, the top of its stack contains the 'return address',the exact line of code following the switch. It literally 'returns' into its own past."&lt;/p&gt;




&lt;h3&gt;
  
  
  The Final Piece: The Kernel RIP
&lt;/h3&gt;

&lt;p&gt;"Wait," Leo interrupted, "so the Kernel &lt;code&gt;RIP&lt;/code&gt; is never explicitly saved with a &lt;code&gt;mov&lt;/code&gt; command?"&lt;/p&gt;

&lt;p&gt;"Exactly!" Marcus clapped his hands. "When the code calls &lt;code&gt;__switch_to&lt;/code&gt;, the &lt;code&gt;call&lt;/code&gt; instruction &lt;em&gt;automatically&lt;/em&gt; pushes the next &lt;code&gt;RIP&lt;/code&gt; onto the stack as a bookmark. Then, when the task wakes up later and hits &lt;code&gt;ret&lt;/code&gt;, it simply picks up that bookmark and continues.&lt;/p&gt;

&lt;p&gt;Once the kernel finishes its work, it executes a final &lt;code&gt;sysret&lt;/code&gt; or &lt;code&gt;iretq&lt;/code&gt;. This pops &lt;strong&gt;Layer 1&lt;/strong&gt;,the Trap Frame.restoring the original User &lt;code&gt;RIP&lt;/code&gt; and &lt;code&gt;RSP&lt;/code&gt;. The CPU is suddenly back in the user application, exactly where it left off, unaware that it was ever frozen."&lt;/p&gt;

&lt;p&gt;Marcus stood up and headed toward the coffee machine. "The stack isn't just memory, Leo. It’s a timeline. As long as you keep the &lt;code&gt;RSP&lt;/code&gt; and the &lt;code&gt;GS&lt;/code&gt; base pointed at the right spots, the CPU will always know exactly who it is and what it was doing."&lt;/p&gt;

&lt;p&gt;Leo turned back to his monitors, the assembly code finally looking less like a wall of text and more like a carefully choreographed dance.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Blueprint: &lt;code&gt;struct pcpu_hot&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In modern kernels, it looks like this. Notice how &lt;code&gt;current_task&lt;/code&gt; and &lt;code&gt;top_of_stack&lt;/code&gt; are right at the top for maximum speed."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;pcpu_hot&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* The current running task_struct */&lt;/span&gt;
            &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;task_struct&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="cm"&gt;/* The top of the kernel stack for the current task */&lt;/span&gt;
            &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;       &lt;span class="n"&gt;top_of_stack&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="cm"&gt;/* Used for user/kernel transition (GS base swap) */&lt;/span&gt;
            &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;       &lt;span class="n"&gt;user_stack_ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="cm"&gt;/* ... other high-frequency data ... */&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="n"&gt;u8&lt;/span&gt;  &lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="cm"&gt;/* Padded to a full cache line */&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>linux</category>
      <category>c</category>
      <category>assembly</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>SLIs, SLOs, SLAs: The Guide to SRE’s Secret Sauce</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Wed, 11 Feb 2026 01:53:56 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/slis-slos-slas-the-guide-to-sres-secret-sauce-53bh</link>
      <guid>https://forem.com/bhushitha_hashan/slis-slos-slas-the-guide-to-sres-secret-sauce-53bh</guid>
      <description>&lt;p&gt;If you ever wanna be an SRE, a real &lt;strong&gt;site reliability wizard&lt;/strong&gt;, you gotta speak the language of the freakin’ trade. And that language? It ain’t “install Prometheus” or “deploy Kubernetes.” Nah, bro. It’s &lt;strong&gt;SLIs, SLOs, SLAs, and Error Budgets&lt;/strong&gt;.The holy trinity of keeping shit alive and your boss off your ass.&lt;/p&gt;

&lt;p&gt;This is how &lt;strong&gt;real humans measure reliability&lt;/strong&gt;, and if you don’t get it, you’re just another person staring at CPU graphs wondering why the feed is broken.&lt;/p&gt;




&lt;h2&gt;
  
  
  SLIs : Service Level Indicators: The User’s Reality Check
&lt;/h2&gt;

&lt;p&gt;SLI is like your &lt;strong&gt;street-level gossip&lt;/strong&gt;. It tells you how your service is actually behaving from the &lt;strong&gt;user’s point of view&lt;/strong&gt;, not from some nerdy server graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples in tech-world:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How fast does your &lt;strong&gt;social media feed load&lt;/strong&gt; for a user? That’s your &lt;strong&gt;latency SLI&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;How many posts fail to load or error out? That’s your &lt;strong&gt;error rate SLI&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;How often is your API &lt;strong&gt;completely unavailable&lt;/strong&gt;? That’s your &lt;strong&gt;availability SLI&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice something? Users don’t give a flying fuck about CPU load, memory usage, or thread pools. That shit is irrelevant. &lt;strong&gt;SLIs are the numbers that matter to humans&lt;/strong&gt;. They’re your reality check.&lt;/p&gt;

&lt;p&gt;Think of SLIs as &lt;strong&gt;the pulse of your service&lt;/strong&gt;. When the pulse drops, shit’s about to hit the fan.&lt;/p&gt;




&lt;h2&gt;
  
  
  SLOs: The Chill Target You Actually Give a Damn About
&lt;/h2&gt;

&lt;p&gt;SLO stands for &lt;strong&gt;Service Level Objective&lt;/strong&gt;, but don’t get stuck on words. Think of it as &lt;strong&gt;the promise you make to yourself&lt;/strong&gt; about what’s acceptable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples distributed here:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;99.9% of requests to your &lt;strong&gt;checkout API&lt;/strong&gt; should complete in under 500ms.&lt;/li&gt;
&lt;li&gt;99% of posts in the social media feed should load correctly on the first try.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s not perfection. That’s &lt;strong&gt;“good enough”&lt;/strong&gt;, and here’s the kicker: &lt;strong&gt;perfect is stupidly expensive&lt;/strong&gt;. Trying to hit 100% uptime is like promising every post loads instantly no matter the traffic spike. Chill. Nobody cares about perfection; SREs care about &lt;strong&gt;manageable reliability&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  SLAs: The Contract With Your Customers (aka The Lawyers Show Up)
&lt;/h2&gt;

&lt;p&gt;SLAs are where shit gets legal. Service Level Agreement. It’s what you promise to your &lt;strong&gt;paying users&lt;/strong&gt;, and if you fail, they can &lt;strong&gt;demand refunds or penalties&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples distributed here:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“If checkout API availability drops below 99.5% in a month, we refund the transaction fee.”&lt;/li&gt;
&lt;li&gt;“If social media feed errors exceed 0.5% for the month, we compensate premium users.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SLAs are basically &lt;strong&gt;the adult version of your SLOs&lt;/strong&gt;, but now lawyers are watching. Your internal metrics (SLIs, SLOs) are tools to &lt;strong&gt;avoid SLA violations&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Error Budget: How Much  Failure is Allowed
&lt;/h2&gt;

&lt;p&gt;Here’s where the genius of SRE shines. Every SLO comes with an &lt;strong&gt;error budget&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: Your SLO says &lt;strong&gt;99.9% of checkout requests &amp;lt; 500ms&lt;/strong&gt;. That means &lt;strong&gt;0.1% of requests can fail&lt;/strong&gt; before you’re in trouble. That 0.1% is your &lt;strong&gt;error budget&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Error budgets aren’t just numbers,they are &lt;strong&gt;decision-making tools&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hit your error budget? Stop risky deployments. Calm the hell down.&lt;/li&gt;
&lt;li&gt;Well within your error budget? Go ahead, push that new feature. Risk it, baby.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Error budgets let you &lt;strong&gt;balance velocity with reliability&lt;/strong&gt;. You stop firefighting everything, and you start &lt;strong&gt;deploying smartly&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Analogy: Think Like the User, Not the Server
&lt;/h2&gt;

&lt;p&gt;Here’s the core truth:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SLI = how fucked is it right now?&lt;/strong&gt;&lt;br&gt;
Users care about feed failing, checkout slowing, API errors. That’s your SLI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SLO = how fucked is okay?&lt;/strong&gt;&lt;br&gt;
“I can survive a few mistakes.” Maybe 1 in 1,000 API requests fail. That’s your SLO.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Budget = how much failure I can tolerate before flipping out&lt;/strong&gt;&lt;br&gt;
If you exceed it, shit hits the fan internally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SLA = how much messing arround can I get sued?&lt;/strong&gt;&lt;br&gt;
Customers will hammer you legally if you break it. That’s your SLA.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why You Give a Damn as an SRE
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You &lt;strong&gt;measure first&lt;/strong&gt;, fix second.&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;don’t chase metrics&lt;/strong&gt; that users can’t feel. CPU spikes are irrelevant. Latency and error rates are everything.&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;accept failures&lt;/strong&gt;. Shit breaks, but you have an &lt;strong&gt;error budget&lt;/strong&gt; to survive and deploy fast.&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;automate prevention&lt;/strong&gt;, because repeating firefighting is for suckers.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sre</category>
      <category>sysad</category>
      <category>analytics</category>
      <category>devops</category>
    </item>
    <item>
      <title>Linux Privileges:Peeling Back the Curtain Of How Linux Really Handles Users, Privileges, and Processes</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Fri, 06 Feb 2026 06:54:57 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/linux-privilegespeeling-back-the-curtain-of-how-linux-really-handles-users-privileges-and-3l6n</link>
      <guid>https://forem.com/bhushitha_hashan/linux-privilegespeeling-back-the-curtain-of-how-linux-really-handles-users-privileges-and-3l6n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;On how Linux really handle privileges on processes has always felt like a black box to me. You type a command, and sometimes the system says “permission denied,” sometimes “okay, you’re root now,” and you shrug. You think it’s magic. But today, after spending hours staring into &lt;code&gt;/proc&lt;/code&gt;, reading &lt;code&gt;task_struct&lt;/code&gt;, tracing &lt;code&gt;execve()&lt;/code&gt;, and watching UIDs dance around, I finally see what’s really happening. Linux isn’t magic at all it’s mechanical, almost brutally logical.simple yet powerfull and perfect. Every privilege, every setuid program, every &lt;code&gt;sudo&lt;/code&gt; call, every login shell is enforced in code. No luck, no wizardry just a lot of careful kernel work.&lt;/p&gt;

&lt;p&gt;I’m going to break it all down. Strap in.&lt;/p&gt;




&lt;h2&gt;
  
  
  UIDs: The Kernel Doesn’t Give a Damn About Names
&lt;/h2&gt;

&lt;p&gt;Okay, now, let me catch your thought: “wait, but what about &lt;code&gt;/etc/passwd&lt;/code&gt; and usernames?” Yeah, I get you. That’s the trap most people fall into. The kernel does &lt;strong&gt;not care&lt;/strong&gt; about your username. Zero. The kernel only cares about numbers: UIDs and GIDs. That’s it.&lt;/p&gt;

&lt;p&gt;Every process has a &lt;code&gt;task_struct&lt;/code&gt;. Inside that is a &lt;code&gt;cred&lt;/code&gt; struct that tracks all the UIDs and GIDs relevant to the process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;cred&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;kuid_t&lt;/span&gt; &lt;span class="n"&gt;ruid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Real UID: the user who launched the process&lt;/span&gt;
    &lt;span class="n"&gt;kuid_t&lt;/span&gt; &lt;span class="n"&gt;euid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Effective UID: what you can actually do right now&lt;/span&gt;
    &lt;span class="n"&gt;kuid_t&lt;/span&gt; &lt;span class="n"&gt;suid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Saved UID: what you can regain if you drop privileges temporarily&lt;/span&gt;
    &lt;span class="n"&gt;kgid_t&lt;/span&gt; &lt;span class="n"&gt;rgid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Real GID&lt;/span&gt;
    &lt;span class="n"&gt;kgid_t&lt;/span&gt; &lt;span class="n"&gt;egid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Effective GID&lt;/span&gt;
    &lt;span class="n"&gt;kgid_t&lt;/span&gt; &lt;span class="n"&gt;sgid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Saved GID&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ruid (Real UID):&lt;/strong&gt; Think of it like your “birth certificate” in Linux.its who spawned you. This almost never changes unless a privileged syscall explicitly allows it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;euid (Effective UID):&lt;/strong&gt; This is what the kernel actually checks for privileges. Want to open &lt;code&gt;/etc/shadow&lt;/code&gt;? Kernel checks this. Want to bind port 80? Kernel checks this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;suid (Saved UID):&lt;/strong&gt; This is your “back door” to regain privileges you temporarily dropped. I’ll show why this matters with setuid programs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; The kernel is the boss. Userspace tools like &lt;code&gt;sudo&lt;/code&gt; or &lt;code&gt;su&lt;/code&gt; just orchestrate things.the kernel is the one making all the actual decisions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setuid: Privilege Already Baked Before You Touch Anything
&lt;/h2&gt;

&lt;p&gt;Next up, the setuid. That infamous &lt;code&gt;+s&lt;/code&gt; bit. This is literally the kernel saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“When this program runs, I’m going to temporarily treat it as if it belongs to the file owner, not the person executing it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let me break it down. You have &lt;code&gt;/usr/bin/passwd&lt;/code&gt; (owned by root, setuid). When &lt;code&gt;alice&lt;/code&gt; runs it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ruid = 1000 (alice)
euid = 0    (root)
suid = 0    (root)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, look closely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ruid&lt;/code&gt; stays alice —&amp;gt; she is still herself.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;euid&lt;/code&gt; is root —&amp;gt; kernel checks this for every privileged syscall.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;suid&lt;/code&gt; is root —&amp;gt; the “return ticket” if alice temporarily drops privileges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, the saved UID exists because &lt;strong&gt;without it, once you drop privileges, you could never regain them&lt;/strong&gt;. That’s the entire point.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dropping and Regaining Privileges Safely
&lt;/h2&gt;

&lt;p&gt;Setuid programs don’t just run full power the entire time cause that would be insane. They often drop privileges temporarily while doing risky stuff. Then, when needed, they regain them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;seteuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// drop privileges&lt;/span&gt;
&lt;span class="c1"&gt;// do unprivileged work&lt;/span&gt;
&lt;span class="n"&gt;seteuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// regain privileges&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Timeline (simplified):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Execve setuid-root:
ruid=alice  euid=root  suid=root

Drop privileges:
seteuid(ruid)
ruid=alice  euid=alice  suid=root

Regain privileges:
seteuid(suid)
ruid=alice  euid=root  suid=root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;strong&gt;suid never changes&lt;/strong&gt; when you temporarily switch euid. It’s a fixed “return ticket.”&lt;/p&gt;




&lt;h2&gt;
  
  
  When Setuid Is Not Set
&lt;/h2&gt;

&lt;p&gt;Now, let’s be clear: if a file &lt;strong&gt;doesn’t have &lt;code&gt;+s&lt;/code&gt;&lt;/strong&gt;, the kernel does something simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ruid = caller UID
euid = caller UID
suid = caller UID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing magical. You can’t elevate yourself arbitrarily. Only root (or a setuid-root binary) can raise privileges.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rules of Privilege Escalation
&lt;/h2&gt;

&lt;p&gt;Now, now, I know what you’re thinking: “so, only root can become anyone else, right?” Exactly. Let’s spell it out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;euid=0 (root):&lt;/strong&gt; can change ruid/euid/suid to anything. Full control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normal users:&lt;/strong&gt; can only &lt;strong&gt;lower privileges&lt;/strong&gt; (drop euid). No raising to someone else’s UID.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setuid files:&lt;/strong&gt; allow a controlled, kernel-enforced elevation to the file owner’s UID.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ruid:&lt;/strong&gt; almost immutable; it’s your original identity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User1: UID 1001
User2: UID 1002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;User1 cannot become 1002.&lt;/li&gt;
&lt;li&gt;User2 cannot become 1001.&lt;/li&gt;
&lt;li&gt;Only root could switch to either.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Login Shells and TTYs: The “Fall From Grace”
&lt;/h2&gt;

&lt;p&gt;Alright, now I know exactly what you’re thinking if u read it till now,: “if the ruid is the one who start the process,who the hell owns the TTY I log in to?” Let me untangle this.&lt;/p&gt;

&lt;p&gt;Before you log in, every virtual terminal (VTY) is essentially owned by &lt;strong&gt;root&lt;/strong&gt;. That’s right,before login, you are like an all-powerful god sitting in &lt;code&gt;/dev/tty1…6&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then systemd or init starts &lt;code&gt;getty&lt;/code&gt; (or &lt;code&gt;agetty&lt;/code&gt;), which listens for login attempts. &lt;code&gt;getty&lt;/code&gt; itself is root-owned. it has to be, because it’s going to spawn login shells, check passwords, and eventually drop privileges safely.&lt;/p&gt;

&lt;p&gt;When you finally log in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;login&lt;/code&gt; verifies your credentials&lt;/li&gt;
&lt;li&gt;then spawns your &lt;strong&gt;login shell&lt;/strong&gt; (bash, zsh, whatever)&lt;/li&gt;
&lt;li&gt;and suddenly you &lt;strong&gt;fall from grace&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ruid = your UID
euid = your UID
suid = your UID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Haha, right? All-powerful god → mortal user in one instant. This is why root privileges are tightly controlled: you can’t just pick up random UIDs at will. The kernel enforces this rigorously.&lt;br&gt;
here check this image ive attached below if u still find this tty thing confusing..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqtna637l6z4e2ygp7b0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqtna637l6z4e2ygp7b0.png" alt=" " width="419" height="927"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;code&gt;sudo&lt;/code&gt;, &lt;code&gt;su&lt;/code&gt;, and Variants
&lt;/h2&gt;

&lt;p&gt;Here’s the part most people misunderstand: &lt;code&gt;sudo&lt;/code&gt; and &lt;code&gt;su&lt;/code&gt; aren’t magical at all they’re &lt;strong&gt;setuid-root programs&lt;/strong&gt; that orchestrate privilege elevation under kernel rules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;sudo:&lt;/strong&gt; Runs as root (setuid), checks &lt;code&gt;/etc/sudoers&lt;/code&gt;, then temporarily switches euid to root for your command.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sudo -i:&lt;/strong&gt; Starts an interactive root shell (&lt;code&gt;euid=0&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;su:&lt;/strong&gt; Switch user; requires root privileges to switch to another user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;su -:&lt;/strong&gt; Switch user and simulate login environment (&lt;code&gt;PATH&lt;/code&gt;, environment variables, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without the kernel enforcing UIDs, all of this would be meaningless. When you run &lt;code&gt;sudo&lt;/code&gt;, the kernel sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ruid = original user
euid = root (because sudo binary is setuid-root)
suid = root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And everything is &lt;strong&gt;checked at the syscall level&lt;/strong&gt;. Permissions aren’t faked.they are real.&lt;/p&gt;




&lt;h2&gt;
  
  
  Process Startup: Everything Happens in Order
&lt;/h2&gt;

&lt;p&gt;Timeline, kernel-first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent calls execve(path, argv, envp)
    ↓
Kernel checks permissions, filesystem flags, LSM
    ↓
Kernel sets credentials (ruid, euid, suid) → includes setuid handling
    ↓
Kernel loads ELF segments into memory
    ↓
Kernel builds stack with argc, argv, envp, auxv
    ↓
Kernel switches to user mode at _start
    ↓
C runtime extracts argc, argv, envp
    ↓
main(argc, argv, envp) runs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key point: &lt;strong&gt;credentials are applied before the environment exists&lt;/strong&gt;, before the program executes a single instruction, and before it can touch syscalls. That’s why setuid works safely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mental Model
&lt;/h2&gt;

&lt;p&gt;Think of Linux privileges like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;execve()          → kernel enforces creds (ruid/euid/suid)
   ↓
ELF loaded, stack built (argc/argv/envp)
   ↓
_enter_user_mode()
   ↓
C runtime sets up main()
   ↓
program executes, syscalls checked against euid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setuid program:&lt;/strong&gt; ruid = caller, euid = file owner, suid = file owner&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normal program:&lt;/strong&gt; ruid = euid = suid = caller&lt;/li&gt;
&lt;li&gt;Drop privileges temporarily → regain via suid → safe privilege handling&lt;/li&gt;
&lt;li&gt;Only root or setuid-root binaries can elevate euid arbitrarily&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Once you understand this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sudo&lt;/code&gt;, &lt;code&gt;su&lt;/code&gt;, login shells, daemons, and setuid-root programs stop being mysterious.&lt;/li&gt;
&lt;li&gt;Everything funnels down to &lt;strong&gt;kernel-enforced credentials&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Understanding ruid/euid/suid, setuid, and process startup explains why Linux is secure and why miswritten setuid programs are a security nightmare.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Linux isn’t magic. It’s just &lt;strong&gt;mechanical, precise, and enforced at every step&lt;/strong&gt;. Once you see it, everything clicks.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>sre</category>
      <category>c</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Wild Ride from Raw Syscalls to Figuring Out NSS and libc</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Wed, 04 Feb 2026 07:27:24 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/wild-ride-from-raw-syscalls-to-figuring-out-nss-and-libc-14li</link>
      <guid>https://forem.com/bhushitha_hashan/wild-ride-from-raw-syscalls-to-figuring-out-nss-and-libc-14li</guid>
      <description>&lt;p&gt;Man, I’ve always had this nerdy obsession with Linux. From day one, I was diving headfirst into the kernel, writing tiny tools using &lt;strong&gt;raw syscalls&lt;/strong&gt;,basically skipping libc entirely and talking to the kernel like a badass. I made my own headers, wrote my own print routines, opened directories using &lt;code&gt;getdents64&lt;/code&gt;, parsed &lt;code&gt;/proc&lt;/code&gt; for processes… basically living dangerously in the kernel’s backyard.&lt;/p&gt;

&lt;p&gt;At the time, I thought I was the shit doing everything “the real way.” And yeah, it worked. But what I didn’t realize was that I was skipping a &lt;strong&gt;whole layer of sanity&lt;/strong&gt; that exists in libc. I had no idea about all the stuff it actually does. All the buffering, human-readable formatting, and things that make life not completely painful.&lt;/p&gt;




&lt;h2&gt;
  
  
  That WTF Moment: &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Everything hit me when I stumbled upon &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; while poking around network and user stuff. I opened it and literally went:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What the actual hell is this? Who the fuck uses this? Isn’t the kernel supposed to know this?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It was super confusing. I was in full raw syscall mode, so the idea that some &lt;strong&gt;config file&lt;/strong&gt; could tell libc how to handle &lt;code&gt;getpwnam()&lt;/code&gt; or &lt;code&gt;getaddrinfo()&lt;/code&gt; blew my mind. I had no clue why this “signboard” was even necessary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Okay, Now NSS Makes Sense
&lt;/h2&gt;

&lt;p&gt;Turns out, &lt;strong&gt;NSS = Name Service Switch&lt;/strong&gt;. And yeah, it’s basically a &lt;strong&gt;signboard inside libc&lt;/strong&gt; telling it where the hell to look for information.&lt;/p&gt;

&lt;p&gt;When a program calls something like &lt;code&gt;getpwuid()&lt;/code&gt; or &lt;code&gt;getpwnam()&lt;/code&gt;, it’s asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Who is this user? What’s their username?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s the thing: the kernel &lt;strong&gt;doesn’t know usernames&lt;/strong&gt;, it only knows numeric IDs, like &lt;code&gt;UID = 1000&lt;/code&gt;. That’s where libc + NSS swoop in like superheroes.&lt;/p&gt;




&lt;h3&gt;
  
  
  How It Actually Works
&lt;/h3&gt;

&lt;p&gt;Say you call &lt;code&gt;getpwnam("Deadpool")&lt;/code&gt;. libc does this:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Read &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Finds the line for users:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; passwd: files systemd
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This basically says:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, check local files (&lt;code&gt;/etc/passwd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Then, ask systemd’s dynamic user database&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;2.&lt;strong&gt;Call each NSS module in order&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First: &lt;code&gt;libnss_files.so.2&lt;/code&gt; → looks in &lt;code&gt;/etc/passwd&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Found? Cool → return result&lt;/li&gt;
&lt;li&gt;Not found? Keep going&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Second: &lt;code&gt;libnss_systemd.so.2&lt;/code&gt; → ask systemd&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Found? Sweet → return result&lt;/li&gt;
&lt;li&gt;Not? Continue to next source if any&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;3.&lt;strong&gt;Return a &lt;code&gt;struct passwd&lt;/code&gt;&lt;/strong&gt; to your program&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full info: username, UID, GID, home dir, shell, all the juicy stuff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; NSS itself is &lt;strong&gt;not a running program&lt;/strong&gt;, just a config file + shared libraries. libc calls them dynamically, no extra processes involved.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Secret Sauce: libc Beyond Raw Syscalls
&lt;/h2&gt;

&lt;p&gt;Here’s something I didn’t realize at first: &lt;strong&gt;libc is more than just a syscall wrapper&lt;/strong&gt;. Sure, it wraps syscalls like &lt;code&gt;write&lt;/code&gt;, &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;getpid&lt;/code&gt;, etc., but it also adds &lt;strong&gt;a ton of extra sauce&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Buffering and formatting&lt;/strong&gt;: &lt;code&gt;printf&lt;/code&gt;, &lt;code&gt;fopen&lt;/code&gt; buffers, &lt;code&gt;getline&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory management&lt;/strong&gt;: &lt;code&gt;malloc&lt;/code&gt;, &lt;code&gt;free&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Threading support&lt;/strong&gt;: &lt;code&gt;pthread_*&lt;/code&gt; functions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy and lookup logic&lt;/strong&gt;: NSS modules, locale, hostname resolution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without NSS, this extra sauce works partially:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syscalls themselves still happen correctly (you can &lt;code&gt;open&lt;/code&gt; files, &lt;code&gt;read&lt;/code&gt; directories, &lt;code&gt;write&lt;/code&gt; to stdout)&lt;/li&gt;
&lt;li&gt;Buffering, formatting, memory, threading still works&lt;/li&gt;
&lt;li&gt;But &lt;strong&gt;any function that needs human-readable names&lt;/strong&gt; (users, groups, hosts, services) would &lt;strong&gt;fail or return NULL&lt;/strong&gt;, because libc has no map to tell it where to look&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  NSS Modules Still Use Syscalls Under the Hood
&lt;/h3&gt;

&lt;p&gt;Here’s the other thing that clicked the perfect image on my mind: &lt;strong&gt;even NSS modules themselves ultimately use syscalls&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For example, &lt;code&gt;libnss_files.so.2&lt;/code&gt; reads &lt;code&gt;/etc/passwd&lt;/code&gt; using &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;close&lt;/code&gt; (syscalls).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;libnss_systemd.so.2&lt;/code&gt; talks to the systemd service using IPC syscalls.&lt;/li&gt;
&lt;li&gt;So everything still hits the kernel eventually the NSS just &lt;strong&gt;adds a layer of logic&lt;/strong&gt; so libc knows &lt;strong&gt;where&lt;/strong&gt; and &lt;strong&gt;how&lt;/strong&gt; to get the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, libc + NSS = fancy middleware. Raw syscalls = truth. NSS just gives meaning to that truth and ensures humans don’t see useless numbers.&lt;/p&gt;




&lt;h2&gt;
  
  
  How This Hit Me
&lt;/h2&gt;

&lt;p&gt;Before this epiphany, my tools were like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open directories with &lt;code&gt;getdents64&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Read &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/status&lt;/code&gt; → get numeric UIDs&lt;/li&gt;
&lt;li&gt;Display numbers only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which is perfectly fine if you just want raw truth. But it’s &lt;strong&gt;boring for humans&lt;/strong&gt;. Humans want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PID: 742   User: Deadpool   Process: bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PID: 742   UID: 1000   Process: bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NSS basically &lt;strong&gt;translates truth into meaning&lt;/strong&gt;, and it’s libc that does all the heavy lifting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layers of the System (Mental Picture)
&lt;/h2&gt;

&lt;p&gt;Here’s how it finally clicked for me:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjx8gt0k6wgqo80am9wb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjx8gt0k6wgqo80am9wb.png" alt=" " width="676" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some key nuggets I learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;libc does way more than syscalls&lt;/strong&gt; its buffering, formatting, threading, memory, and yes, NSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NSS is optional&lt;/strong&gt; if you only need numbers, but humans will hate your output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Systemd has a dynamic user database&lt;/strong&gt; for service and container users, which NSS can query&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raw syscalls = truth, NSS = meaning&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Reflection
&lt;/h2&gt;

&lt;p&gt;Real talk: this was a &lt;strong&gt;big “oh shit” moment&lt;/strong&gt;. I realized that all my badass low level tools were cool, but they weren’t really “user-friendly” or system aware. I had been skipping an entire ecosystem of userspace logic.&lt;/p&gt;

&lt;p&gt;Now, I see the value in combining both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raw syscalls → to understand the kernel and ABIs like a boss&lt;/li&gt;
&lt;li&gt;libc + NSS → to make tools that are readable, robust, and actually useful&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The One-Liner to Finalize It
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;“Syscalls give you the raw truth; NSS gives libc the damn map to turn that truth into something humans can actually understand.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;This journey taught me not just &lt;strong&gt;how Linux works&lt;/strong&gt;, but also &lt;strong&gt;how to think in layers&lt;/strong&gt;: kernel, ABI, libc, NSS, and human-readable output.&lt;/p&gt;

&lt;p&gt;And now, whenever I build a tool, I don’t just make it work, I know &lt;em&gt;why&lt;/em&gt; it works, what layer is doing what, and how the pieces actually fit together.&lt;/p&gt;




</description>
      <category>c</category>
      <category>linux</category>
      <category>x86</category>
      <category>sre</category>
    </item>
    <item>
      <title>API Demystified: From Confusion to Confidence</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Sat, 30 Aug 2025 08:17:30 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/api-demystified-from-confusion-to-confidence-4apb</link>
      <guid>https://forem.com/bhushitha_hashan/api-demystified-from-confusion-to-confidence-4apb</guid>
      <description>&lt;p&gt;Ok today let’s talk about &lt;strong&gt;API&lt;/strong&gt;. what the fuck is it, what makes a &lt;strong&gt;good&lt;/strong&gt; API, and why APIs have become such a hot topic that even non-tech folks have to care about it.&lt;/p&gt;

&lt;p&gt;so when i first came across the word API, it felt like some weird nuance.I kinda knew what it was, but if someone actually asked me “what’s an API?” … bruh, i’d stumble. yeah i could spit out an answer, but it didn’t feel like it came from me. i wasn’t confident, i wasn’t comfortable.&lt;/p&gt;

&lt;p&gt;and if you feel the same, if you’re not fully comfy around APIs,then this one’s for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  what even is an API?
&lt;/h2&gt;

&lt;p&gt;first things first: when we google or ask around, answers about APIs sound different. some say “it’s a well-defined interface where two software applications talk to each other.” others say “it’s a contract, not just technology.”&lt;/p&gt;

&lt;p&gt;so… who’s right? actually both.&lt;/p&gt;

&lt;p&gt;umm, how do i paint this picture so it sticks?&lt;/p&gt;

&lt;p&gt;right!! imagine going to a restaurant. you get a menu. now, this menu shows you exactly what you can order. you can’t just order stuff outside of it. this is like a well-defined interface: you’re shown your options, you don’t need to run into the kitchen asking around. the menu already gives you the “what’s possible.”&lt;/p&gt;

&lt;p&gt;now, when you order pasta, you expect pasta. if the waiter brings you rice and curry? chaos. you’d be confused, maybe pissed.&lt;/p&gt;

&lt;p&gt;see the parallel? the restaurant gave us a menu aka &lt;strong&gt;the API&lt;/strong&gt;. the menu tells us what’s possible and what we can expect. and we as customers expect the restaurant to actually deliver what we asked for. that’s the &lt;strong&gt;contract&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;so yeah..an API is both things: a &lt;strong&gt;well-defined interface&lt;/strong&gt; &lt;em&gt;and&lt;/em&gt; a &lt;strong&gt;contract between provider and receiver&lt;/strong&gt;. a good API checks both boxes.&lt;/p&gt;




&lt;h2&gt;
  
  
  ok, cool now, but what makes an API “good”?
&lt;/h2&gt;

&lt;p&gt;now you got the picture of what an api is. not super detailed yet, but enough of a mental image to explore deeper.&lt;/p&gt;

&lt;p&gt;and here’s where people usually stumble: most of us aren’t actually designing APIs, we’re just &lt;em&gt;using&lt;/em&gt; them. when we build apps or functions, we just consume APIs,our focus is on what we are building.And because of that, we don’t notice or pay much attention to think about the design or structure of the api we use or appreciate it. so when someone asks “what makes a good API?” we blank.&lt;/p&gt;

&lt;p&gt;but here’s the shift: &lt;strong&gt;think of an API as a software product.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;when we hear “software product,” what pops in mind? specifications,backward compatibility, availability and things that relying on it, downtime is a nightmare, versioning and finally ability to evolve.&lt;/p&gt;

&lt;p&gt;guess what? same rules apply to APIs.&lt;/p&gt;

&lt;p&gt;so, a well-defined API has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a clear specification&lt;/li&gt;
&lt;li&gt;a solid contract  and it &lt;em&gt;sticks&lt;/em&gt; to it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and here’s the thing: with humans, contracts can be flexible. you order pasta, they mistakenly bring curry, you can call it out, they apologize, fix it.&lt;/p&gt;

&lt;p&gt;but software? nah. it’s strict. code doesn’t “understand” misunderstandings. if your API promises pasta, it better deliver pasta.&lt;/p&gt;

&lt;p&gt;that’s why a good API is all about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;contract discipline&lt;/strong&gt; → never betray what you promised&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;availability&lt;/strong&gt; → if your API is down half the time, who’ll use it?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;evolution without breaking shit&lt;/strong&gt; → business + tech are always moving. APIs need to evolve but still keep backward compatibility so current users don’t break.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;of course, sometimes we &lt;em&gt;can’t&lt;/em&gt; evolve without breaking old stuff. that’s where &lt;strong&gt;API versioning&lt;/strong&gt; comes in. when you can’t maintain backward compatibility, you roll out v2 (whether via URL versioning or headers). the old consumers keep working, while new ones move forward.&lt;/p&gt;

&lt;p&gt;so, a good API is a software product: reliable, backward-compatible when possible, and able to evolve without chaos.&lt;/p&gt;




&lt;h2&gt;
  
  
  API classifications (not what you think)
&lt;/h2&gt;

&lt;p&gt;so far you’re clear on what an API is and what makes it good. now let’s zoom out to classification.&lt;/p&gt;

&lt;p&gt;and no, i’m not talking about REST vs SOAP. those are styles. what i’m talking about is &lt;em&gt;different dimensions of classification&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;because APIs aren’t in one big hierarchy with one boss. instead, you can classify them by different aspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;by audience&lt;/strong&gt; → who uses it? public (anyone), private (internal only), or partner (shared with specific parties). the ones you usually meet are public APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;by access medium&lt;/strong&gt; → what domain it lives in. web API, library API, OS API, hardware API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;by communication style&lt;/strong&gt; → how the client talks and how data flows. could be REST (resources + HTTP verbs), GraphQL, or SOAP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;by package&lt;/strong&gt; → how it’s delivered. raw endpoint? SDK (ready-made lib)?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;by domain/use case&lt;/strong&gt; → what problem it solves. cloud API, payment API, social API, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aight so now you know that infact an single api can be classified under different dimensions and still fall under multiple categories the same time.&lt;/p&gt;




&lt;p&gt;sheesh!!that was a whole load of info right?&lt;/p&gt;

&lt;p&gt;but now, if someone asks you what an API is, you won’t just parrot some textbook line. you’ve got a full picture, with intuition.&lt;/p&gt;

&lt;p&gt;go through this a couple of times if you’re still not comfy.My goal isn’t to cram definitions in to your head instead it’s to have that natural, intuitive feel of “i know what an API really is.”&lt;/p&gt;

&lt;p&gt;so until we meet again ✌️&lt;/p&gt;

</description>
      <category>devops</category>
      <category>development</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What Happens When Code Runs Without an OS? Exploring CPU Execution, Memory, and Interrupts</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Sat, 14 Jun 2025 14:34:00 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/what-happens-when-code-runs-without-an-os-exploring-cpu-execution-memory-and-interrupts-do1</link>
      <guid>https://forem.com/bhushitha_hashan/what-happens-when-code-runs-without-an-os-exploring-cpu-execution-memory-and-interrupts-do1</guid>
      <description>&lt;p&gt;When writing code that runs without an operating system "bare-metal code", you're not dealing with the luxuries of system calls, drivers, or protected memory. You're dealing directly with the CPU and memory as they are. Understanding how the CPU &lt;em&gt;actually&lt;/em&gt; behaves in this state,how it executes, loops, crashes, and responds to interrupts is foundational for developers and systems programmers.&lt;/p&gt;

&lt;p&gt;Let’s break this down from the ground up.&lt;/p&gt;




&lt;h2&gt;
  
  
  Instruction Flow: The CPU Moves Forward By Default
&lt;/h2&gt;

&lt;p&gt;At its simplest, the CPU is a machine that fetches instructions from memory and executes them, one after another. This sequential behavior is driven by a special register: the &lt;strong&gt;Program Counter&lt;/strong&gt; (PC), or in x86, the &lt;strong&gt;Instruction Pointer&lt;/strong&gt; (IP).&lt;/p&gt;

&lt;p&gt;The Program Counter holds the address of the next instruction to execute. After executing an instruction, the CPU increases the PC to point to the following one. That’s how programs “move forward” .line by line, byte by byte.&lt;/p&gt;

&lt;p&gt;Example in x86 assembly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov eax, 5
add eax, 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After &lt;code&gt;mov&lt;/code&gt;, the PC is incremented, and it proceeds to &lt;code&gt;add&lt;/code&gt;. Unless told otherwise, the CPU just keeps marching forward.&lt;/p&gt;




&lt;h2&gt;
  
  
  Control Flow Is Yours: Loops, Jumps, Branches
&lt;/h2&gt;

&lt;p&gt;But that "forward march" isn’t locked in. Assembly provides full control of program flow through jump instructions (&lt;code&gt;jmp&lt;/code&gt;), function calls (&lt;code&gt;call&lt;/code&gt;), loops (&lt;code&gt;loop&lt;/code&gt;, &lt;code&gt;jnz&lt;/code&gt;, etc.), and conditional branches.&lt;/p&gt;

&lt;p&gt;For example, you can build a loop like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start:
  dec eax
  jnz start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code counts down from whatever value is in &lt;code&gt;eax&lt;/code&gt;, repeatedly jumping back to &lt;code&gt;start&lt;/code&gt; until &lt;code&gt;eax&lt;/code&gt; hits zero. You’ve created a backward loop, manually. The CPU isn't "thinking" in directions it's just following whatever address it's told to fetch next.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory Isn’t Sequential: You Can Reuse and Overwrite Freely
&lt;/h2&gt;

&lt;p&gt;The CPU also doesn't treat memory like a one-way street. It's just a flat space of addresses and you can write, erase, and jump around in it freely. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov [0x1000], eax    ; write eax to memory
mov eax, [0x1000]    ; read it back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s direct memory access. No protection, no guards unless you write them.&lt;/p&gt;

&lt;p&gt;You could even store instructions themselves in RAM and jump between them as needed. This lets you build dynamic code flows, jump tables, or even self-modifying code (if you're careful and a little daring).&lt;/p&gt;




&lt;h2&gt;
  
  
  Manual Loops Across Memory Locations
&lt;/h2&gt;

&lt;p&gt;You don’t even have to put your code in one spot. Here’s an example of a manual loop jumping between non-sequential locations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Assume:
; 0x0000: mov eax, 5
; 0x0003: jmp 0x0010
; ...
; 0x0010: add eax, 2
; 0x0013: jmp 0x0000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The CPU starts at &lt;code&gt;0x0000&lt;/code&gt;, sets &lt;code&gt;eax&lt;/code&gt; to 5,&lt;/li&gt;
&lt;li&gt;Jumps to &lt;code&gt;0x0010&lt;/code&gt;, adds 2 to &lt;code&gt;eax&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Jumps back to &lt;code&gt;0x0000&lt;/code&gt; — and loops.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This kind of manual control over memory and instruction flow is exactly how low-level systems work .The CPU is simply obeying pointers and doing what it’s told.&lt;/p&gt;




&lt;h2&gt;
  
  
  Crashes and CPU Chaos
&lt;/h2&gt;

&lt;p&gt;If you mess up and overwrite your instructions, jump to invalid memory, or create an infinite loop  there’s no safety net. No OS to save you. The CPU may freeze, reboot, or enter undefined behavior.&lt;/p&gt;

&lt;p&gt;Here’s an infinite loop that’ll run forever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start:
  jmp start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a more useful loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov al, 0
loop_start:
  inc al
  cmp al, 10
  jne loop_start
hlt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code counts from 0 to 9 and then halts the CPU. That &lt;code&gt;hlt&lt;/code&gt; instruction is essential  otherwise the CPU would just keep reading random memory and likely crash.&lt;/p&gt;




&lt;h2&gt;
  
  
  The CPU Never Stops ,Unless You Tell It To!!
&lt;/h2&gt;

&lt;p&gt;The CPU doesn’t know when to stop. It doesn’t assume your program ends after a few instructions. If you don’t explicitly stop it with &lt;code&gt;hlt&lt;/code&gt; or reset it via hardware, it just keeps going. It’ll execute whatever’s next — even if that means garbage data in RAM.&lt;/p&gt;

&lt;p&gt;This is why real-mode programs and BIOS routines are so strict about handling “what’s next.” In the absence of guardrails, everything is your responsibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interrupts Still there Even Without an OS
&lt;/h2&gt;

&lt;p&gt;Let’s take a deeper dive into interrupts. Yes, even with no OS at all, the hardware  like a keyboard or timer  can still fire interrupts.&lt;/p&gt;

&lt;p&gt;For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The keyboard fires &lt;strong&gt;IRQ1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The system timer fires &lt;strong&gt;IRQ0&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;These go to the &lt;strong&gt;Programmable Interrupt Controller&lt;/strong&gt; (PIC)&lt;/li&gt;
&lt;li&gt;The PIC forwards them to the CPU&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CPU, on receiving an interrupt, checks its &lt;strong&gt;Interrupt Vector Table (IVT)&lt;/strong&gt; to find the address of the relevant handler.&lt;/p&gt;

&lt;p&gt;But here's the catch: if you haven’t set that handler up, the CPU jumps into random memory. That’s an instant crash.&lt;/p&gt;




&lt;h2&gt;
  
  
  BIOS: The Unsung Hero of Early Execution
&lt;/h2&gt;

&lt;p&gt;During early boot, you're not completely alone.if BIOS is still active, it provides basic interrupt services. You can use them like functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov ah, 0
int 16h   ; BIOS keyboard input
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These BIOS interrupts work only in &lt;strong&gt;real mode&lt;/strong&gt;. As soon as you leave that mode or overwrite the handlers, you're on your own.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Interrupt Vector Table (IVT): What It Is and Where It Lives
&lt;/h2&gt;

&lt;p&gt;The IVT is a fixed table in low memory, from &lt;code&gt;0x0000&lt;/code&gt; to &lt;code&gt;0x03FF&lt;/code&gt;. It holds 256 entries, each 4 bytes (2 bytes offset + 2 bytes segment), mapping interrupt numbers to handler addresses.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;INT 0x09&lt;/code&gt; → CPU looks at &lt;code&gt;0x0024&lt;/code&gt; to &lt;code&gt;0x0027&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Reads the pointer there&lt;/li&gt;
&lt;li&gt;Jumps to that address to run the keyboard handler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The BIOS sets this up on boot, giving you basic services. But if you're writing your own OS or bootloader, you'll need to set your own IVT  and do it carefully.&lt;/p&gt;




&lt;h2&gt;
  
  
  RAM Is Empty at Power-On! So Where Does IVT Come From?
&lt;/h2&gt;

&lt;p&gt;RAM is volatile,and it holds nothing on startup. So how does the IVT get there?&lt;/p&gt;

&lt;p&gt;It’s written by the BIOS.&lt;/p&gt;

&lt;p&gt;Here’s what happens at power-on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Power is turned on&lt;/li&gt;
&lt;li&gt;The CPU begins executing at address &lt;code&gt;0xFFFF0&lt;/code&gt; — in ROM&lt;/li&gt;
&lt;li&gt;BIOS code runs:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Initializes RAM, screen, keyboard&lt;/li&gt;
&lt;li&gt;Writes the IVT into RAM&lt;/li&gt;
&lt;li&gt;Loads a bootloader (e.g., GRUB or your own code)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This boot process is precise and hardware specific. Without BIOS or UEFI, you’d have to manually write this entire sequence, including the IVT.&lt;/p&gt;




&lt;h2&gt;
  
  
  Disabling Interrupts With &lt;code&gt;CLI&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Until your IVT is ready, interrupts are dangerous. A timer or keyboard interrupt might fire and jump to uninitialized memory.&lt;/p&gt;

&lt;p&gt;To prevent this, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLI   ; Clear Interrupt Flag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It tells the CPU: “Ignore all hardware interrupts for now.”&lt;/p&gt;

&lt;p&gt;Later, once your handlers are in place, re-enable interrupts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STI   ; Set Interrupt Flag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This flow is critical when setting up your own OS kernel or bootloader interrupts must be carefully managed from the start.&lt;/p&gt;




&lt;h2&gt;
  
  
  You Can’t Use All of RAM Freely in Real Mode
&lt;/h2&gt;

&lt;p&gt;The IVT sits at &lt;code&gt;0x0000 – 0x03FF&lt;/code&gt;. That memory is off-limits unless you're replacing the table. Similarly, &lt;code&gt;0x0400 – 0x04FF&lt;/code&gt; is the BIOS Data Area  also reserved. And &lt;code&gt;0xA0000 – 0xBFFFF&lt;/code&gt; is often used for video memory. Writing into these areas without knowing their purpose will break things fast.&lt;/p&gt;

&lt;p&gt;Here's a rough map:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0x0000 – 0x03FF&lt;/code&gt;: IVT&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x0400 – 0x04FF&lt;/code&gt;: BIOS Data Area&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0xA0000 – 0xBFFFF&lt;/code&gt;: Video memory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0xF0000 – 0xFFFFF&lt;/code&gt;: BIOS ROM mapping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only areas outside these regions are safe, unless of cpurse you know exactly what you’re doing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts: The CPU Is Obedient, Not Intelligent
&lt;/h2&gt;

&lt;p&gt;The CPU has no opinion. It doesn’t know what a keyboard is, or what a loop is, or that you're trying to build an operating system. It obeys instructions, fetches bytes, and jumps wherever you tell it even into chaos.&lt;/p&gt;

&lt;p&gt;This is your playground.&lt;/p&gt;

&lt;p&gt;When you write bare-metal code, you’re writing the rules of the world. You’re building not just a program, but a miniature reality that the CPU inhabits it and it goes on until you tell it to stop.&lt;/p&gt;

&lt;p&gt;And that, right there, is the power of low-level programming.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;Diving into bare-metal programming feels like stepping into a new universe one where you control every bit and byte. This direct control is both thrilling and challenging because there’s no OS to hold your hand.&lt;/p&gt;

&lt;p&gt;If you're passionate about systems programming or OS development, you're not alone. I’m learning from scattered books, online resources, and AI assists.piecing it all together step by step. If there are passionate experts out there who care to offer guidance, share insight, or steer me in the right direction, feel free to reach out.&lt;/p&gt;

&lt;p&gt;And if you spot mistakes, oversights, or have corrections to offer, I genuinely welcome them . drop them in the comments. I’m here to learn, explore, and build this world from the ground up.&lt;/p&gt;

&lt;p&gt;References: OSDev.org&lt;br&gt;
          : Programming from the Ground Up by Jonathan Bartlett&lt;/p&gt;

</description>
      <category>programming</category>
      <category>assembly</category>
      <category>bios</category>
    </item>
    <item>
      <title>Why Everything Inside Your Computer Is Just Numbers</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Fri, 13 Jun 2025 10:22:48 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/why-everything-inside-your-computer-is-just-numbers-5dmd</link>
      <guid>https://forem.com/bhushitha_hashan/why-everything-inside-your-computer-is-just-numbers-5dmd</guid>
      <description>&lt;p&gt;When you power on your computer, it might seem like magic: a machine with flashy lights, crisp graphics, and powerful AI all running seamlessly. But underneath all of that, your computer is really just a highly sophisticated number-cruncher. It doesn’t "understand" in any human sense instead it processes raw numbers and bytes.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How the CPU wakes up and starts executing instructions&lt;/li&gt;
&lt;li&gt;What instructions look like in memory&lt;/li&gt;
&lt;li&gt;How the CPU knows where instructions start and end&lt;/li&gt;
&lt;li&gt;The role of architecture in instruction size and format&lt;/li&gt;
&lt;li&gt;The Von Neumann architecture’s influence on how programs and data coexist in memory&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Understanding CPU Instructions in Memory
&lt;/h2&gt;

&lt;p&gt;At its core, a CPU instruction like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mov eax, 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is just a sequence of bytes stored in memory. The CPU does not see "mov" or "eax" as words; it sees raw binary numbers.&lt;/p&gt;

&lt;p&gt;In machine code, that instruction is represented as the following five bytes (in hexadecimal):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;B8 01 00 00 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each byte occupies one memory address. So in memory, this sequence is laid out like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At some starting address (say, 0x00000000), the byte &lt;code&gt;B8&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;At 0x00000001, the byte &lt;code&gt;01&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;At 0x00000002, &lt;code&gt;00&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;At 0x00000003, &lt;code&gt;00&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;At 0x00000004, &lt;code&gt;00&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first byte (&lt;code&gt;B8&lt;/code&gt;) is the &lt;strong&gt;opcode&lt;/strong&gt;, which tells the CPU: “Move an immediate 32-bit value into the EAX register.” The next four bytes (&lt;code&gt;01 00 00 00&lt;/code&gt;) are the actual 32-bit little-endian value to move (in this case, the number 1).&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory Is Just Bytes With Addresses
&lt;/h2&gt;

&lt;p&gt;Think of memory as a huge row of lockers, each holding a single byte a number from 0 to 255. Every locker (byte) has an address, so the CPU knows where to find data or instructions.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Address 0x00000000 might hold &lt;code&gt;123&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Address 0x00000001 might hold &lt;code&gt;065&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Address 0x00000002 might hold &lt;code&gt;255&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on.&lt;/p&gt;

&lt;p&gt;All data, whether numbers, text, images, or instructions, is ultimately just bytes stored in these lockers. The meaning depends on how software interprets those bytes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Storing Data and Instructions as Numbers in Memory
&lt;/h2&gt;

&lt;p&gt;At the most basic level, a computer’s memory is a sequence of bytes ,small storage units that each hold a number between 0 and 255. Everything stored in a computer, whether text, numbers, images, or instructions, is ultimately just these numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Is Text Stored?
&lt;/h3&gt;

&lt;p&gt;Text is stored using character encoding standards such as ASCII. For example, the string &lt;code&gt;"HELLO"&lt;/code&gt; is stored as the sequence of bytes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[72, 69, 76, 76, 79]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each number corresponds to the ASCII code for a letter (&lt;code&gt;72&lt;/code&gt; for 'H', &lt;code&gt;69&lt;/code&gt; for 'E', etc.).&lt;/p&gt;

&lt;h3&gt;
  
  
  How Are Numbers Stored?
&lt;/h3&gt;

&lt;p&gt;Numbers can be stored in two primary ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As text: The characters &lt;code&gt;'1'&lt;/code&gt;, &lt;code&gt;'0'&lt;/code&gt;, &lt;code&gt;'0'&lt;/code&gt; are stored as ASCII codes &lt;code&gt;[49, 48, 48]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;As raw numeric values: The integer &lt;code&gt;100&lt;/code&gt; stored directly as the byte &lt;code&gt;100&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This distinction is important because the CPU only processes bytes. The meaning of those bytes depends entirely on context,whether they represent text, numbers, instructions, or other types of data.&lt;/p&gt;




&lt;h3&gt;
  
  
  If Everything Is Just Numbers, How Does the CPU Know What to Do?
&lt;/h3&gt;

&lt;p&gt;This raises a fundamental question: if memory is just numbers, how does the CPU know which numbers are instructions to execute and which are data?&lt;/p&gt;

&lt;p&gt;The answer lies in the way the CPU is designed and how software prepares the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  CPU Instructions Are Numbers Too
&lt;/h2&gt;

&lt;p&gt;Every instruction that a CPU executes such as &lt;code&gt;MOV&lt;/code&gt;, &lt;code&gt;ADD&lt;/code&gt;, or &lt;code&gt;JMP&lt;/code&gt; is encoded as a binary number known as an opcode.well talk about opcodes in detail in a bit.&lt;/p&gt;

&lt;p&gt;For example, on x86 processors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Opcode (Hex)   Instruction
------------   -----------
B8             MOV EAX, immediate
05             ADD EAX, immediate
C3             RET (return)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CPU contains a decoder that interprets these binary patterns as specific instructions.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does the CPU Identify Instructions?
&lt;/h2&gt;

&lt;p&gt;Press the power button, and your CPU begins with no knowledge of its surroundings.&lt;br&gt;
The CPU does not inherently distinguish instructions from data. Instead, it begins executing instructions from a specific memory address known as the instruction pointer.This address points to a special, read-only area called ROM (Read-Only Memory), where your BIOS or UEFI firmware lives. The CPU fetches its first instructions from this ROM chip.&lt;/p&gt;

&lt;p&gt;At this address, the CPU reads bytes and interprets them as instructions in sequence. If the bytes at the instruction pointer correspond to valid opcodes, the CPU executes them accordingly.&lt;/p&gt;

&lt;p&gt;It’s important to note that the RAM (random access memory) is uninitialized and doesn’t contain meaningful data at this early stage.&lt;/p&gt;

&lt;p&gt;The operating system or bootloader sets the instruction pointer to the start of the program’s code segment, guiding the CPU to interpret that memory region as executable instructions.&lt;/p&gt;


&lt;h2&gt;
  
  
  What’s the Difference Between Code and Data?
&lt;/h2&gt;

&lt;p&gt;At the hardware level, there is no intrinsic difference between code and data—both are just numbers stored in memory. The distinction arises from how the system uses those numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the CPU executes the bytes, they are treated as code.&lt;/li&gt;
&lt;li&gt;If the program reads or writes the bytes, they are treated as data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This concept is central to the Von Neumann architecture, where code and data share the same memory space but are used differently depending on context.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Happens If Code and Data Get Confused?
&lt;/h2&gt;

&lt;p&gt;If the CPU attempts to execute data as code, it will misinterpret the bytes, often causing crashes or unpredictable behavior. Modern operating systems implement memory protection mechanisms to reduce such risks by separating code and data into distinct regions of memory.&lt;/p&gt;


&lt;h2&gt;
  
  
  How CPU Architecture Influences Instruction Size and Format
&lt;/h2&gt;

&lt;p&gt;Instruction size depends heavily on the CPU architecture. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On modern x86 or x86_64 CPUs, instructions are &lt;strong&gt;variable length&lt;/strong&gt; — they can range from 1 to 15 bytes.&lt;/li&gt;
&lt;li&gt;The instruction &lt;code&gt;mov eax, 1&lt;/code&gt; takes 5 bytes because it includes an opcode byte plus four bytes for the 32-bit immediate value.&lt;/li&gt;
&lt;li&gt;On simpler 8-bit CPUs like the 6502 or Z80, instructions are generally shorter (often 1 to 3 bytes).&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  What Is an Opcode?
&lt;/h2&gt;

&lt;p&gt;An opcode (operation code) is a byte that encodes the CPU instruction type. It tells the CPU what to do next.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;B8&lt;/code&gt; means “move an immediate 32-bit value into EAX”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;89&lt;/code&gt; means “move a register into memory or another register”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C3&lt;/code&gt; means “return from subroutine”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;90&lt;/code&gt; means “no operation” (NOP)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the CPU reads an opcode, it knows exactly how many additional bytes to read for operands (like registers, immediate values, or memory addresses) based on the opcode’s meaning.&lt;/p&gt;


&lt;h2&gt;
  
  
  How Does the CPU Know Where Instructions End?
&lt;/h2&gt;

&lt;p&gt;The CPU follows a strict fetch-decode-execute cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It &lt;strong&gt;fetches&lt;/strong&gt; one byte from the current instruction pointer.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;decodes&lt;/strong&gt; that byte by looking it up in an internal opcode table.&lt;/li&gt;
&lt;li&gt;The opcode tells the CPU whether more bytes need to be fetched and how many.&lt;/li&gt;
&lt;li&gt;The CPU fetches the remaining bytes (operands).&lt;/li&gt;
&lt;li&gt;It then &lt;strong&gt;executes&lt;/strong&gt; the instruction.&lt;/li&gt;
&lt;li&gt;The instruction pointer is updated to the next instruction’s first byte.&lt;/li&gt;
&lt;li&gt;The cycle repeats.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because of this design, instructions are &lt;strong&gt;self-describing&lt;/strong&gt; in length. The first opcode byte inherently defines the size and format of the entire instruction.&lt;/p&gt;

&lt;p&gt;For example, the instruction &lt;code&gt;mov [eax + 4], ebx&lt;/code&gt; translates to the bytes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;89 58 04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;89&lt;/code&gt; is the opcode for a register/memory move&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;58&lt;/code&gt; is a ModR/M byte that specifies the memory location (eax plus an 8-bit displacement)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;04&lt;/code&gt; is the displacement value&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Quick Overview of Instruction Components
&lt;/h2&gt;

&lt;p&gt;Many x86 instructions are composed of multiple parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optional &lt;strong&gt;prefix bytes&lt;/strong&gt; for repeat or segment overrides&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;opcode&lt;/strong&gt; itself (the main instruction code)&lt;/li&gt;
&lt;li&gt;Optional &lt;strong&gt;ModR/M&lt;/strong&gt; byte specifying addressing modes and registers&lt;/li&gt;
&lt;li&gt;Optional &lt;strong&gt;SIB&lt;/strong&gt; (scale-index-base) byte for complex memory addressing&lt;/li&gt;
&lt;li&gt;Optional &lt;strong&gt;displacement&lt;/strong&gt; bytes for memory offsets&lt;/li&gt;
&lt;li&gt;Optional &lt;strong&gt;immediate&lt;/strong&gt; bytes for literal values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CPU’s decoder logic knows how to parse these parts step-by-step as it reads the instruction stream.&lt;/p&gt;




&lt;h2&gt;
  
  
  Von Neumann Architecture and Shared Memory
&lt;/h2&gt;

&lt;p&gt;All of this ties back to the Von Neumann architecture concept: program instructions and data share the same memory.&lt;/p&gt;

&lt;p&gt;This means that instructions like &lt;code&gt;mov eax, 1&lt;/code&gt; are stored as numbers, just like data values.&lt;/p&gt;

&lt;p&gt;The CPU doesn’t inherently distinguish code from data — it relies on the instruction pointer to fetch bytes in sequence and interpret them as instructions.&lt;/p&gt;

&lt;p&gt;This architecture offers flexibility but can also introduce vulnerabilities, such as when data is mistakenly executed as code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up what we discussed so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The CPU begins execution from a fixed ROM address containing firmware.&lt;/li&gt;
&lt;li&gt;Memory is a continuous sequence of bytes, each with a unique address.&lt;/li&gt;
&lt;li&gt;Instructions are sequences of bytes, starting with an opcode byte that tells the CPU how to decode the rest.&lt;/li&gt;
&lt;li&gt;Instruction size varies based on architecture and specific instruction.&lt;/li&gt;
&lt;li&gt;The CPU uses internal decoding logic and lookup tables to fetch and execute instructions correctly.&lt;/li&gt;
&lt;li&gt;The Von Neumann architecture explains why instructions and data coexist in the same memory space.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This article is designed to give you some understanding of what’s happening inside your CPU when it starts running code beneath the surface of all the software and graphics you see.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;References:Programming from the Ground Up by Jonathan Bartlett&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Beyond Blueprints: Seeing the Soul of Java's Classes and Objects</title>
      <dc:creator>Bhushitha Hashan</dc:creator>
      <pubDate>Tue, 08 Apr 2025 09:42:45 +0000</pubDate>
      <link>https://forem.com/bhushitha_hashan/beyond-blueprints-seeing-the-soul-of-javas-classes-and-objects-3a29</link>
      <guid>https://forem.com/bhushitha_hashan/beyond-blueprints-seeing-the-soul-of-javas-classes-and-objects-3a29</guid>
      <description>&lt;p&gt;We've all heard the simplistic analogy: "A class is a blueprint, and an object is a house." While it offers a rudimentary starting point, it barely scratches the surface of the profound relationship between classes and objects in object-oriented programming, especially within the robust ecosystem of Java. Let's discard the oversimplifications and embark on a technical and philosophical exploration to truly grasp their significance in crafting resilient and elegant software.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Technical Foundation: A Java Perspective
&lt;/h2&gt;

&lt;p&gt;Within the context of Java, classes and objects have particular meaning.They are not mere abstract concepts,they are fundamental building blocks with distinct roles at different stages of their lifecycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Class: The template of Behavior and Structure
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;class&lt;/strong&gt; in Java is a &lt;strong&gt;compile-time construct&lt;/strong&gt;, a meticulous definition etched in your source code. It acts as a comprehensive template, dictating the very essence of the entities your program will manipulate. This template encompasses,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State (variables)::&lt;/strong&gt; These are the variables declared within a class (e.g., &lt;code&gt;int age&lt;/code&gt;, &lt;code&gt;String name&lt;/code&gt;). They represent the data that an object of this class will hold, defining its characteristics. Think of them as the attributes that describe an entity.instance variables define the precise memory footprint of each object. When a class is loaded, the JVM calculates field offsets based on type signatures in the class file - primitive types like int (4 bytes) and long (8 bytes) get fixed-width slots, while object references consume either 4 or 8 bytes depending on JVM configuration.Each object header (typically 12 bytes) contains a pointer to this layout metadata in the class's klass structure.Static fields are treated differently,they stored in the class's mirror object in Metaspace, not within individual instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behavior (Methods)::&lt;/strong&gt; These are the functions defined within a class (e.g., &lt;code&gt;calculateSalary()&lt;/code&gt;, &lt;code&gt;login()&lt;/code&gt;). They encapsulate the actions that an object of this class can perform, defining its capabilities and interactions in controlled manner.When a Java class is loaded, the JVM stores its bytecode and metadata, including the structure of fields and methods, within the Method Area. For classes with overridable instance methods, the JVM creates a vtable in the Method Area, which is an ordered array of pointers to the actual method implementations (either bytecode in the Method Area or compiled native code in the Code Cache). Similarly, classes implementing interfaces may have itables in the Method Area to facilitate interface method dispatch. Each object created on the heap contains a pointer to its class's metadata in the Method Area, allowing the JVM to access the appropriate vtable or itables. During method invocation on an object, the JVM uses the object's class pointer to locate the vtable or itable and then uses a precomputed index to find the memory address of the method's executable code, enabling dynamic dispatch and polymorphism. Static methods and constructors, not subject to dynamic dispatch, are also stored in the Method Area and are invoked directly using the class metadata. Instance fields reside within the object on the heap, while static fields are stored in the class's metadata in the Method Area.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Identity (Constructors):&lt;/strong&gt; These special methods  dictate how a new object of the class is initialized. They set the initial state of an object when it is created, giving it its initial identity.At a raw, low-level, when &lt;code&gt;new&lt;/code&gt; is executed, the JVM first allocates a contiguous block of raw bytes in the heap, the size determined by the class's field layout. This memory is initialized to zero. Then, the appropriate constructor's bytecode is executed. This bytecode directly manipulates the memory at specific byte offsets corresponding to the instance fields, writing the initial values provided in the constructor call or default values. The constructor might also call other methods, including the constructor of the superclass, which similarly manipulates the raw byte representation of the object's inherited fields. Finally, the &lt;code&gt;new&lt;/code&gt; operation returns the memory address of this now-initialized block of bytes as a reference to the newly created object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relationships (Inheritance, Interfaces):&lt;/strong&gt; Java's &lt;code&gt;extends&lt;/code&gt; and &lt;code&gt;implements&lt;/code&gt; keywords within a class definition establish how this class relates to other classes and interfaces, enabling code reuse and polymorphism.At the JVM level, inheritance via extends creates a hierarchical vtable structure where method calls are resolved through virtual method table lookups - each class maintains a table of method slots, with subclasses copying and overriding parent entries, while invokevirtual opcodes use this table for dynamic dispatch. Interface implementation (implements) generates separate itables (interface method tables) that map interface methods to concrete implementations, resolved through invokeinterface which performs additional overhead for interface method resolution including checking all implemented interfaces. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally A class exists solely in your source code. It is the input for the &lt;strong&gt;Java compiler&lt;/strong&gt;, which then translates this human readable definition into &lt;strong&gt;bytecode&lt;/strong&gt;  the language understood by the Java Virtual Machine (JVM).the moment your program runs and touches that class, the JVM brings it to life in memory. It builds this whole shadow version of your class in Metaspace.Method tables, reflection junk,Constant Pool Resolution,Class Hierarchy Info ,JIT Optimization Hooks which  the Just-In-Time compiler uses to aggressively optimize hot code paths etc are few.&lt;/p&gt;

&lt;h2&gt;
  
  
  Object: The Living Instance
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;object&lt;/strong&gt;, on the other hand, is a &lt;strong&gt;runtime instance&lt;/strong&gt; of a class. It is the tangible manifestation of the blueprint defined by the class. When your Java program runs, objects come to life, occupying precious memory within the &lt;strong&gt;heap&lt;/strong&gt;. &lt;br&gt;
When a new object comes into being within the JVM's heap, it carves out a specific chunk of raw bytes from the available memory. The size of this chunk isn't a simple tally of its declared fields; it also includes a bit of extra baggage known as the object header. This header is like an internal ID tag, holding crucial low-level information. One part, the "mark word," carries bits that track things like the object's unique hash code, its status for garbage collection, and any active locking information. Another vital part is the "klass pointer," which is essentially a direct memory address acting like a signpost, pointing the JVM back to the detailed blueprint of the object's class stored in the Metaspace.&lt;/p&gt;

&lt;p&gt;Right after this header, the actual data fields of the object reside. For basic data types like integers and long numbers, their raw binary values are laid out directly in the allocated memory, starting at specific positions (offsets). The JVM decides these positions based on a careful arrangement process that considers the order in which the fields are declared and also any alignment rules that the computer's processor might require for optimal performance.&lt;/p&gt;

&lt;p&gt;When you tell an object to do something (invoke a method), the special &lt;code&gt;this&lt;/code&gt; keyword you often see is, at its heart, just the raw memory address where that object lives in the heap. The JVM takes this address, along with the name of the method you called, and uses the "klass pointer" from the object's header to find the class's instructions. Within these instructions, it locates the vtable (for regular methods) or itable (for interface methods). These tables are like internal address books, containing the raw memory locations of the actual machine code that makes the method run. Finally, the object's unique "identity" at the most fundamental level is deeply connected to its unique starting address within the vast landscape of the heap, and the &lt;code&gt;hashCode()&lt;/code&gt; method often cleverly uses this address or some derived value to give you a more human-friendly integer representation of that uniqueness.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Philosophical and Design Significance: Beyond the Code
&lt;/h2&gt;

&lt;p&gt;Stepping aside the technical specifications,Now let's delve into the philosophical and design implications of classes and objects, understanding their true meaning in crafting robust and maintainable software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Class as a "Rulebook": The Abstract Definition of an Idea
&lt;/h2&gt;

&lt;p&gt;Think of a Java class as a strict and detailed rulebook. It lays out exactly what kind of data its objects will hold.like numbers, strings, or lists — and what actions they’ll be able to perform,like depositing money or printing details. This isn’t a gentle suggestion; it’s a contract. Every object created from that class must follow these rules without exception. The Java Virtual Machine (JVM) enforces this behind the scenes, ensuring that your objects behave predictably and consistently.&lt;/p&gt;

&lt;p&gt;Let’s take a real-world example: a &lt;strong&gt;BankAccount class.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This class doesn’t just suggest that a bank account should have a balance and an accountNumber. It defines them as essential parts of what makes a bank account a bank account. It also outlines specific operations, like deposit(), withdraw(), and getBalance(). These aren't optional features — they are the core capabilities every BankAccount object must have.&lt;/p&gt;

&lt;p&gt;But there’s more. A good class often comes with invariants — unbreakable rules that must always hold true. For instance, a BankAccount might require that the balance can never drop below zero, and a withdrawal can only happen if there’s enough money in the account. These built-in checks act like safety rails, preventing your objects from getting into illogical or invalid states.&lt;/p&gt;

&lt;h2&gt;
  
  
  Object as a "Tangible Entity": The Concrete Realization
&lt;/h2&gt;

&lt;p&gt;Now here’s where it gets more interesting.&lt;/p&gt;

&lt;p&gt;If a class is the rulebook, then an object is a living, breathing copy created by following those rules. When your program runs and creates a new BankAccount, that’s no longer an idea — it’s a real instance in memory, with its own data and its own life. It might have a balance of $500 and an account number like 12345. You can interact with it: deposit money, withdraw cash, or check its balance.&lt;/p&gt;

&lt;p&gt;And here’s the cool part,if you also have a bank account in the program, it’s built from the same blueprint but lives a completely separate life. Your account might have $2,000, and mine $500. Even though both are BankAccount objects, each one has its own memory, its own values, and its own identity.&lt;/p&gt;

&lt;p&gt;Just like two houses built from the same blueprint can have different paint colors and furniture, two objects of the same class can have different data, but still obey the same structural rules. That’s the power of object-oriented programming.&lt;/p&gt;

&lt;p&gt;Finally,A well-designed class becomes a promise. It says, “Every object built from me will behave in a certain way and hold certain data and no surprises.” That kind of consistency is what allows large, complex programs to stay manageable.&lt;/p&gt;

&lt;p&gt;So the next time you define a class, remember, you're not just typing out some syntax. You're crafting a set of rules that will shape real, living things in your program's world.Each one with its own identity, yet all bound by the same laws you set.&lt;/p&gt;

&lt;p&gt;And when you create an object, you’re not just allocating memory,you're giving life to an idea.&lt;/p&gt;

</description>
      <category>java</category>
      <category>oop</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
