Linux-linux和windows创建新进程的区别以及posix_spawn

Linux上创建一个新的进程可以使用fork函数,这个函数执行的效果是复制当前进程创建一个新的进程,这个进程执行的代码与父进程相同。通过fork返回的pid我们可以在fork后的代码中区分父进程和子进程需要执行的逻辑。示例代码如下:

c 复制代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
    pid_t pid = fork();
    
    if (pid < 0) {
        fprintf(stderr, "Fork failed");
        return 1;
    } else if (pid == 0) {
        // 子进程代码
        printf("Child process (PID: %d)\n", getpid());
    } else {
        // 父进程代码
        printf("Parent process (PID: %d), Child PID: %d\n", getpid(), pid);
    }
    return 0;
}

而在window上,使用CreateProcess接口可以直接指定一个可执行程序路径创建新的进程,新进程的执行代码不在父进程中。

cpp 复制代码
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void _tmain( int argc, TCHAR *argv[] )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    if( argc != 2 )
    {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return;
    }

    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        argv[1],        // Command line 这里指定程序路径
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}

可以看到两者的不同之处:fork复制当前进程开启新进程,执行的代码都在父进程中,createProcess指定可执行程序从而开启新进程,执行代码的代码在指定的可执行程序中。那么在linux上如何实现类似createProcess的效果呢,一种是fork+exec:

复制代码
pid_t parent = getpid();
pid_t pid = fork();

if (pid == -1)
{
    // error, failed to fork()
} 
else if (pid > 0)
{
    int status;
    waitpid(pid, &status, 0);
}
else 
{
    // we are the child
    execve(...);
    _exit(EXIT_FAILURE);   // exec never returns
}

exec函数族会替换当前的进程映像(process image),我的理解是相当于子进程变成了exec指定的新的可执行程序在执行。还可以使用posix_spawn函数,用法类似windows的createProcess:

cpp 复制代码
pid_t pid;
  char *argv[] = {"ls", (char *) 0};
  int status;
  puts("Testing posix_spawn");
  fflush(NULL);
  status = posix_spawn(&pid, "/bin/ls", NULL, NULL, argv, environ);
  if (status == 0) {
    printf("Child id: %i\n", pid);
    fflush(NULL);
    if (waitpid(pid, &status, 0) != -1) {
      printf("Child exited with status %i\n", status);
    } else {
      perror("waitpid");
    }
  } else {
    printf("posix_spawn: %s\n", strerror(status));
  }

Linux设计上将"创建一个新进程"和"加载新的可执行程序到新的进程"两个步骤分离了,而windows的CreateProcess则是把两个步骤合并了。

  1. https://learn.microsoft.com/en-us/windows/win32/procthread/creating-processes
  2. https://stackoverflow.com/questions/5883462/linux-createprocess
  3. https://superuser.com/questions/1737519/why-a-fork-is-often-followed-by-an-exec
相关推荐
sdm07042714 小时前
应用层自定义协议
运维·服务器·网络
Agent产品评测局15 小时前
标准化产品vs定制开发,制造业自动化方案选型横评:2026工业智能体落地深度指南
运维·人工智能·ai·chatgpt·自动化
bush415 小时前
linux开发板连接virtualbox虚拟机ubuntu的usb网卡,访问外网方法。
linux·运维·ubuntu
JOJO___15 小时前
【2026】记录在windows编译llama.cpp步骤,AMD CPU本地部署千问3.5本地大模型,内存占用低
windows·cpu·amd·llama.cpp·llama.cpp编译·千问3.5·本地大语言模型
VOOHU-沃虎15 小时前
VOOHU——防水RJ45连接器在户外网络设备中的应用与选型
运维·服务器·网络
小明同学0115 小时前
C++后端项目:统一大模型接入 SDK(一)
linux·c++·chatgpt
码农编程录16 小时前
【notes10】spi
linux
yyuuuzz16 小时前
谷歌云使用的几个常见注意事项
运维·服务器·网络·安全·web安全·云计算·aws
大明者省16 小时前
完整 Ubuntu 服务器 XFCE 桌面 + XRDP 远程桌面 部署使用全流程
运维·服务器·ubuntu