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
相关推荐
盟接之桥1 小时前
盟接之桥说制造:在安全、确定与及时之间,构建品质、交期与反应速度的动态平衡
大数据·运维·安全·汽车·制造·devops
learning_tom2 小时前
HTML图片标签及路径详解
linux·服务器·php
要记得喝水2 小时前
C#某公司面试题(含题目和解析)--1
开发语言·windows·面试·c#·.net
dbdr09012 小时前
Linux 入门到精通,真的不用背命令!零基础小白靠「场景化学习法」,3 个月拿下运维 offer,第二十六天
linux·运维·服务器·网络·python·学习
大白的编程日记.3 小时前
【Linux学习笔记】信号的深入理解之软件条件产生信号
linux·笔记·学习
鹧鸪云光伏与储能软件开发3 小时前
投资储能项目能赚多少钱?小程序帮你测算
运维·数据库·小程序·光伏·光伏设计软件·光伏设计
群联云防护小杜3 小时前
服务器异常磁盘写排查手册 · 已删除文件句柄篇
运维·服务器·nginx·开源·lua
buyutang_3 小时前
C/C++ Linux系统编程:线程控制详解,从线程创建到线程终止
linux·c语言·c++·学习
云的牧人3 小时前
Ubuntu 22 redis集群搭建
linux·运维·ubuntu
siriuuus3 小时前
Linux 磁盘扩容及分区相关操作实践
linux·运维·服务器