2

みなさん、 fork と signal を使っていくつかの実験をしているときに、非常に興味深い動作を示すプログラムに出くわしましたが、何時間も苦労した後、何が起こっているのかわかりませんでした。

私がやろうとしているのは、本体内に子プロセスを作成し、「hello world」を出力してから exit を呼び出すことです。この後、そのシグナル ハンドラが呼び出され、wait システム コールによってブロックされた親プロセスも呼び出されることが完全に理解されます。今、シグナルハンドラーで別のプロセスを作成していますが、それ以降、出力は無限になります。

出力は次のとおりです: Hello world Linux に来て UNIX に来て Linux に来て UNIX に来て Linux に来て UNIX に来て ...

また、何度も何度も印刷されたLinuxに来るのはなぜですか。

また、フォークが呼び出されたときに教えてください。重複したアドレス空間が親で構成されていることは知っていますが、シグナルハンドラーはどうですか。それらも重複しますか。私の場合、子呼び出しが終了すると。次に、呼び出されるシグナルハンドラーは子または親です。

助けてください。ありがとう。

void sig_handler(int signo)
{
if(fork() == 0){

}
else{
    int pid = 0;
    wait(&pid);
    printf("Come to unix");
    fflush(stdout);
}
 }


int main()
{
if (signal(SIGCHLD, sig_handler) == SIG_ERR){
}

int child_pid;
int i;

child_pid = fork();
switch (child_pid) {
    case -1:         
        perror("fork");
        exit(1);
    case 0:          
        printf("hello world\n");fflush(stdout);        
        exit(0);
    default:
        wait(&i);
        printf("Come to linux");
        exit(0);
        //break;
}

return 0;
}
4

2 に答える 2

1

無限ループに陥ることは明らかではありませんか?SIGCHLD ハンドラーを作成してから、そのハンドラーで再度 fork し、子プロセスが終了するのを待ちます。基本的に、そのハンドラーの子が終了すると、親は再びハンドラーに入ります。以下のコードはそれを避けるべきです。シグナルハンドラーの開始時に、シグナルをデフォルトに設定して回避します。

void sig_handler(int signo) {
     signal (SIGCHLD, SIG_IGN);
    if(fork() == 0){ 

    }   
    else{
        int pid = 0;
        wait(&pid);
        printf("Come to unix");
        fflush(stdout);
    }    
}

また、未定義の動作を回避するために、シグナル ハンドラーでのみ非同期シグナル セーフ ルーチンを呼び出すことができます。printf と fflush が安全に同期できるかどうかはわかりません。上記の変更を行うとループが回避されますが、プログラムの動作は未定義のままになる可能性があります。フォークは非同期で安全だと思います

以下の参考になる議論を参照してください: http://sourceware.org/bugzilla/show_bug.cgi?id=4737

于 2013-03-23T13:21:24.643 に答える
0

シグナル ハンドラでの呼び出しfork(2)は、POSIX 標準に従って未定義の動作をするため、実行しないでください :)

http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.htmlを参照してください。

于 2013-03-23T12:33:49.150 に答える