4

ipc に共有メモリとセマフォを使用するプログラムを作成しています。共有メモリとセマフォを作成するメイン サーバー プロセスが 1 つあります。クライアント プロセスはいくつでも共有メモリにアタッチでき、許可されている場合は読み書きできます。セマフォは、読み取りと書き込みを制御するブロッキング メカニズムを提供します。クライアントを終了しようとする場合を除いて、すべて正常に動作します。共有メモリにアクセスするためのセマフォ ブロックはスレッド内にあり、プロセスの終了時にセマフォ ブロックを解放する方法がないため、スレッドは正しく終了します。これについてどうすればいいですか?これは Linux 用です。

具体的には、1 つの shm と 2 つの sem があります。最初の sem は書き込みをブロックし、2 番目のブロックは読み取りをブロックします。クライアントが何かを書き込む場合、クライアントは write sem が 0 になるのを待ってから、それを 1 に設定し、書き込み、次に read sem を 0 に設定します。これにより、待機しているサーバーが解放され、クライアントが書き込んだ内容が読み取られます。読み取りが完了すると、サーバーは書き込み sem を 0 に戻し、次のクライアントが書き込みを開始します。read sem が 0 のときに解放される semop 呼び出しでハングします。この semop 呼び出しはスレッド内にあり、メイン スレッドを終了させる前にそのスレッドを正しく終了する方法を理解する必要があります。

これは私がやりたいことの例ですが、機能していません (スリープはぶら下がっている semop 呼び出しのふりをしています):

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

void termination_handler (int signum) {
    printf( "Got Signal\n" );
}

void *threadfunc( void *parm ) {
    struct sigaction action;

    action.sa_handler = termination_handler;
    sigemptyset( &action.sa_mask );
    action.sa_flags = 0;

    sigaction( SIGUSR1, &action, NULL );

    printf("Thread executing\n");

    sleep( 100 ); // pretending to be the semaphore

    pthread_exit( NULL );
}

int main() {
    int       status;
    pthread_t threadid;
    int       thread_stat;

    status = pthread_create( &threadid, NULL, threadfunc, NULL );

    if ( status <  0) {
        perror("pthread_create failed");
        exit(1);
    }

    sleep( 5 );

    status = pthread_kill( threadid, SIGUSR1 );

    if ( status <  0 )
        perror("pthread_kill failed");

    status = pthread_join( threadid, (void *)&thread_stat );
    if ( status <  0 )
        perror("pthread_join failed");

    exit( 0 );
}
4

4 に答える 4

1

2 つ半の答えがあります。:)

まず、あなたのコード例は私のために機能します(Linux上): pthread_killは、いくつかのprintf sで明らかにされ、 sleepの戻り値を覚えているように、約5秒後に期待どおりにEINTRワーカースレッドのスリープを正常に上げます。AFAICT、特定のスレッドをシグナル割り込みしたい場合は、それを行っています。

第二に、試してみてくださいSEM_UNDO。このフラグは、 sembuf引数semopで渡されるsem_flgメンバーで設定でき、名前が示すように、プロセスの終了時にセマフォの調整を元に戻します。IIUC、クライアントを強制終了すると、そのクライアントはセマフォを不適切にロックしたままにします。 まさにこの状況のた​​めに作られました。SEM_UNDO

最後に、敬意を表して、ここでセマフォの論理を逆にしたのでしょうか? 私があなたの質問を読んだように、ゼロの semval は「リソースが解放されている」ことを示し、1 の semval は「リソースがロックされている」ことを示します (引用: 「...[クライアント] 書き込み sem が 0 になるのを待ち、それを 1 に設定します。 、書いています...」)。ただし、2 つ以上の書き込みクライアントが SysV sem がゼロになるのを待っている場合、それらはすべて一緒に解放されます。これはむしろ不快な競合状態であり、少なくとも予期しないセマフォの減少と増加につながる可能性があります。

于 2009-07-20T05:06:15.997 に答える
0

環境によっては、タイムアウトを使用してセマフォを取得することしかできない場合があります。タイムアウトするたびに、クローズスレッドが要求されているかどうかを確認し、単にあきらめてシャットダウンします。

于 2009-07-17T05:40:07.857 に答える