wshibin's Technical Blog
website·Indexed 29 days ago
https://wshibin.github.ioA collection of technical notes and analyses covering systems programming, C/C++, RISC-V assembly, and Linux performance optimization. Includes deep dives into spdlog, musl libc, and LVGL V7.11.0 source code, as well as guides on WinDbg, GoogleTest, and Node.js.
What's inside wshibin
- CLAUDE.md is a project context file located in the root directory of a project. It serves as the 'brain' or initial cognitive model for Claude Code, providing the AI with essential project context, architecture, and conventions immediately upon starting a session. Unlike a README.md (which is written for humans), CLAUDE.md is written specifically for the AI to ensure consistent code output, reduce errors, and save context window usage by preventing the AI from having to rediscover project patterns via tools in every session.
Overview of RISC-V Floating-Point Extensions (F and D)
RISC-V implements floating-point support through layered extensions based on the IEEE 754 standard:
- F Extension: Provides 32 single-precision (32-bit) floating-point registers (f0-f31) and associated load/store, arithmetic, comparison, and conversion instructions.
- D Extension: Extends registers to 64-bit width for double-precision. It depends on the F extension. When D is present, single-precision values are stored in the lower 32 bits, with the upper 32 bits set to NaN-boxing (all 1s).
- Instruction Suffixes: Instructions ending in
.sdenote single-precision operations; those ending in.ddenote double-precision operations.
Overview of Rust Basic Types
Rust provides a variety of basic types categorized by their purpose and memory layout. Key types include signed and unsigned integers, floating-point numbers, booleans, Unicode characters, compound types (tuples, arrays), and heap-allocated or reference types (Vec, String, Box, slices).Category Types Size Signed Integers i8, i16, i32, i64, i128, isize 8/16/32/64/128/ptr width Unsigned Integers u8, u16, u32, u64, u128, usize 8/16/32/64/128/ptr width Floats f32, f64 32/64 bits Boolean bool 1 byte Character char 4 bytes (Unicode scalar) Tuple (T1, T2, ...) Sum of elements Array [T; N] N * size_of::<T>() Vector Vec<T> 3 words (ptr, len, cap) Slice &[T], &mut [T] 2 words (ptr, len) String Slice &str, &mut str 2 words (ptr, len) Owned String String 3 words (ptr, len, cap) Reference &T, &mut T 1 word (pointer) Box Box<T> 1 word (pointer) Raw Pointer *const T, *mut T 1 word Function Pointer fn(T1, T2) -> R 1 word Overview of Rust I/O Trait Hierarchy
Rust's I/O system is built around three core traits that provide a unified interface for files, network connections, memory buffers, and terminals:
Read: For byte-oriented input.Write: For byte-oriented output.BufRead: For buffered input (inherits fromRead), enabling line-based reading.
Common implementations include:
Read:File,TcpStream,Stdin,Cursor<&[u8]>,&[u8].BufRead:BufReader<R>,StdinLock,Cursor<&[u8]>.Write:File,TcpStream,Stdout,Stderr,Vec<u8>,BufWriter<W>,Cursor<&mut [u8]>.
use std::io::prelude::*; use std::io::{self, Read, Write, ErrorKind};Overview of RISC-V Pseudo-Instructions
Pseudo-instructions are high-level mnemonics provided by the assembler to improve readability, hide complexity, and ensure portability. They are not recognized by the CPU hardware; instead, the assembler transparently translates each pseudo-instruction into one or more 'hard' instructions (machine code) before outputting the final binary. This process is deterministic and can be inspected using tools likegcc -Sorobjdump -M no-aliases.Overview of RISC-V RV64I Register File
The RV64I architecture provides 32 general-purpose registers (x0-x31), each 64 bits wide. Registers are the fastest storage in the CPU with zero-cycle latency. The Program Counter (PC) is a separate 64-bit register that tracks the current instruction address; it cannot be accessed directly like general-purpose registers and is modified only via jump/branch instructions or AUIPC.Overview of CMake and its toolset
CMake is an open-source, cross-platform build system generator. It does not build the software itself but generates native makefiles and workspaces for various build systems (such as Make, Ninja, Visual Studio, and Xcode) based on platform-independent configuration files.
The CMake family consists of several key tools:
- CMake: The primary tool for configuration and build system generation.
- CTest: Used for testing the software.
- CPack: Used for packaging the software.
Overview of OpenClaw AI Agent Gateway
OpenClaw is an AI Agent gateway that connects an AI assistant to various tools (terminal, messaging, files, calendars, etc.), allowing users to execute tasks via natural language.Overview of Windows User Mode and Kernel Mode architecture
Windows architecture is split into two primary modes:
User Mode Components:
- User Processes: Standard applications (e.g.,
notepad.exe). - Subsystem DLLs: Implement official Windows APIs (e.g.,
kernel32.dll,user32.dll,gdi32.dll). - NTDLL.DLL: The lowest layer of user mode; implements Native APIs and handles the transition to kernel mode. Also manages the heap and image loader.
- Service Processes: Processes communicating with the Service Control Manager (
services.exe).
Kernel Mode Components:
- Executive (NtOskrnl.exe): Upper layer containing managers for objects, memory, I/O, PnP, power, and configuration.
- Kernel: Core time-sensitive functions including thread scheduling, interrupt/exception dispatching, and synchronization (mutexes/semaphores).
- Device Drivers: Loadable modules executing in kernel mode.
- Win32k.sys: Kernel-mode component for the Windows subsystem (UI and GDI).
- HAL (Hardware Abstraction Layer): Hides hardware details (interrupt controllers, DMA) from drivers.
- User Processes: Standard applications (e.g.,
Overview of Memory-Mapped Files (MMF) in Windows
Memory-Mapped Files (MMF), known as 'Sections' in the kernel, allow an application to map a disk file's contents directly into its virtual address space. This enables file access via standard pointers instead of repeated
ReadFileandWriteFilecalls. Key advantages include:- No need for manual buffer allocation or repeated I/O function calls.
- Ability to use standard memory functions like
memcpyandmemseton file data. - Improved performance via OS-managed caching.
- Native support for high-performance Inter-Process Communication (IPC) through shared memory.
Overview of the Windows I/O System Architecture
The Windows I/O system abstracts access to both physical and logical devices. User-mode processes interact with the system via Windows APIs. At the kernel level, the I/O Manager converts these requests into I/O Request Packets (IRPs), which are then passed to the appropriate device driver (e.g., an NTFS driver for files). While kernel-level I/O is inherently asynchronous, the I/O Manager can handle synchronization for the caller if a synchronous call is requested.Overview of overloadable operators in Rust
In Rust, operator overloading is achieved by implementing specific traits fromstd::opsorstd::cmp. Rust does not allow the creation of new operators or the overloading of logic operators like&&,||, or the assignment operator=. When an operator is used (e.g.,a + b), Rust desugars it into a trait method call (e.g.,a.add(b)).Category Operator Trait Method Unary -xstd::ops::Negneg(self) -> OutputUnary !xstd::ops::Notnot(self) -> OutputArithmetic a + bstd::ops::Addadd(self, rhs) -> OutputArithmetic a - bstd::ops::Subsub(self, rhs) -> OutputArithmetic a * bstd::ops::Mulmul(self, rhs) -> OutputArithmetic a / bstd::ops::Divdiv(self, rhs) -> OutputArithmetic a % bstd::ops::Remrem(self, rhs) -> OutputBitwise a & bstd::ops::BitAndbitand(self, rhs) -> OutputBitwise a | bstd::ops::BitOrbitor(self, rhs) -> OutputBitwise a ^ bstd::ops::BitXorbitxor(self, rhs) -> OutputBitwise a << bstd::ops::Shlshl(self, rhs) -> OutputBitwise a >> bstd::ops::Shrshr(self, rhs) -> OutputCompound Assign a += bstd::ops::AddAssignadd_assign(&mut self, rhs)Compound Assign a -= bstd::ops::SubAssignsub_assign(&mut self, rhs)Compound Assign a *= bstd::ops::MulAssignmul_assign(&mut self, rhs)Comparison a == bstd::cmp::PartialEqeq(&self, &rhs) -> boolComparison a != bstd::cmp::PartialEqne(&self, &rhs) -> boolComparison a < bstd::cmp::PartialOrdlt(&self, &rhs) -> boolComparison a <= bstd::cmp::PartialOrdle(&self, &rhs) -> boolComparison a > bstd::cmp::PartialOrdgt(&self, &rhs) -> boolComparison a >= bstd::cmp::PartialOrdge(&self, &rhs) -> boolIndexing a[i]std::ops::Indexindex(&self, idx) -> &OutputIndexing a[i] = vstd::ops::IndexMutindex_mut(&mut self, idx) -> &mut Output