0

/proc/[pid]/task/. を使用して特定のプロセスのスレッドを列挙したいのですが、procのマニュアルページでは、次のように述べています。

マルチスレッド プロセスでは、メイン スレッドが既に終了している場合 (通常は pthread_exit(3) の呼び出しによって)、/proc/[pid]/task ディレクトリの内容は利用できません。

それから私はいくつかのコードを書き、

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void* PrintHello(void* data){
  pthread_t tid = (pthread_t)data;
  int rc;

  rc = pthread_join(tid, NULL);
  if(rc){
    exit(1);
  } else{
    printf("Hello from new thread %d - got %d\n", pthread_self(), data);
    sleep(180);
    pthread_exit(NULL);
  }
}

int main(int argc, char* argv[]){
  int rc;
  pthread_t thread_id;
  thread_t tid;

  tid = pthread_self();
  printf("\nmain thread(%d) ", tid); 

  rc = pthread_create(&thread_id, NULL, PrintHello, (void*)tid);
  if(rc){
    printf("\n ERROR: return code from pthread_create is %d \n", rc);
    exit(1);
  }
  sleep(1);
  printf("\n Created new thread (%d) ... \n", thread_id);
  pthread_exit(NULL);
}

メインスレッドが pthread_exit() を呼び出した後、ゾンビになります。/proc/[pid]/task ディレクトリは残りますが、/proc/[pid]/maps は空です。

$ ./a.out & 
 main thread(164759360) 
 Created new thread (164755200) ... 
Hello from new thread 164755200 - got 164759360

$ ps auwx |  grep a.out
spyder    5408  0.0  0.0      0     0 pts/0    Zl+  10:27   0:00 [a.out] <defunct>
spyder    5412  0.0  0.0 109400   896 pts/1    S+   10:27   0:00 grep --color=auto a.out

$ ls /proc/5408/task/
5408  5409
$ cat /proc/5408/maps 
$ cat /proc/5408/status
Name:   a.out
State:  Z (zombie)
Tgid:   5408
Pid:    5408
....
$ cat /proc/5409/maps 
00400000-00401000 r-xp 00000000 fd:02 2752690                            /home/spyder/a.out
00600000-00601000 rw-p 00000000 fd:02 2752690                            /home/spyder/a.out
018cb000-018ec000 rw-p 00000000 00:00 0                                  [heap]
3dcf000000-3dcf020000 r-xp 00000000 fd:01 139203                         /usr/lib64/ld-2.15.so
3dcf21f000-3dcf220000 r--p 0001f000 fd:01 139203                         /usr/lib64/ld-2.15.so
....

何か問題でも?

4

2 に答える 2

1

あなたはこれをすべて逆に持っています。関数で実行される関数は、スレッドにPrintHello参加していますが、逆になる必要があります。main()

main()スレッド/関数では、次を呼び出す必要があります。

(void)pthread_join(thread_id, NULL);

要するに、pthread_join()「「thread_id」のスレッドと識別が完了するまで待ってから、他のことを行う」ことを意味します。あなたのコードは基本的に言っています:

  1. main() プログラム ロジックを開始する
  2. スレッドを作成し、いくつかの printf() と sleep() を実行してから、プログラム全体を終了します
  3. 同時に、main() が終了するまで何もしないスレッドを作成しました。
  4. main() が終了すると、いずれにせよすべてがホース処理PrintHello()されるため、join() 呼び出しが失敗する可能性が高いため、スレッドが正常に終了する可能性はありません。

おそらくこれを行うつもりでした(余分なコメントに注意してください):

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void* PrintHello(void* data){
  pthread_t tid = (pthread_t)data;

  //pthread_join(tid, NULL);  //WRONG
  printf("Hello from new thread %d - I was launched by thread number: %d\n", pthread_self(), data);
  sleep(180); //Sleep for 3 minutes, for no reason really
  pthread_exit(NULL); //All done in this thread
}

int main(int argc, char* argv[]){
  int rc;
  pthread_t thread_id;
  long int tid;

  tid = pthread_self();

  rc = pthread_create(&thread_id, NULL, PrintHello, (void*)tid);
  if(rc) {
    printf("\n ERROR: return code from pthread_create is %d; Thread probably didn't get created\n", rc);
    exit(1);
  }
  sleep(1); //Sleep, for no reason
  printf("\n Created new thread (%d) ... Now let's wait for it to finish\n", thread_id);
  pthread_join(thread_id, NULL); //Wait for the child thread to finish it's work
  return 0; //All done!
}

私の仮定が正しい場合は、そのことを示してください。さらに修正を加えることができます。幸運を!

于 2012-06-21T03:37:00.527 に答える
0

pthreads ライブラリがどのように機能するかについての私の理解から、ゾンビ スレッドの理由は、メイン スレッドと正常に結合するとそのリソースが破棄され、メイン スレッドが (メイン関数の戻りを通じて) ステータスを返すため、親プロセスによって消費される可能性があり、場合によっては (wait を使用して) スレッド グループが完全に終了するまで (つまり、プロセス全体が終了するまで)、このスレッドを完全に破棄することはできません。pthread_exit 呼び出しの値を親プロセスに返すことが何らかの方法で許可された場合、PrintHello関数がまだ実行されているため、親は子プロセスが終了したと考えますが、これは正しくありません。

于 2014-09-16T09:59:46.573 に答える