ENOSYSで失敗するsem_open()を停止するにはどうすればよいですか?
質問
2つのSlackware Linuxシステムがあり、POSIXセマフォ sem_open()
呼び出しが失敗し、errnoが38に設定されています。以下を再現するサンプルコード(CentOS / RedHatで正常に動作します)。
これを引き起こす可能性のあるカーネルまたはシステム構成オプションはありますか?その他の提案?
問題のあるシステムはSlackware 10.1.0カーネル2.6.11 /lib/librt-2.3.4.so /lib/libpthread-0.10.soですが、同じコードがはるかに古いRedHat 9カーネル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
はtrueであり、 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 <*> -lrt
if [ $? -ne 0 ] ; then exit ; fi
# Run
$( dirname <*>)/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をアップグレードする必要があるだけかもしれません。
Edit2:私が使用していると思うslackware 11では、2.6.13より新しいカーネルが必要と思われるNPTLスレッドライブラリ(/ lib / tls内のlib)を使用する必要があると思いますsem_openが機能します。
Edit3:a)/ dev / shmをマウントし、b)環境変数 LD_ASSUME_KERNEL
を2.6.13(すべてのカーネルバージョン)に設定することで、私が持っているslackware 11ボックスで動作するようになりました&gt; 2.6.12が機能します)。カーネルが2.6.11.11であっても動作するようですが、スレッドのような他のものは動作しないかもしれません。
他のヒント
スレッドライブラリの古いバージョンは、プロセス間のPOSIXセマフォの共有をサポートしていません。 man sem_init
pshared引数は、セマフォがローカルにあるかどうかを示します 現在のプロセス(psharedがゼロ)または複数の間で共有される プロセス(psharedはゼロではありません)。 LinuxThreadsは現在 プロセス共有セマフォをサポートするため、sem_initは常に psharedがゼロでない場合、エラーENOSYS。
sem_open()は名前付きセマフォを作成するため、常にプロセス間でそれらを共有しようとします。
Slackware 10でsem_init()を使用してプロセス間で匿名セマフォの共有をサポートするには
- libpthreadおよび(おそらく)librtをアップグレードします
- カーネルのアップグレード
さらに、sem_open()との名前付きセマフォの共有をサポートします
-
/ etc / fstab
に行を追加して、/ dev / shm
をtmpfstmpfs / dev / shm tmpfsデフォルト0 0
-
mount / dev / shm
を実行または再起動
「プロセス共有sema4が機能しない」」仮説は私にはいくらか理にかなっています。それがあなたに役立つというわけではありませんが、時間と傾向がある場合は、次のことを試して、「プロセス共有」がアスペクトは失敗しているものです:
-
非共有メモリでsem_initを使用してセマフォを作成します(スレッド用)。動作する場合、sema4sはプロセス内で動作します。
-
共有メモリで実験を繰り返します。プロセス間で機能するかどうかがわかります。 sema4を実際に使用して、プロセス間で機能するかどうかを確認する必要があることに注意してください。
プロセス間でセマフォを共有する別の方法は、SystemVセマフォを使用することです。
これらは、共有POSIXセマフォが機能しない場合でも機能します(少なくとも上記のシステムでは)。
posixメッセージキューで作業していたのと同じエラーmq_openがerrono 38(ENOSYS)で失敗しました。
回避策は、カーネル構成でPOSIX MESSGE QUEUEを有効にしてカーネルを再構築することです。
これにより、POSIXメッセージキューをサポートするカーネルが構築され、動作しました。
ありがとう