为何使用vfork的x86_64汇编程序未并行执行而是顺序运行?
问题原因与解决办法
核心问题:vfork的特性导致父进程阻塞
你调用的syscall 58是vfork系统调用,它的设计目标是让子进程立即执行exec类调用,在子进程调用exit或exec之前,父进程会被内核强制挂起——这是vfork的标准行为,和WSL的线程数设置无关,也是你看到子进程先完全执行完、父进程才继续运行的原因。
解决办法:改用fork实现并行
如果要实现父子进程并行执行,应该使用fork系统调用(syscall号57)。fork会为子进程创建独立的地址空间,父进程不会被阻塞,两者可以被系统调度器并行调度运行。
修改后的代码示例
bits 64 default rel %include "stringfns.asm" ; basic print functionality section .data count: dw 0 section .text global main main: mov r15, 0 spawner: mov rax, 57 ; 替换为fork的syscall号 syscall cmp rax, 0 je child call debug ; 父进程不再被阻塞,会和子进程交替执行 inc r15 cmp r15, 16 jne spawner ; 父进程等待所有子进程结束,避免提前退出导致子进程被终止 mov r15, 0 wait_loop: mov rax, 61 ; waitpid系统调用,等待任意子进程 mov rdi, -1 mov rsi, 0 mov rdx, 0 syscall cmp rax, -1 jne wait_loop jmp exit child: mov r15, 0 .loop: inc r15 cmp r15, 1000 ; 子进程执行循环逻辑 jne .loop ; 多个子进程修改count会有竞态,用原子操作保证计数准确 mov rax, 151 ; atomic_add系统调用(x86_64) mov rdi, count mov rsi, 1 syscall xor rsi, rsi mov si, [count] call iprintln ; 打印当前count值 mov rax, 60 mov rdi, 0 syscall ; 子进程必须显式exit,否则会继续执行父进程后续代码 exit: mov rax, 60 mov rdi, 0 syscall
额外说明
- fork与vfork的本质区别:fork复制父进程地址空间,父子进程独立运行;vfork共享父进程地址空间,且强制阻塞父进程,仅用于快速启动新程序的场景。
- 竞态条件处理:多个子进程直接修改全局变量
count会导致值不准确,示例中使用atomic_add系统调用保证计数操作的原子性,避免竞态问题。 - 父进程等待逻辑:原代码中父进程会直接退出,可能导致子进程未执行完就被终止,添加
waitpid循环让父进程等待所有子进程执行完毕。
内容的提问来源于stack exchange,提问作者user26752091
相关产品推荐
相关产品推荐

