Можно ли использовать мьютекс в многопроцессорном случае в Linux/UNIX?

Это вопрос интервью.

Можно ли использовать мьютекс в многопроцессорном случае в Linux/UNIX?

Моя идея: Нет, разные процессы имеют раздельное пространство памяти.

mutex используется только для многопоточности.

Семафор

используется для многопроцессорной обработки для синхронизации.

правильно?

Любые комментарии приветствуются.

спасибо

Ответ 1

 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.

Initialize    Мьютексы являются либо внутрипроцессорными, либо межпроцессорными, в зависимости от    по аргументу, неявно или явно    инициализация этого мьютекса. Статически назначенный мьютекс    не требуется явно инициализировать; по умолчанию,    статически назначенный мьютекс инициализируется всеми нулями    и его область задана в пределах вызывающего процесса.

 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().

Ответ 2

Вполне возможно использовать мьютекс с совместным использованием процесса.

Фактически, современные приложения предпочитают использовать совместно используемый мьютез процесса вместе с переменной состояния процесса совместно с семафором, потому что последняя менее гибкая.

Я помню использование Red Hat Linux в 2004 году, и в то время он поддерживал как взаимные мьютексы процессов, так и переменные условия.

Ответ 3

Не совсем. Потоки POSIX имеют концепцию атрибут процесса, который можно использовать для создания мьютексов, которые могут управляться несколькими процессами.

Вы можете поместить такой мьютекс в общую память, чтобы все процессы могли получить к нему.

Ли LINXX реализует это. Я не уверен, мне никогда не приходилось использовать его, поскольку он кажется излишне сложным.

Для полезной точности атрибутов см. мой ответ на этот вопрос.

Ответ 4

Я искал именованный мьютекс, чтобы я мог обеспечить взаимное исключение для жизненного цикла процесса (убедитесь, что только один процесс запущен для некоторого набора свойств). Я не нашел ни одного (похоже, что я, возможно, не выглядел достаточно сложно), и поэтому я реализовал свой собственный псевдо-мьютекс в Linux с помощью абстрактного сокета домена UNIX. Только одно bind() для этого сокета будет успешным. Другая приятная вещь заключается в том, что ОС будет очищать абстрактный UNIX-домен, если процесс умирает и, таким образом, не очищает сам сокет. К сожалению, я не уверен, что вы можете "подождать" на этом псевдо-мьютексе, чтобы стать доступным.

Абстрактный сокет домена UNIX - это сокет домена UNIX, имя которого начинается с нулевого байта. Остерегайтесь, однако, я считаю, что весь буфер используется как имя, и поэтому вы хотите убедиться, что вы не просто memcpy или strcpy частичной строки в нем, либо если вы действительно убедитесь, что вы сначала заполнили весь буфер некоторым символом.

Все, кроме первого bind(), не будут выполнены с ошибкой EADDRINUSE.

// 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;
    }

Спасибо, Ник

Ответ 5

Да, вообще в Linux у нас есть только неназванные мьютексы, из-за которых они не могут работать между процессами. Нам нужен семафор, чтобы справиться с этим.

В Windows у них есть концепция именованных мьютексов, которая позволяет использовать мьютексы между процессами.