web-dev-qa-db-ja.com

Linux / UNIXのマルチプロセッシングケースでミューテックスを使用することは可能ですか?

これはインタビューの質問です。

Linux/UNIXのマルチプロセッシングケースでミューテックスを使用することは可能ですか?

私の考え:いいえ、異なるプロセスには別々のメモリ空間があります。

mutexはマルチスレッドにのみ使用されます。

セマフォは、同期を行うマルチプロセッシングに使用されます。

正しい ?

コメントを歓迎します。

ありがとう

21
user1002288
 Mutual exclusion locks (mutexes)  prevent  multiple  threads
 from simultaneously executing critical sections of code that
 access shared data (that is, mutexes are used  to  serialize
 the  execution  of  threads).  All mutexes must be global. A
 successful call for a mutex lock  by  way  of   mutex_lock()
 will  cause  another  thread that is also trying to lock the
 same mutex to block until the owner thread unlocks it by way
 of   mutex_unlock().  Threads  within  the  same  process or
 within other processes can share mutexes.

 Mutexes can synchronize threads within the **same  process**  or
 in  ***other   processes***.  Mutexes  can  be used to synchronize
 threads between processes if the mutexes  are  allocated  in
 writable  memory  and shared among the cooperating processes
 (see mmap(2)), and have been initialized for this task.

初期化ミューテックスは、そのミューテックスの初期化に暗黙的または明示的に渡される引数に応じて、プロセス内またはプロセス間です。静的に割り当てられたミューテックスは、明示的に初期化する必要はありません。デフォルトでは、静的に割り当てられたミューテックスはすべてゼロで初期化され、そのスコープは呼び出しプロセス内に設定されます。

 For inter-process synchronization, a mutex needs to be allo-
 cated   in  memory shared between these processes. Since the
 memory for such a mutex must be allocated dynamically,   the
 mutex needs to be explicitly initialized using mutex_init().
28
laksbv

process-shared mutex を使用することはかなり可能です。

実際、最新のアプリケーションでは、セマフォの柔軟性が低いため、プロセス共有ミューテックスとプロセス共有条件変数を使用することを好みます。

2004年にRed Hat Linuxを使用したことを覚えていますが、当時はプロセス共有ミューテックスと条件変数の両方をサポートしていました。

8

そうでもない。 POSIXスレッドには process-shared attribute という概念があり、これを使用して、複数のプロセスで操作できるmutexを作成できます。

このようなミューテックスを共有メモリに配置して、複数のプロセスがすべて取得できるようにすることができます。

LINUXがこれを実装しているかどうかはわかりませんが、不必要に複雑に見えるため、使用する必要がありませんでした。

属性の有用な精度については、 この質問 への私の答えを参照してください。

5
paxdiablo

プロセスの存続期間にわたって相互排除を保証できるように、名前付きミューテックスを探していました(特定のプロパティセットごとに1つのプロセスのみが実行されるようにします)。私はそれを見つけませんでした(十分に見えなかったように見えます)。そのため、抽象UNIXドメインソケットを使用して、Linuxに独自の疑似名前付きミューテックスを実装しました。そのソケットへの単一のbind()のみが成功します。もう1つの良い点は、プロセスが停止し、ソケット自体をクリーンアップしない場合、OSが抽象UNIXドメインソケットをクリーンアップすることです。残念ながら、この擬似ミューテックスが使用可能になるまで「待機」する方法はわかりません。

抽象UNIXドメインソケットは、名前がヌルバイトで始まるUNIXドメインソケットです。ただし、バッファ全体が名前として使用されるため、memcpyやstrcpyに部分的な文字列を入れないようにするか、最初にバッファ全体を何らかの文字で埋めるようにする必要があることに注意してください。

最初のbind()以外はすべて、EADDRINUSEのerrnoで失敗します。

// Create an abstract socket to use as a mutex.                             

int err;
int mutex_sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (mutex_sock == -1)
    {
    err = errno;
    printf("main, failed creating mutex socket: %s\n",
            get_error_string(errno, error_string, sizeof(error_string)));
    log_event(LOG_LEVEL_ERROR, "main, failed creating mutex socket: "
            "%s", get_error_string(errno, error_string,
            sizeof(error_string)));
    errno = err;
    goto done;
    }

// Bind to abstract socket.  We use this as a sort of named mutex.          

struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.Sun_family = AF_UNIX;
strncpy(addr.Sun_path + 1, socket_name, sizeof(addr.Sun_path) - 2);
result = bind(mutex_sock, (struct sockaddr*) &addr, sizeof(addr));
if (result == -1)
    {
    err = errno;
    if (errno == EADDRINUSE)
        {
        printf("main, failed bind to mutex socket: %s.  "
                "Another instance must be running.\n",
                get_error_string(errno,
                error_string, sizeof(error_string)));
        log_event(LOG_LEVEL_ERROR, "main, failed bind to mutex socket: "
                "%s.  "
                "Another instance must be running.",
                get_error_string(errno,
                error_string, sizeof(error_string)));
        }
    else
        {
        printf("main, failed bind to mutex socket: %s\n",
                get_error_string(errno, error_string,
                sizeof(error_string)));
        log_event(LOG_LEVEL_ERROR, "main, failed bind to mutex socket: %s",
                get_error_string(errno, error_string,
                sizeof(error_string)));
        }
    errno = err;
    goto done;
    }

ありがとう、ニック

2
nickdu

はい、Linuxでは一般に、名前のないミューテックスしかありません。これは、プロセス間で動作できないためです。それを乗り越えるにはセマフォが必要です。

Windowsでは、名前付きミューテックスの概念があり、プロセス間でミューテックスを使用できます。

0
Gargi Srinivas