You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用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

额外说明

  1. fork与vfork的本质区别:fork复制父进程地址空间,父子进程独立运行;vfork共享父进程地址空间,且强制阻塞父进程,仅用于快速启动新程序的场景。
  2. 竞态条件处理:多个子进程直接修改全局变量count会导致值不准确,示例中使用atomic_add系统调用保证计数操作的原子性,避免竞态问题。
  3. 父进程等待逻辑:原代码中父进程会直接退出,可能导致子进程未执行完就被终止,添加waitpid循环让父进程等待所有子进程执行完毕。

内容的提问来源于stack exchange,提问作者user26752091

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:52:39