1

親プロセスはN個の子を作成し、それぞれが自分自身をexecに置き換えます。パイプの配列を介して親とexecの間に通信があります(int pipefd [N] [2];

execは、次のコマンドを使用してパイプに書き込みます。

char msg[50];
sprintf( msg, "\tsent from pid: %d, pi= %f", getpid(), pi);
printf("%s\n",msg);
write(i1, msg, strlen(msg)+1);

そして親はこれらで読みます:

for (i=0;i<N;i++) {
   close(pipefd[i][1]);  // close the write end of the pipe in the parent

   read(pipefd[i][0], buffer, sizeof(buffer));
   printf("\n-C-\n");

   if (buffer[0] == '\t'){
     printf("%s\n",buffer);
   }
   int j;
   for (j=0; j<100; j++) {
      buffer[j]='\n';
   }
   close(pipefd[i][0]);
}

ここで問題となるのは、子が終了した後でのみ、読み取りのブロックが解除され、バッファが出力されることです。私がやりたいのは、execがパイプに書き込んだ直後にバッファーを出力することです。

以下はすべてのコードです:

親ファイル:

#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>

#define N 5
pid_t *pid;
int pipefd[N][2];

int flag = 0;
int count_ctrl_c = 0;
void signal_handler(int sig){
    signal(sig, SIG_IGN);
    printf("\n");

    flag = 1;
    signal(SIGINT, signal_handler);
}

int main(int argc, char *argv[]) {


    int i;
    for (i = 0; i < N; i++) {
        pipe(pipefd[i]);
    }

    int parent_pid = getpid();
    pid= (pid_t *)malloc(N * sizeof(pid_t));

    for (i = 0; i < N; i++) {
        pid[i] = fork();
        if (pid[i] == 0) //The parent process will keep looping
        {

            char b[50];
            sprintf( b, "%d", i+1);

            char i0[50];
            sprintf( i0, "%d", pipefd[i][0]);

            char i1[50];
            sprintf( i1, "%d", pipefd[i][1]);

            char par_id[50];
            sprintf( par_id, "%d", parent_pid);

            execl("***the/path/to/exec/calculate***", b,i0,i1,par_id,NULL);
        }
    }

    if (parent_pid == getpid()) {
        signal(SIGINT, signal_handler);


        while(1){
            if (flag){

                printf("\n-A-\n");
                char buffer[100];
                int i;
                for (i=0;i<N;i++) {
                    // Apostellei to shma SIGUSR2 se ola ta paidia tou
                    kill(pid[i], SIGUSR2);
                }

                printf("\n-B-\n");
                for (i=0;i<N;i++) {
                    close(pipefd[i][1]);  // close the write end of the pipe in the parent

                    read(pipefd[i][0], buffer, sizeof(buffer));
                    printf("\n-C-\n");
                    if (buffer[0] == '\t'){
                        printf("%s\n",buffer);
                    }
                    int j;
                    for (j=0; j<100; j++) {
                        buffer[j]='\n';
                    }
                    close(pipefd[i][0]);
                }
                //exit(0);
                printf("finished reading\n");

                flag = 0;
                count_ctrl_c++;
                if (count_ctrl_c == 2) {
                    exit(0);
                }
            }

        }
    }
}

計算.c

#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>

#define N 5

int i0,i1,parent_pid;

int flag = 0;
int time_to_term = 0;
double pi;

void signal_handler2(int sig);
void signal_handler(int sig);

void signal_handler2(int sig){
    signal(sig, SIG_IGN);
    signal(SIGALRM, SIG_IGN);
    flag = 1;
    signal(SIGUSR2, signal_handler2);
    signal(SIGALRM, signal_handler);
}

void signal_handler(int sig){
    signal(sig, SIG_IGN);
    pid_t pid = getpid();
    printf("time: %d, pid: %d, pi: %1.10f\n", time_to_term, pid, pi);
    exit(0);
}

int main(int argc, char *argv[]) {
    int pid;
    signal(SIGINT, SIG_IGN);
    signal(SIGUSR2, signal_handler2);
    signal(SIGALRM, signal_handler);

    time_to_term = atoi(argv[0]);   
    alarm(time_to_term);

    i0 = atoi(argv[1]);
    i1 = atoi(argv[2]);
    parent_pid = atoi(argv[3]);

    double mul = 1.0;
    double par = 2.0;
    pi = 3.0;

    while(1){


        pi = pi + (mul * (4.0 / (par * (par + 1.0) * (par + 2.0))));
        mul = mul * (-1.0);
        par += 2;

        sleep(1);

         if (flag) {
            signal(SIGALRM, SIG_IGN);
            close(i0);

            char msg[50];
            sprintf( msg, "\tsent from pid: %d, pi= %f", getpid(), pi);
             printf("%s\n",msg);
            write(i1, msg, strlen(msg)+1);

            close(i1);
            flag = 0;

            signal(SIGALRM, signal_handler);
            //exit(0);


        }
    }

}
4

3 に答える 3

1

私見ですが、すべての子プロセスが作成したすべてのパイプを継承し、これはシステムリソースの浪費であるため、設計はあまり良くありません。行うべき正しいことは次のとおりです。

親プロセスでは:

  1. dup親プロセスが後で使用するために保持するfdの#0および#1。fcntlこれらの新しいfdでwithを使用しF_DUPFD_CLOEXECて、での継承を防止します。exec

  2. closefd#0

  3. closefd#1

  4. パイプを作成する

  5. 上記のように、パイプの読み取りfdの継承を防止します

  6. dup2パイプのfdを書き込んでfd#1にします。close元の書き込みfd

  7. forkexec子プロセス

  8. 必要なすべての子供に対してステップ3から7を繰り返します

  9. dup2printf/scaf機能を復元するために元のfdの#0と#1の複製を#0と#1に保存しました

  10. すべてのパイプの読み取りfdをポーリングするために使用selectし、#0に入力が必要な場合は#0をポーリングするために使用します

双方向通信が必要な場合は、ステップ4で、説明した手順を適切に調整して2つのパイプを作成し、ステップ2から7を繰り返して子を作成します。

子プロセスで(後exec

必要に応じてすべての処理を行います。fd#1またはprintfなどを使用して親に書き込みます。子プロセスは常に親PIDを取得できますgetppid()

于 2012-09-30T13:34:04.707 に答える
1

straceこれをトラブルシューティングするための一般的なヒント:ツールを使用してパイプラインの両側を実行し(strace -fフォークを追跡するために使用できます)、パイプから実際に何が書き込まれ、何が読み取られるかを確認できます。

この場合、子供は何も書いていないと思います!これは、使用する stdio レイヤー ( printf() ) が、それが端末に書き込んでいるのか、それとも他の何かに書き込んでいるのかをチェックするためです。端末の場合、改行ごとに出力をフラッシュしますが、それ以外の場合は、大きなデータ ブロックが書き込まれた後にのみフラッシュします (GNU システムでは 8KiB)。printf( ) の後にfflush()を使用して手動で出力をフラッシュしてみてください。それが役立つ場合は、setvbuf()を使用してstdoutバッファリング モードを調整できます。

于 2012-09-30T11:55:40.453 に答える
0

オペレーティング システムが書き込みをバッファリングしている可能性があります。

への呼び出しの後にパイプを明示的にフラッシュするには、ioctlとを使用してみてください。また、何か陰湿なことが起こっている場合に備えて、戻り値を確認してください。の詳細については、 http://pubs.opengroup.org/onlinepubs/7908799/xsh/ioctl.htmlを参照してください。FLUSHWwriteioctl

于 2012-10-01T01:59:53.610 に答える