Linux CreateProcess?

Linux CreateProcess?

本文关键字:CreateProcess Linux      更新时间:2023-10-16

我在Linux平台上开发。

我想在我的库中创建一个新进程,而不替换当前正在执行的映像。

因为我正在开发一个库,所以我没有main函数。

我想在调用程序应用程序关闭后继续新的进程(就像CreateProcess Windows API)。

在Linux中是否可能?

类似这样的函数:

void Linux_CreateProcess(const char* app_name)
{
  // Executing app_name.
  // ???????? what is the code ??????
  // app_name is running and never close if current application close.
  return;
}

注意:

  • system()阻塞当前进程,这是不好的。

  • exec()族替换当前正在执行的映像,效果不好

  • 如果当前进程关闭,popen()关闭新进程。

前面已经提到了fork/exec的组合,但是还有posix_spawn函数族可以用来替代fork + exec,它更直接地相当于CreateProcess。下面是两种可能性的例子:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <spawn.h>
#include <sys/wait.h>
extern char **environ;
void test_fork_exec(void);
void test_posix_spawn(void);
int main(void) {
  test_fork_exec();
  test_posix_spawn();
  return EXIT_SUCCESS;
}
void test_fork_exec(void) {
  pid_t pid;
  int status;
  puts("Testing fork/exec");
  fflush(NULL);
  pid = fork();
  switch (pid) {
  case -1:
    perror("fork");
    break;
  case 0:
    execl("/bin/ls", "ls", (char *) 0);
    perror("exec");
    break;
  default:
    printf("Child id: %in", pid);
    fflush(NULL);
    if (waitpid(pid, &status, 0) != -1) {
      printf("Child exited with status %in", status);
    } else {
      perror("waitpid");
    }
    break;
  }
}
void test_posix_spawn(void) {
  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: %in", pid);
    fflush(NULL);
    if (waitpid(pid, &status, 0) != -1) {
      printf("Child exited with status %in", status);
    } else {
      perror("waitpid");
    }
  } else {
    printf("posix_spawn: %sn", strerror(status));
  }
}

posix_spawn可能是目前首选的解决方案。

在此之前,fork()execXX()是这样做的(其中execXXexec函数族中的一个,包括execl, execlp, execle, execv, execvpexecvpe)。在目前的GNU C库中,至少在Linux中,posix_spawn是通过fork/exec实现的;Linux没有posix_spawn系统调用

您将使用fork()(或vfork())启动一个单独的进程,它将是父进程的克隆。在子进程和父进程中,执行都在继续,但fork在两种情况下都返回不同的值,允许您进行区分。然后,您可以在子进程中使用execXX()函数之一。

但是,请注意,这个问题-文本借用自我的一篇博客文章(http://davmac.wordpress.com/2008/11/25/forkexec-is-forked-up/):

似乎没有任何简单的符合标准的方法(甚至通常可移植的方法)来并行执行另一个进程并确保exec()调用成功。问题是,一旦fork()d,然后成功地执行了exec()d,您就无法与父进程通信以通知exec()成功。如果exec()失败,那么你可以与父进程通信(例如通过信号),但你不能通知成功-父进程可以确定exec()成功的唯一方法是等待()子进程完成(并检查是否有失败指示),当然这不是并行执行。

。如果execXX()成功,您将不再拥有控制权,因此无法向原始(父)进程发出成功信号。

这个问题的潜在解决方案,如果它是一个问题,在你的情况下:

[…使用pipe()创建一个管道,将输出端设置为close-on-exec,然后fork()(或vfork()), exec(),并在exec()失败时(在调用_exit()之前)向管道写入一些内容(可能是errno)。父进程可以从管道中读取数据,如果执行exec()成功,将立即得到一个结束输入,如果执行exec()失败,将得到一些数据。

(注意,如果子进程以低于父进程的优先级运行,并且父进程等待它的输出,则此解决方案很容易导致优先级反转)。

还有上面提到的posix_spawn和其他答案,但它不能解决检测执行子可执行文件失败的问题,因为它通常是根据fork/exec实现的,并且可以在exec()阶段失败之前返回成功。

您写的:

我想在我的库中创建一个新的进程,而不替换当前正在执行的映像。System()阻塞了当前进程,这是不好的。我想继续当前的进程。

只需在命令调用后添加一个&号。示例:system("/bin/my_prog_name &");

您的进程不会被阻塞!

实现此目的的经典方法是使用fork()创建子进程,然后使用exec()函数之一替换子进程的执行映像,保持父进程不变。然后两个进程将并行运行。

我认为posix_spawn做你想要的。在内部,它可能会做fork/exec,但也许它也会做一些非常有用的东西。

您应该先使用fork(),然后使用execvp()

fork()函数创建一个新的子进程。在父进程中,您将接收子进程的进程ID。在Child process中,返回的进程ID为0,这告诉我们该进程是一个子进程。

execvp()用一个新的进程映像替换调用进程映像。这样做的效果是运行一个带有调用进程的进程ID的新程序。注意,没有启动一个新进程;新流程映像只是覆盖原始流程映像。execvp函数最常用于覆盖通过调用fork函数创建的进程映像。

是的,fork()和exec..()是正确的解决方案。看看这段代码,如果它能帮助你:

switch( fork() )
{
    case -1 : // Error
            // Handle the error
            break;
    case 0 :
            // Call one of the exec -- personally I prefer execlp
            execlp("path/to/binary","binary name", arg1, arg2, .., NULL);
            exit(42); // May never be returned
            break;
    default :
            // Do what you want
            break;  
}

我想fork就是你要找的。