Как мне остановить сбой sem_open() с помощью ENOSYS?
Вопрос
У меня есть две системы Slackware Linux, в которых семафор POSIX sem_open()
вызов завершается с ошибкой errno, равной 38.Пример кода для воспроизведения приведен ниже (код отлично работает на CentOS / RedHat).
Существуют ли какие-либо параметры конфигурации ядра или системы, которые могли бы вызвать это?Другие предложения?
Системы с проблемой - это Slackware 10.1.0 kernel 2.6.11 /lib / librt-2.3.4.so /lib / libpthread-0.10.so, но тот же код работает на гораздо более старом RedHat 9 kernel 2.4.20 /lib / librt-2.3.2.so /lib / tls / libpthread-0.29.so.(а также работает на ядре CentOS 5 2.6.18 /lib/librt-2.5.so /lib/i686/nosegneg/libpthread-2.5.so).
man sem_open
предполагает, что это errno означает sem_open()
не поддерживается системой.
#define ENOSYS 38 /* Function not implemented */
Тот Самый sem_open()
пользовательское пространство находится в librt
с которыми мы динамически связываемся и librt
присутствует в затронутых системах.
Затронутая система утверждает, что поддерживает семафоры POSIX: _POSIX_SEMAPHORES
является правдой и sysconf(_SC_SEMAPHORES)
подтверждает это.
Спасибо, Киран
Правка 1:Я добавил более подробную информацию об используемых версиях программного обеспечения и удалил некоторые не относящиеся к делу комментарии.
Правка 2:/dev/shm монтируется в хороших системах и не монтируется в плохих.Его установка не изменила поведение затронутых систем.Я думаю, что /dev/shm тоже необходим, но sem_open() выходит из строя до этого, и strace поддерживает это.
# /* Quick'n'dirty test program to illustrate sem_open failure
#Run this file to auto-build test and run as a.out
# Build
gcc $0 -lrt
if [ $? -ne 0 ] ; then exit ; fi
# Run
$( dirname $0)/a.out
exit
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>
int main(int argc, char *argv[]) {
const char *SEM_NAME = "SHRMEM_SCXL"; /* name of mutex */
sem_t *mutex = SEM_FAILED; /* ptr to mutex */
#ifdef _POSIX_SEMAPHORES
printf("_POSIX_SEMAPHORES %ld\n", _POSIX_SEMAPHORES);
#else
puts("Undefined");
#endif
printf("sysconf %s\n", sysconf(_SC_SEMAPHORES) ? "Yes" : "No" );
mutex = sem_open(SEM_NAME, O_CREAT, 0666, 1);
if (mutex == SEM_FAILED) printf("Failed %d\n", errno);
else {
puts("Success - pause while you check /dev/shm ");
sleep(5);
sem_close(mutex);
sem_unlink(SEM_NAME);
}
}
Решение
Смонтирован ли файл /dev/shm?Более старые версии slackware, возможно, не монтировали эту файловую систему при загрузке.Из /etc/fstab:
tmpfs /dev/shm tmpfs defaults 0 0
Редактировать:Вероятно, в конце концов, проблема не в этом.Я думаю, вам, возможно, просто нужно обновить ваше ядро или, возможно, даже librt.
Редактировать 2:Я думаю, что для slackware 11, который, я думаю, вы используете, вам понадобится ядро новее 2.6.13, чтобы использовать библиотеки потоков NPTL (библиотеки в /lib / tls), которые, по-видимому, необходимы для работы sem_open .
Редактировать 3:Мне удалось заставить его работать с коробкой slackware 11, которая у меня есть, путем а) монтирования /dev / shm и б) установки переменной окружения LD_ASSUME_KERNEL
до версии 2.6.13 (будет работать любая версия ядра > 2.6.12).Кажется, это работает, даже если ядро 2.6.11.11, но другие вещи, такие как потоки, могут и не работать.
Другие советы
Более старые версии библиотек потоков не поддерживают совместное использование семафоров POSIX между процессами.От man sem_init
Аргумент Pshared указывает, является ли семафор локальным для текущего процесса (Pshared равен нулю) или должен быть разделен между несколькими процессами (Pshared не равен нулю).LinuxThreads в настоящее время не поддерживает семафоры процесса, поэтому SEM_INIT всегда возвращается с ошибкой enosys, если Pshared не равна нулю.
Поскольку sem_open() создает именованные семафоры, она всегда пытается разделить их между процессами.
Для поддержки совместного использования анонимных семафоров между процессами с помощью sem_init() в Slackware 10.
- обновить libpthread и (возможно) librt
- обновить ядро
Кроме того, для поддержки совместного использования именованных семафоров с помощью sem_open().
добавить строку в
/etc/fstab
монтировать/dev/shm
как tmpfstmpfs /dev/shm значения по умолчанию tmpfs 0 0
бегать
mount /dev/shm
или перезагрузите компьютер
Гипотеза «разделяемые процессы sema4 не работают» имеет для меня некоторый смысл.Не то чтобы это вам помогло, но если у вас есть время и желание, вы можете попробовать следующее, чтобы увидеть, не является ли аспект «совместного процесса» тем, что не работает:
создайте семафор, используя sem_init в общей памяти (для потоков).Если это работает, то sema4s работают внутри процесса.
повторите эксперимент в общей памяти.Это должно сказать вам, работают ли они между процессами.Обратите внимание, что вам, возможно, придется попробовать ИСПОЛЬЗОВАТЬ sema4, чтобы увидеть, работает ли он между процессами.
Другой способ совместного использования семафора между процессами — использовать семафоры SystemV.
Они работают даже там, где общие семафоры POSIX не работают (по крайней мере, в системах, описанных выше).
Видеть http://www.linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html для примеров двух типов использования семафора.
Я работал с очередями сообщений posix и получил ту же ошибку, что и ошибка mq_open с ошибкой 38 (ENOSYS).
Задача состоит в том, чтобы перестроить kenel с включенной в конфигурации ядра ОЧЕРЕДЬЮ СООБЩЕНИЙ POSIX.
Это позволит создать ядро с поддержкой очереди сообщений POSIX, и у меня это сработало.
Спасибо