Можно ли использовать мьютекс в многопроцессорном случае в 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 у них есть концепция именованных мьютексов, которая позволяет использовать мьютексы между процессами.