Linux 创建进程?

发布于 2024-11-04 17:27:28 字数 612 浏览 0 评论 0原文

我是在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() 如果当前进程关闭,则关闭新进程。

I developing on the Linux platform.

I want to create a new proccess in my library without replacing the current executing image.

Because I am developing a library, I don't have a main function.

And I want to continue the new process after the invoker application closes (Just like CreateProcess Windows API).

Is it possible in Linux or not?

something like this function:

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;
}

Note:

  • system() blocks the current process, it is not good. I want to continue the current process.

  • exec() family replace the current executing image, it is not good.

  • popen() closes the new process if the current process closed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

一个人的旅程 2024-11-11 17:27:28

已经提到了 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: %i\n", pid);
    fflush(NULL);
    if (waitpid(pid, &status, 0) != -1) {
      printf("Child exited with status %i\n", 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: %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));
  }
}

The fork/exec combination was already mentioned, but there is also the posix_spawn family of functions that can be used as a replacement for fork + exec and is a more direct equivalent to CreateProcess. Here is an example for both possibilities:

#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: %i\n", pid);
    fflush(NULL);
    if (waitpid(pid, &status, 0) != -1) {
      printf("Child exited with status %i\n", 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: %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));
  }
}
木緿 2024-11-11 17:27:28

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

在此之前 fork()execXX() 是执行此操作的方法(其中 execXXexec 之一code> 函数系列,包括 execlexeclpexecleexecvexecvp > 和 execvpe)。目前在 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() 成功的唯一方法是为子级调用 wait()进程完成(并检查是否没有失败指示),这当然不是并行执行。

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

如果您的情况存在问题,则此问题的潜在解决方案:

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

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

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

posix_spawn is probably the preferred solution these days.

Before that fork() and then execXX() was the way to do this (where execXX is one of the exec family of functions, including execl, execlp, execle, execv, execvp, and execvpe). In the GNU C library currently, at least for Linux, posix_spawn is implemented via fork/exec anyway; Linux doesn't have a posix_spawn system call.

You would use fork() (or vfork()) to launch a separate process, which will be a clone of the parent. In both the child and parent process, execution continues, but fork returns a different value in either case allowing you to differentiate. You can then use one of the execXX() functions from within the child process.

Note, however, this problem - text borrowed from one of my blog posts (http://davmac.wordpress.com/2008/11/25/forkexec-is-forked-up/):

There doesn’t seem to be any simple standards-conformant way (or even a generally portable way) to execute another process in parallel and be certain that the exec() call was successful. The problem is, once you’ve fork()d and then successfully exec()d you can’t communicate with the parent process to inform that the exec() was successful. If the exec() fails then you can communicate with the parent (via a signal for instance) but you can’t inform of success – the only way the parent can be sure of exec() success is to wait() for the child process to finish (and check that there is no failure indication) and that of course is not a parallel execution.

i.e. if execXX() succeeds, you no longer have control so can't signal success to the original (parent) process.

A potential solution to this problem, in case it is an issue in your case:

[...] use pipe() to create a pipe, set the output end to be close-on-exec, then fork() (or vfork()), exec(), and write something (perhaps errno) to the pipe if the exec() fails (before calling _exit()). The parent process can read from the pipe and will get an immediate end-of-input if the exec() succeeds, or some data if the exec() failed.

(Note that this solution through is prone to causing priority inversion if the child process runs at a lower priority than the parent, and the parent waits for output from it).

There is also posix_spawn as mentioned above and in other answers, but it doesn't resolve the issue of detecting failure to execute the child executable, since it is often implemented in terms of fork/exec anyway and can return success before the exec() stage fails.

り繁华旳梦境 2024-11-11 17:27:28

你写道:

<块引用>

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

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

您的进程不会被阻止!

You wrote:

I want to create a new proccess in my library without replacing the current executing image.
system() blocks the current process, it is not good. I want to continue current process.

Just add an ampersand after the command call.
Example: system("/bin/my_prog_name &");

Your process will not be blocked!

望她远 2024-11-11 17:27:28

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

The classic way to do this is to use fork() to create a child process, and then use one of the exec() functions to replace the executing image of the child, leaving the parent untouched. Both process will then run in parallel.

过潦 2024-11-11 17:27:28

我认为 posix_spawn 可以满足您的要求。在内部它可能会执行 fork/exec 操作,但也许它也可以执行一些时髦有用的操作。

I think posix_spawn does what you want. Internally it might do fork/exec, but maybe it also does some funky useful stuff.

柠檬心 2024-11-11 17:27:28

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

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

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

You should be using fork() and then execvp().

fork() function creates a new child process. In the parent process you receive the process ID of the child process. In Child process the process ID returned is 0, which tells us that the process is a child process.

execvp() replaces the calling process image with a new process image. This has the effect of running a new program with the process ID of the calling process. Note that a new process is not started; the new process image simply overlays the original process image. The execvp function is most commonly used to overlay a process image that has been created by a call to the fork function.

走野 2024-11-11 17:27:28

是的,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;  
}

Yes, fork() and exec..() is the correct solution. Look at this code if it can help you :

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;  
}
吻安 2024-11-11 17:27:28

我认为 fork 就是您正在寻找的。

I think fork is what you are looking for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文