shm_open()

Открыть объект в разделяемой области памяти

Прототип:

#include <fcntl.h>
#include <sys/mman.h>
int shm_open( const char *name,
int oflag,
mode_t mode );

Аргументы:

name
Имя объекта в разделяемой области памяти, который необходимо открыть.
oflag
Комбинация следующих битов (определены в <fcntl.h>):
O_RDONLY
открыть только для чтения.
O_RDWR
открыть для чтения и записи.
O_CREAT
если объект разделяемой памяти существует, этот флаг не действует, за исключением случаев, отмеченных в разделе O_EXCL ниже. В противном случае создается объект в разделяемой области памяти и его права устанавливаются в соответствии со значением mode и маской создания режима файла для процесса.
O_EXCL
если установлены O_EXCL и O_CREAT, то shm_open() завершится с ошибкой, если объект разделяемой памяти существует. Операции проверки его существования и создание объекта, если такового не существует, являются атомарными по отношению к другим процессам, выполняющим shm_open(), открывая тот же объект в разделяемой памяти с помощью комбинации битов O_EXCL и O_CREAT.
O_TRUNC
если объект разделяемой памяти существует и успешно открыт с O_RDWR, размер объекта урезается до нулевой длины, но режим доступа и владелец не изменяются.
mode
Биты разрешения (права) для объекта памяти устанавливаются в значение mode, за исключением тех битов, которые установлены в маске создания файла для процесса. Для получения более подробной информации, см. umask(), и struct stat.

Библиотека:

libc

Описание:

Функция shm_open() возвращает файловый дескриптор, связанный с объектом в разделяемой области памяти, указанным в name. Этот файловый дескриптор используется другими функциями для обращения к объекту в разделяемой области памяти (например, mmap(), mprotect()). Флаг файлового дескриптора FD_CLOEXEC в fcntl() устанавливается для данного файлового дескриптора.

Аргумент name интерпретируется следующим образом:

name Новая запись в ространстве имен
entry CWD/entry
/entry /dev/shmem/entry
entry/newentry CWD/entry/newentry
/entry/newentry /entry/newentry

где CWD - это текущий рабочий каталог программы в момент, когда она вызвала shm_open().

Состояние объекта в разделяемой памяти, включая все связанные с ним данные, сохраняется до тех пор, пока объект в разделяемой области памяти не будет удален и оставшиеся ссылки на него во всех процессах не исчезнут.

Возвращаемое значение:

Неотрицательное целое число, представляющее неиспользуемый файловый дескриптор с минимальным номером. Если возникла ошибка функция возвращается -1, а код ошибки записывается в errno.

Коды ошибок:

EACCES
Отказано в разрешении на создание объекта в разделяемой области памяти. Объект в разделяемой области памяти существует и права, указанные в oflag, недопустимы; либо указан параметр O_TRUNC и разрешение на запись отклонено.
EEXIST
O_CREAT и O_EXCL установлены, а указанный объект в разделяемой области памяти уже существует.
EINTR
Вызов shm_open() был прерван сигналом.
EINVAL
Неявный вызов resmgr_open_bind() завершился с ошибкой.
ELOOP
Слишком много уровней вложенности символических ссылок или префиксов.
EMFILE
Данный процесс использует слишком много файловых дескрипторов.
ENAMETOOLONG
Длина аргумента name превышает NAME_MAX.
ENFILE
В системе открыто слишком много объектов в разделяемой области памяти.
ENOENT
O_CREAT не установлен и именованный объект в разделяемой области памяти не существует; O_CREAT установлен, и либо префикс имени не существует, либо аргумент name указывает на пустую строку.
ENOSPC
Недостаточно памяти для создания нового объекта в разделяемой области памяти.
ENOSYS
Функция shm_open() не поддерживается данной реализацией.

Примеры:

В данном примере создается объект в разделяемой области памяти, но работы с ним не производится:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <sys/mman.h>
int main( int argc, char** argv )
{
int fd;
unsigned *addr;
/* In case the unlink code isn't executed at the end */
if ( argc != 1 )
{
shm_unlink( "/bolts" );
return (EXIT_SUCCESS);
}
/* Create a new memory object */
fd = shm_open( "/bolts", O_RDWR | O_CREAT, 0777 );
if ( fd == -1 )
{
fprintf( stderr, "Open failed:%s\n", strerror( errno ) );
return (EXIT_FAILURE);
}
/* Set the memory object's size */
if ( ftruncate( fd, sizeof( *addr ) ) == -1 )
{
fprintf( stderr, "ftruncate: %s\n", strerror( errno ) );
return (EXIT_FAILURE);
}
/* Map the memory object */
addr = mmap( 0, sizeof( *addr ), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0 );
if ( addr == MAP_FAILED )
{
fprintf( stderr, "mmap failed: %s\n", strerror( errno ) );
return (EXIT_FAILURE);
}
printf( "Map addr is 0x%08x\n", addr );
/* Write to shared memory */
*addr = 1;
/*
* The memory object remains in
* the system after the close
*/
close( fd );
/*
* To remove a memory object
* you must unlink it like a file.
*
* This may be done by another process.
*/
shm_unlink( "/bolts" );
return (EXIT_SUCCESS);
}

В данном примере используется объект в разделяемой области памяти для обмена данными с порожденным новым процессом:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
main(int argc, char * argv[])
{
int fd;
unsigned *addr;
/* In case the unlink code isn't executed at the end */
if ( argc != 1 )
{
shm_unlink( "/bolts" );
return (EXIT_SUCCESS);
}
/* Create a new memory object */
fd = shm_open( "/bolts", O_RDWR | O_CREAT, 0777 );
if ( fd == -1 )
{
fprintf( stderr, "Open failed : %s\n", strerror( errno ) );
return (EXIT_FAILURE);
}
/* Set the memory object's size */
if ( ftruncate( fd, sizeof( *addr ) ) == -1 )
{
fprintf( stderr, "ftruncate : %s\n", strerror( errno ) );
return (EXIT_FAILURE);
}
/* Map the memory object */
addr = mmap( 0, sizeof( *addr ), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0 );
if ( addr == MAP_FAILED )
{
fprintf( stderr, "mmap failed:%s\n", strerror( errno ) );
return (EXIT_FAILURE);
}
printf( "Map addr is %6.6X\n", addr );
printf( "Press break to stop.\n" );
sleep( 3 ); /* So you can read above message */
/* We unlink so object goes away on last close. */
shm_unlink( "/bolts" );
*addr = '0';
if ( fork() )
{
for ( ; ; )
if ( *addr == '0' )
putc( *addr = '1', stderr );
else
sched_yield();
} else {
for ( ; ; )
if ( *addr == '1' )
putc( *addr = '0', stderr );
else
sched_yield();
}
return (EXIT_SUCCESS);
}

Классификация:

POSIX 1003.1 Shared Memory Objects

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Да
В потоке
Да

Тематические ссылки:

struct stat, fcntl(), ftruncate(), mmap(), munmap(), mprotect(), open(), shm_ctl(), shm_ctl_special(), shm_unlink(), sysconf()




Предыдущий раздел: Описание API системной библиотеки