2017-09-07 4 views
0

私はCentOS 7.3でCode :: Blocks 16.01を使ってプログラムを書いています。このプログラムには、main関数と、clone()関数によって作成された子プロセス(またはいわゆるスレッド)が含まれています。私の目的は、chdir()関数がCLONE_FSパラメータを削除することによってメイン関数の作業ディレクトリに影響するかどうかをテストすることです。うまくいけばうまくいきますが、新しい問題が発生します。私のコードを先に読んでください:GNUのclone()関数がスタックしました

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <dirent.h> 
#include <sys/stat.h> 
#include <sys/mman.h> 
#include <sched.h> 
#include <fcntl.h> 

#define STACK_SIZE 1024*1024*8 

int thread_func(void *arg){ 
    int i; 
    char *cdir; 
    for(i = 0; i < 100; i++){ 
     switch(i%3){ 
     case 0: 
      chdir("/home/centos/dirtest/dir000"); 
      break; 
     case 1: 
      chdir("/home/centos/dirtest/dir001"); 
      break; 
     case 2: 
      chdir("/home/centos/dirtest/dir002"); 
      break; 
     } 
     cdir = getcwd(NULL,0); 
     fprintf(stderr,"Child Thread in # %d: %s\n",i,cdir); 
    } 
    free(cdir); 
    return 1; 
} 

int main(){ 
    void *pstack = (void*)mmap(NULL, STACK_SIZE, 
             PROT_READ | PROT_WRITE, 
             MAP_PRIVATE | MAP_ANONYMOUS | MAP_ANON, 
             -1, 0); 
    if(MAP_FAILED != pstack){ 
     int ret,i; 
     char *cdir; 
     ret = clone(thread_func, 
         (void*)((unsigned char *)pstack + STACK_SIZE), 
         CLONE_VM | CLONE_FILES , 
         NULL); 
     if(ret == -1){ 
      fprintf(stderr,"Thread create failed\n"); 
      return 0; 
     } 
     for(i = 0; i < 100; i++){ 
      cdir = getcwd(NULL,0); 
      fprintf(stderr,"Main Function in # %d: %s\n",i,cdir); 
     } 
      free(cdir); 
    } 
    return 1; 
} 

しかし、私がコマンドラインで端末に生成されたexeファイルを実行すると、スタックしてしまいました。メイン関数も子プロセスも "for"ループを終了することはできず、 "Ctrl-C"でプログラムを終了しなければなりませんでした。

誰でも問題を見つけることができますか?

********はここで、私はGETCWD()関数に変更を加えましたコメント

感謝を********新しい進歩の編集です。また、私はwaitpid()関数を追加しました。しかし、失敗を示しています。以下のように変更されたコードは次のとおりです。

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <dirent.h> 
#include <sys/stat.h> 
#include <sys/mman.h> 
#include <sys/wait.h> 
#include <sched.h> 
#include <fcntl.h> 

#define STACK_SIZE 1024*1024*8 

int thread_func(void *arg){ 
    int i; 
    char cdir[1024]; 
    for(i = 0; i < 100; i++){ 
     switch(i%3){ 
     case 0: 
      chdir("/home/centos/dirtest/dir000"); 
      break; 
     case 1: 
      chdir("/home/centos/dirtest/dir001"); 
      break; 
     case 2: 
      chdir("/home/centos/dirtest/dir002"); 
      break; 
     } 
     getcwd(cdir,sizeof(cdir)); 
     fprintf(stderr,"Child Thread in # %d: %s\n",i,cdir); 
    } 

    return 1; 
} 

int main(){ 

    /*void *pstack = (void*)mmap(NULL, STACK_SIZE, 
             PROT_READ | PROT_WRITE, 
             MAP_PRIVATE | MAP_ANONYMOUS , 
             -1, 0); 
    if(MAP_FAILED != pstack){*/ 
     void *pstack = malloc(STACK_SIZE); 
     int ret,i; 
     char cdir[1024]; 
     ret = clone(thread_func, 
         (void*)((char *)pstack + STACK_SIZE), 
         CLONE_VM | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD, 
         NULL); 
     if(ret == -1){ 
      fprintf(stderr,"Thread create failed\n"); 
      goto mem; 
     } 
     for(i = 0; i < 100; i++){ 
      getcwd(cdir,sizeof(cdir)); 
      fprintf(stderr,"Main Function in # %d: %s\n",i,cdir); 
     } 
     ret = waitpid(ret,0,0); 
     if(ret == -1){ 
      fprintf(stderr,"waitpid failed\n"); 
     } 
mem: 
    //} 
    free(pstack); 
    return 1; 
} 
+0

プロセスで作成できるスレッド数に制限はありますか?その限界は100未満ですか?もっと真剣に、あなたは十分な記憶を解放していますか? 'thread_func()'の 'getcwd()'から100個の戻り値のうち99個をリークしています。そして 'main()'の 'getcwd()'から100個の戻り値の99個を漏らしています。 –

+0

Jonathan Leffler、ご意見ありがとうございます。 getcwd()は重要な問題です。今度はこの呼び出しを修正しましたが、次のように別の問題が発生します。main関数はループを終了しますが、子スレッドは終了しません。 –

答えて

1

私は問題の一つは、あなたが実際にそれのためのlibcを用意することなくlibcのに触れる複数の実行スレッドを持っていることであることをかなり確信しています。スレッドが正常に生成されるとき、pthreadsを使って、stdio(あなたはstderrに印刷)に触れる複数のスレッドに対してlibcを準備するコードを実行し、mallocのロックを有効にして(getcwd内でmallocsを実行するので)、TLSを設定し、お互いにぶつからないでください。

あなたはこれを実行していません。もちろん、cloneを使って独自のスレッドを自由に生成することはできますが、呼び出したすべてのコードがスレッドセーフであることを確認することは、あなたの責任です。あなたはlibcを呼び出して、最高のものを望むだけでは動作しません。 Libcは、スレッドが1つしか実行されていないか、またはスレッドがpthreadで作成されていることを期待しています。

+0

ご意見ありがとうございます。実際にはgetcwd関数が重要な理由です。今度はコードを変更して元の投稿を編集しました。メイン関数が子スレッドが "for"ループを終了するのを待つことができないように、新しい問題が発生します。 –

関連する問題