揭开 fork 系统调用的魔法面纱

主要观点:Unix 类操作系统常用fork系统调用创建新进程,其在用户代码中的工作方式初学时易令人困惑,需通过检查fork的返回值确定在子进程或父进程中。通过示例代码展示了forkexecve的使用,解释了在if条件分支中同时出现以及fork如何返回两个不同值等疑惑,还介绍了系统调用的底层实现及相关汇编指令,如movqcmpqjz等,并展示了用汇编重写的示例程序及相关解读。

关键信息:

  • fork创建子进程,子进程是父进程的副本(有内部差异),系统调用返回后需检查返回值确定进程。
  • 示例中父进程打印消息后等待子进程结束,子进程执行ls程序。
  • 系统调用在内核实现,用户空间代码需用特定指令请求内核执行,libc提供系统调用包装器。
  • X86 架构下系统调用的约定:将系统调用号放入RAX寄存器,最多六个参数通过特定寄存器传递,返回值存于RAX
  • 用汇编重写示例程序,通过movq设置寄存器,cmpq比较值,jz根据比较结果跳转等。

重要细节:

  • fork函数实际是libc提供的fork系统调用的包装器。
  • 不同架构的系统调用调用约定不同,文中还列出了其他架构的相关内容。
  • 给出了exit系统调用的示例汇编代码及相关注释。
  • 完整的汇编程序可在这里找到,运行make可构建程序。
  • 关键是系统调用的返回值写入RAX寄存器,fork时父进程RAX为子进程pid,子进程RAX为 0。
阅读 8
0 条评论