CPU寄存器设计及进程/线程中寄存器共享与上下文切换问题
Hey there, let's unpack your questions step by step—this is core stuff about CPU registers, process/thread execution, and debugging, so I'll make it as clear as possible!
Registers are the fastest form of storage in a CPU, sitting directly on the processor die right next to the arithmetic logic unit (ALU). Their design is driven by three key goals:
- Speed first: They exist to eliminate the need to fetch data from RAM (or even cache) for the most frequently used values—like function arguments, loop counters, or intermediate calculation results.
- Balanced complexity: Too many registers would make the CPU physically larger, more power-hungry, and harder to design. Too few would force constant trips to memory, slowing everything down. So CPU architects strike a balance based on the target use case (e.g., embedded vs. server chips).
- Architecture-specific roles: Registers are split into categories based on their purpose:
- General-purpose registers (GPRs): Used for arbitrary data storage and calculations (e.g.,
EAX/RAXin x86,R0-R12in ARM). - Special-purpose registers: Tied to specific CPU functions, like the program counter (
PC/RIP) that tracks the next instruction to execute, stack pointer (SP/RSP) that points to the top of the call stack, or status flags (FLAGS/CPSR) that store results of arithmetic operations. - Control registers: Manage low-level CPU operations, like memory paging (e.g.,
CR3in x86 holds the base address of the process's page table).
- General-purpose registers (GPRs): Used for arbitrary data storage and calculations (e.g.,
Let's tackle each of your sub-questions one by one:
Do each function have their own dedicated argument registers?
Nope, functions don't get "exclusive" argument registers. Instead, all functions follow a calling convention—a standardized set of rules defined by the CPU architecture and operating system. This convention dictates:
- Which registers are used to pass the first N arguments (the rest go on the stack).
- Which registers the caller must save before making a call (caller-saved registers).
- Which registers the callee must preserve before modifying (callee-saved registers).
For example, in x86-64 System V (used on Linux/macOS), the first 6 integer arguments are passed in RDI, RSI, RDX, RCX, R8, and R9. When you see arguments in registers during GDB debugging, that's just the function following this convention—not using a register reserved just for it.
Do all functions within the same process share argument registers?
Yes, they share the CPU's physical registers. Remember: a single CPU core can only execute one thread at a time. When a function calls another, the caller will load arguments into the convention-specified registers, then jump to the callee's code. The callee uses those registers to read the arguments, and if it needs to modify a callee-saved register, it'll first push its value to the stack to preserve it for the caller.
It's like sharing a whiteboard: everyone uses the same board, but everyone follows the rules of writing in the right spots and cleaning up after themselves so the next person can use it.
Are registers shared between threads or processes?
- Threads in the same process: No, they don't share register state. Each thread has its own execution context, which includes a full set of register values (PC, SP, GPRs, flags, etc.). Even though threads share the same virtual memory space, their register states are completely independent.
- Different processes: Absolutely not. Processes have entirely separate virtual memory spaces and execution contexts. A process can't access another process's registers directly—they're isolated at the hardware level.
If registers are not shared, how are their values stored during CPU context switches?
When a context switch happens (triggered by a timer interrupt, system call, or thread preemption), the CPU and kernel work together to save and restore register states:
- The CPU switches to kernel mode, which has access to protected system resources.
- The kernel saves the current thread/process's entire register state into a dedicated data structure:
- For processes: The Process Control Block (PCB).
- For threads: The Thread Control Block (TCB).
This includes every register—from GPRs to the program counter and status flags.
- The kernel then selects the next thread/process to run, and loads its saved register state from its PCB/TCB back into the CPU's physical registers.
- Finally, the CPU switches back to user mode and resumes execution from the point where the new thread/process left off.
One key note: For process switches, the kernel also has to switch the CPU's memory management registers (like CR3 in x86) to point to the new process's page table, ensuring the CPU uses the correct virtual memory space. Threads in the same process share this page table, so that step isn't needed for thread switches.
内容的提问来源于stack exchange,提问作者Yves

