2016-12-02 17 views
1

私は2人の子供をフォークする必要があるLinux上のC言語でプログラムを書いています。linux - exec'dプログラムが終了しない

最初の子は、パイプを介して2番目の子に2つの乱数を送信します。それはSIGUSR1信号を待ち受けて終了します。

2番目の子は、STDINとしてパイプ入力を複製し、fpをSTDOUTとして複製します。次に、入力と終了に応じていくつかのデータを出力するプログラムを実行します。

私の問題は、execl'dプログラムは決して終了しないと私には分からないということです。どんな助けやヒントも高く評価されます。

main.cの(親):

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

const int BUFFER_SIZE = 30; 

int pipefd[2] = {0,0}; 
int parent_pid = 0; 
int first_pid = 0; 
int second_pid = 0; 
int sleep_time = 5; 
int debug = 0; 
FILE *fp; 

void parent_func() { 
    int wstatus = 0; 

    sleep(sleep_time); 
    kill(first_pid, SIGUSR1); 
    wait(&wstatus); 
    waitpid(second_pid, &wstatus, 0); 
} 

static void sigusr1_handler(int sig) { 
    if (sig == SIGUSR1) { 
     fputs("TERMINATED", stderr); 
     close(pipefd[1]); 
     exit(0); 
    } 
} 

void first_func() { 
    struct sigaction act; 
    char buffer[BUFFER_SIZE]; 

    close(pipefd[0]);                                   
    memset(&act, '\0', sizeof(act)); // clear the sigaction struct                       

    act.sa_handler = &sigusr1_handler; // sets function to run on signal                      

    if (sigaction(SIGUSR1, &act, NULL) < 0) { // assign sigaction                       
     fputs("cannot assign sigaction - exiting...", stderr);                        
     exit(1);                                    
    }                                       

    while (1) {                                    
     sprintf(buffer, "%d %d\n", rand(), rand());                           
     write(pipefd[1], buffer, strlen(buffer));                            
     puts(buffer);                                   
     sleep(1);                                    
    }                                              
}                                        

void second_func() {                                   
    close(pipefd[1]);                                   
    fp = fopen("out.txt", "w");                                
    char buf[30]; 

    dup2(pipefd[0], STDIN_FILENO); 
    close(pipefd[0]); 
    //dup2(fileno(fp), STDOUT_FILENO); 

    execl("./test", "", NULL); 
    perror("Error"); 
} 

int main(int argc, char *argv[]) { 
    int fork_val = 0; 
    parent_pid = getpid(); 

    if (pipe(pipefd)) { 
     fputs("cannot create pipe - exiting...", stderr); 
     return 1; 
    } 

    if (debug) { 
     sleep_time *= 10; 
    } 

    if ((fork_val = fork()) == -1) { 
     fputs("cannot fork process - exiting...", stderr); 
     return 1; 
    } else if (fork_val == 0) { 
     first_func(); 
    } else { 
     first_pid = fork_val; 
     if ((fork_val = fork()) == -1) { 
      fputs("cannot fork process - exiting...", stderr); 
      return 1; 
     } else if (fork_val == 0) { 
      second_func(); 
     } else { 
      second_pid = fork_val; 
      parent_func(); 
     } 
    } 
    fclose(fp); 
    exit(0); 
} 

TEST.C(execl'dファイル):

#include "nd.h" 
#include "nsd.h" 
#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    int num1 = 0; 
    int num2 = 0; 
    char buffer[100]; 

    while (fgets(buffer, 100, stdin) != NULL) { 
     if (sscanf(buffer, "%d %d", &num1, &num2) == 2) { 
      (num1 < 0) ? num1 = (num1 * -1) : num1; 
      (num2 < 0) ? num2 = (num2 * -1) : num2; 
      if (num1 == 1 || num2 == 1) { 
       puts("1"); 
      } else if (num1 == num2) { 
       if (nd(num1) == 1) { 
        puts("prime"); 
       } else { 
        printf("%d\n", num1); 
       } 
      } else if (nd(num1) == 1 && nd(num2) == 1) { 
       puts("prime"); 
      } else { 
       printf("%d\n", nsd(num1, num2)); 
      } 
     } else { 
      fputs("error\n", stderr); 
     } 
    } 
    fputs("DONE", stderr); 
    exit(0); 
} 
+0

[正しいC書式設定](// prohackr112.tk/r/proper-c-formatting)を調べてください。あるいは、コードを徹底的に難読化する方法を学んでください(// prohackr112.tk/r/proper-c-obfuscation)。 –

+0

申し訳ありませんが、私は書式を編集しました。今はOKだろう。 – dotSK

+0

親プロセスは 'pipefd [0]'を終了する必要があります。 – Barmar

答えて

0

からファイルの終わりを検出することができるようにしますライターなしで空のパイプから読み込む必要があるパイプ(記述子を記述するためのプロセスがない)。

あなたの作家(first_func())は決してディスクリプタを閉じず、決して終わりのないループに何かを書き込んでいないので、読者はデータを待つか、またはデータを読み込みます。

有用でない記述子を閉じることに注意してください。パイプに問題が発生する可能性があります。リーダーやライターであるため、ファイルの終わりを検出できません。

+0

ありがとう、私は親プロセスでパイプを閉じるのを忘れました。しかし、first_func()のパイプは親プロセスからのシグナルを送ることによって呼び出されるsigusr1_handler()によって閉じられます。 – dotSK

関連する問題