2012-04-03 11 views
1

これは、私はthread.thenで再びそれを初期化、SEMのinit奇妙problem.Iであり、最初にそれをDestoryは、私が目を覚ますことができない、それはagain.theコードは次のとおりです。posix sem_postはスレッド内のsem initのところでsem_waitをスリープ解除できません。 Linuxの

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <semaphore.h> 
#include <time.h> 
#include <assert.h> 
#include <errno.h> 
#include <signal.h> 
#include <pthread.h> 

sem_t sem; 
int key = 1; 

static void * 
wait_func() 
{ 
    printf("i'm wait\n"); 
    sem_wait(&sem); 
} 

static void * 
cancel_func(void *arg) 
{ 
    pthread_t tid = *(pthread_t *)arg; 
    if (key == 1) 
    { 
     sleep(1); 
     key = 0; 
    } 
    else 
     sleep(3); 
    if(pthread_cancel(tid) == 0) 
     printf("cancle!\n"); 

    sem_init(&sem, 0, 0); 
    sem_destroy(&sem); 
} 

int 
main(int argc, char *argv[]) 
{ 
    pthread_t wthread, cthread; 
    pthread_attr_t attr; 
    int i = 0; 

    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 

    sem_init(&sem, 0, 0); 

    while (i < 2) 
    { 
    //  sem_init(&sem, 0, 0); 

     pthread_create(&wthread, &attr, wait_func, NULL); 
     if (i < 1) 
      pthread_create(&cthread, &attr, cancel_func, &wthread); 
     if (key == 0) 
     { 
      sleep(2); 
      if (sem_post(&sem) == 0) 
       printf("post!\n"); 
      key = 1; 
     } 
     sleep(4); 
     ++i; 
    } 
    sleep(1000); 
} 

しかし、それは!コメントのようなwhileループでsem_initを変更する作業になりますので、私は2つのプログラムをstraced、および1をfindedしている)スレッド内のinit、sem_postはこのように、sys_futexを呼び出していませんでした:

nanosleep({2, 0}, i'm wait 

{2,0}) = 0 書き込み(1、 "post!\ n"、6post! )= 6

このようなメイン処理において3210

2)INIT、sem_postコールsys_futex:

nanosleep({2, 0}, i'm wait 

{2,0})= 0 のfutex(0x600dc0、FUTEX_WAKE_PRIVATE、1)= 1個の 書き込み(1、「ポスト! \ n "、6post! )= 6

これはsyscallの問題だと思っていました。sem_postで2つのプログラムを逆アセンブルするのにgdbを使いました。残念ながら、1)スレッド内のinit、sem_postのsyscallも呼び出す; 2)ripがシステムコールであるレジストリステータスを比較する。最後に

in thread: 
rax   0xca  202   //sys_futex 
rbx   0x3c0e61bbc0  257939323840 
rcx   0x0  0   //utime 
rdx   0x1  1   //val 
rsi   0x81  129   //op:private_wake 
rdi   0x600dc0 6294976  //sem uaddr 
in main process: 
rax   0xca  202 
rbx   0x3c0e61bbc0  257939323840 
rcx   0x0  0 
rdx   0x1  1 
rsi   0x81  129 
rdi   0x600da0 6294944 

、私はこのproblem.Pleaseについては考えている私に解決策を見つけるためにいくつかのアドバイスを与え、感謝。

+0

これは実際の問題ですか?継続的にセマフォを作成して破棄しない場合は、問題はありません。それに加えて、共有キー状態変数では、短いスリープと複数のスレッド、私はあなたのコードが実際に何をしているのか分かりません。申し訳ありませんが、私は訂正する準備ができていますが、これは「私はセマフォーで非現実的で奇妙なことをしています。あなたがセマフォを作成してそれを破壊しないなら、あなたは大丈夫ですか? –

+0

ええ、それは私の例のコードを使用するたびに繰り返すことができます。私はsem_initのいくつかのマニュアルページを読んだが、多くのスレッドで同じsemを初期化しないと言っていますが、 sem_varを2回実行します。コードはsem_waitの内容を作成するだけのものではありません.syscall(futex_wake)と呼ばれるコードをアセンブルしてください。ただし、このシステムコールをダンプしないでください。 – user1310866

答えて

0

あなたの問題はkeyへのアクセスにあると思います。共有変数へのアクセスがアトミックであるという保証はありません。特に、コンパイラはメモリからの値の読み出しを最適化し、別のスレッドで行われた値の変更を認識しないようにすることができます。

オプティマイザが起動しないようにするには、key変数volatileを宣言する必要があります。しかし、私はあなたのプログラムを書いたやり方が、スレッドが修正されたことを保証するメモリ障壁があることを保証するとは確信していません同時書き込みでは混在していません。

最新のC11には、アクセスがアトミックであることを保証するために_Atomicもあります。しかし、C11はまだ完全には実装されていません(その機能を持つコンパイラがあるかもしれません)。 C11にはmutexがあり、セマフォはロック構造ではないため、セマフォには問題があります。これら2つの機能がどのように連携するかはまだ規定されていません。

+0

あなたはgdbを使って段階的に最適化を捨てることを意味しますので、トレースシステムでは実際にexecで実行されていませんでしたか?はい、righ.iはシステムタップでこれを確認しました。どうもありがとうございました! – user1310866

関連する問題