UNIX in a nuthsell

Однажды мне припёрло разделить сегмент shared memory между разными пользователями, где один должен писать/читать, а другой только читать из сегмента. Учитывая, что права на элементы SysV IPC очень схожи на обычные права файла (разве что они не могут быть exec… впрочем нынче в linux вроде могут), то всё могло бы решится маской 0640, переданной вместе с флагами в shmget… Но это так не работало.

То есть так работало:

my $shmid = shmget(28282828, 1073741824, IPC_CREAT | 0660);
my $shmid = shmget(28282828, 1073741824, 0660);

И вот так уже нет, хотя должно:

my $shmid = shmget(28282828, 1073741824, IPC_CREAT | 0640);
my $shmid = shmget(28282828, 1073741824, 0640);

Если верить мурзилке, то для корректной работы достаточно запросить на клиенте сегмент с теми же параметрами, что и на владельце сегмента (конечно без флага IPC_CREAT). Но внезапно оказалось, что какие бы ты права не запросил на втором процессе (который делает shmget без IPC_CREAT), он пытается подключаться с сегменту в режиме записи, выдавая ошибку, если права на сегменте этого не позволяют. Это касается как групповых прав, так и «общих».

Короче, в linux есть ещё специфичный флаг SHM_RDONLY. И вот с ним то и надо вызывать shmget, если не хочешь, чтобы он пытался зацепить сегмент shared memory с правами на запись. То есть так работает:

my $shmid = shmget(28282828, 1073741824, IPC_CREAT | 0640);
my $shmid = shmget(28282828, 1073741824, SHM_RDONLY);

Теперь другой вопрос в том, что передать так параметры shmget’у не даёт ни IPC::ShareLite, ни IPC::Shareable. А значит придётся писать свой собственный велосипед вокруг IPC::SharedMem и Storable.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

98 ÷ = 98