12

Linuxプラットフォームで開発しています。

現在実行中のイメージを置き換えずに、ライブラリに新しいプロセスを作成したいと思います。

私はライブラリを開発しているので、主な機能はありません。

そして、呼び出し側アプリケーションが閉じた後も新しいプロセスを続行したいと思います(CreateProcessWindows 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()現在のプロセスが閉じている場合は、新しいプロセスを閉じます。

4

8 に答える 8

40

fork/のexec組み合わせについては既に説明しましたが、 +posix_spawnの代わりに使用でき、より直接的に と等価な関数群もあります。両方の可能性の例を次に示します。forkexecCreateProcess

#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));
  }
}
于 2011-05-04T13:59:24.290 に答える
15

posix_spawn最近ではおそらく推奨されるソリューションです。

fork()それ以前execXX()は、これを行う方法でした (は、、、、、およびを含む関数ファミリーのexecXX1 つです)。現在、GNU C ライブラリでは、少なくとも Linux ではfork/exec を介して実装されています。Linux にはシステム コールがありません。execexeclexeclpexecleexecvexecvpexecvpeposix_spawnposix_spawn

fork()(または) を使用vfork()して、親のクローンとなる別のプロセスを起動します。子プロセスと親プロセスの両方で実行は続行forkされますが、どちらの場合も異なる値が返されるため、区別できます。execXX()その後、子プロセス内から関数の 1 つを使用できます。

ただし、この問題に注意してください-私のブログ投稿の1つから借用したテキスト( 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() を使用して、何か (おそらく errno) をexec() が失敗した場合 (_exit() を呼び出す前) にパイプします。親プロセスはパイプから読み取ることができ、exec() が成功した場合はすぐに入力の終わりを取得し、exec() が失敗した場合はデータを取得します。

(子プロセスが親プロセスよりも低い優先度で実行され、親がそこからの出力を待機する場合、このソリューションは優先度の逆転を引き起こす傾向があることに注意してください)。

posix_spawn上記および他の回答にもありますが、とにかく fork/exec に関して実装されることが多く、exec()ステージが失敗する前に成功を返す可能性があるため、子実行可能ファイルの実行の失敗を検出する問題は解決しません。

于 2011-05-04T12:39:22.853 に答える
4

あなたが書いた:

現在実行中のイメージを置き換えることなく、ライブラリに新しいプロセスを作成したいと考えています。system() は現在のプロセスをブロックします。これは良くありません。現在のプロセスを継続したい。

コマンド呼び出しの後にアンパサンドを追加するだけです。例:system("/bin/my_prog_name &");

あなたのプロセスはブロックされません!

于 2014-05-06T19:57:07.710 に答える
2

これを行う古典的な方法は、fork() を使用して子プロセスを作成し、次に exec() 関数の 1 つを使用して子プロセスの実行中のイメージを置き換え、親プロセスはそのままにしておくことです。その後、両方のプロセスが並行して実行されます。

于 2011-05-04T12:40:45.733 に答える
2

posix_spawn はあなたが望むことをすると思います。内部的には fork/exec を行うかもしれませんが、ファンキーで便利なことも行うかもしれません。

于 2011-05-04T15:11:35.757 に答える
1

を使用する必要がありfork()ますexecvp()

fork()関数は新しい子プロセスを作成します。親プロセスでは、子プロセスのプロセス ID を受け取ります。子プロセスでは、返されるプロセス ID は 0 です。これは、プロセスが子プロセスであることを示しています。

execvp()呼び出しプロセス イメージを新しいプロセス イメージに置き換えます。これには、呼び出しプロセスのプロセス ID を使用して新しいプログラムを実行する効果があります。新しいプロセスは開始されないことに注意してください。新しいプロセス イメージは元のプロセス イメージを単にオーバーレイします。execvp 関数は、fork 関数の呼び出しによって作成されたプロセス イメージをオーバーレイするために最も一般的に使用されます。

于 2011-05-04T12:40:20.220 に答える
1

はい、 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;  
}
于 2011-05-04T13:03:10.147 に答える
-1

forkはあなたが探しているものだと思います。

于 2011-05-04T12:38:52.513 に答える