2011-08-16 8 views
4

問題: bashスクリプトイベントが発生するたびに呼び出されますCアプリケーションがあります。また、これらのイベントを追跡する必要があるC++アプリケーションもあります。 C++アプリケーションは、select()イベントループによって駆動されます。 BashスクリプトC++アプリケーションの間に実装する最も簡単なIPCは何ですか?永続IPCバッシュ間のスクリプトとC++

C Application ---Each time calls Bash script---> Bash application ---???---> C++ Application 
私の心に入って来た

ほとんどソリューション:

  1. TCPネットワークソケットを使用するには、これは選択の名前を使用するに耳を傾け、実際のソケット
  2. 両方のイベントを処理する必要があることを意味しますbashスクリプトが終了すると、パイプのもう一方の端も閉じます。

1つのファイルしか使用できないような簡単なものがありますかselect()内のディスクリプタ?

答えて

2

Unix datagramまたはUDPソケットとなります。 bashスクリプトはそのソケットにデータグラムを送るだけです(そのソケットにsendmsg()またはsendto()socatまたはnetcat/ncなどのヘルパープログラムが必要な場合があります)。レシーバはデータグラムソケットの接続を受け入れる必要はありません。一度読み取る準備ができたら、待っているデータグラムがなければなりません。データグラムの長さの制約があります。

+0

+1データグラムソケットは、Accept()を混乱させる必要がないためです。また、マニュアルページによれば、Unixドメインのデータグラムソケットは信頼できるものですが、UDPソケットは信頼できません。それはまさに私が探していたものです。ありがとうございました。 –

+1

私は単純なパイプの使用は、リソースが少なくて済み、ファイルシステムに触れず、(sendmsg()/ sendto()のために外部プログラムを使わなくても)bashで完全に実行できるので、 –

+0

ソケットファイル名が宛先アドレスであるので、ヘルパープログラムは必要でないかもしれません(私は試していません)ので、 'echo" abc "> socket'で十分です。 –

3

名前はpipe()です。注意:UNIXのファイル記述子は、両方のプロセスでfork()execve()の後に開いたままです!したがって、pipe()を使用してファイル記述子のペアを取得し、bashのecho >&FDを使用してfdに書き込むことができます。FDはファイル記述子番号です。

これは、非常に簡単で、簡単で、私が推測するものよりも少ないリソースを使用します。 select()の使用は問題ありません。ただブロックしないでくださいread()私のサンプルではありますが、select()pfds[0]です。

サンプルプログラム( 'hello work、my pid:XXX'を送信する10のbashプロセスがプロセスを起動する間に1秒待っています)サンプルはすべての子に1つのパイプしか使用しませんでした。 。それについては実際には、私はは)(サンプル下記の注を参照)、それをお勧めしません:

#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdlib.h> 

#include <stdio.h> 
#include <assert.h> 

int main(int argc, char **argv) { 
    int pfds[2]; 
    pid_t p; 

    assert(0 == pipe(pfds)); 

    p = fork(); 
    if (p == 0) { 
     unsigned int i; 
     char str_fd[3];   char *env[] = {NULL}; 
     char *args[] = { "/bin/bash", "-c", "echo >&$1 hello world, my pid: $$" 
         , "-s", str_fd, NULL}; 
     snprintf(str_fd, 3, "%d", pfds[1]); 
     str_fd[2] = 0; 

     for (i = 0; i < 10; i++) { 
      p = fork(); 
      if(0 == p) { 
       assert(0 == 
         execve("/bin/bash", (char *const*)args 
          , (char *const*)env)); 
      } else if (0 > p) { 
       perror("fork"); 
       exit(1); 
      } else { 
       wait(NULL); 
      } 
      sleep(1); 
     } 
    } else if(p > 0) { 
     char *buf = malloc(100); 
     ssize_t sz; 
     printf("fd is %d, <hit Ctrl+C to exit>\n", pfds[1]); 
     while(0 < (sz = read(pfds[0], buf, 100))) { 
      buf[99] = 0; 
      printf("received: '%s'\n", buf); 
     } 
     free(buf); 
     if (0 == sz) { 
      fprintf(stderr, "EOF!"); 
     } else { 
      perror("read from bash failed"); 
     } 
     wait(NULL); 
    } else { 
     perror("fork failed"); 
     exit(1); 
    } 
    return 0; 
} 

サンプルプログラムの出力:

$ gcc test.c && ./a.out 
fd is 4, <hit Ctrl+C to exit> 
received: 'hello world, my pid: 779 
' 
received: 'hello world, my pid: 780 
' 
received: 'hello world, my pid: 781 
' 
received: 'hello world, my pid: 782 
' 
received: 'hello world, my pid: 783 
' 
received: 'hello world, my pid: 784 
' 
received: 'hello world, my pid: 785 
' 
received: 'hello world, my pid: 786 
' 
received: 'hello world, my pid: 787 
' 
received: 'hello world, my pid: 788 
' 

作品は、bashsは「送信Hello Worldの、私をpid:親プロセスにXXX \ n 'すべて1つのパイプを使用しています:-)。

デモプログラム(POSIXセマンティクスを使ってOKで、LinuxとMacOS Xでテストしたはずです)のように動作するようですが、子プロセスごとにpipe()を使用することをお勧めします。これにより、問題が少なくなり、一度に複数の子プロセスを実行することも可能になります。 select()またはepoll()(多くの子プロセスがある場合)はあなたの友人です。

pipe()は、特にbashと比較して非常に安いので、私は間違いなく1つ以上の子供のために同じパイプを使用しません。

+0

Bashプロセスは、イベントが発生するたびに作成されます。 Bashプロセスの最初のインスタンスが終了すると、パイプは両端で閉じられます。これは、C++アプリケーションからパイプをすばやく再オープンする必要があることを意味します。 –

+0

サンプルプログラムを少し変更しました。私は今、パイプに送るすべての10のbashプロセスを生成します。常に同じパイプです。これは、一度に実行されているパイプに常に1つのbashプロセスが送信されている場合にのみ機能します。 –

+0

@Ansis Atteka、あなたが私のデモで見ることができるように、ただ1本のパイプで動作します。しかしpipe()は非常に安いので、bashごとにパイプ()を使うこともできます。次に、複数のシェルが同時に実行されている場合でも問題は発生しません。 listenするファイルのデスクリプターがたくさんある場合は、 'epoll()'を使います。 –

1

ZeroMQのような軽量メッセージングキューを使用できます。あなたはPUSH-PULL機構を使うと思います。あなたのCプログラムやbashスクリプトは、C++アプリケーションがイベントをプルする間にイベントをプッシュします。 ZeroMQはC言語で書かれていますが、ほかにもC++とPythonのバインディングがあります。 PUSH-PULLの例については、hereを参照してください。

+0

+1。私はまた、このアプローチを考えましたが、私の問題は(少なくとも最初は)過体重に見えました。私は余分な依存関係を加えないものを探していました。 –

関連する問題