shm_ctl()

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

Прототип:

#include <sys/mman.h>
int shm_ctl( int fd,
int flags,
uint64_t paddr,
uint64_t size );

Аргументы:

fd
Дескриптор файла, связанный с объектом в разделяемой области памяти, возвращаемый функцией shm_open().
flags
Один или несколько битов, определенных в <sys/mman.h>:
SHMCTL_ANON
выделить анонимную память.
SHMCTL_GLOBAL
любое отображение с объектом может быть глобальным для всех процессов.
SHMCTL_HIGHUSAGE
объект часто используется и система должна стремиться ускорить доступ к нему.
SHMCTL_LAZY
откладывает фактическое выделение памяти до тех пор, пока на нее не появятся ссылаются. При создании анонимных объектов раделяемой области памяти (вызывая mmap() с MAP_ANON | MAP_SHARED и файловым дескриптором -1), флаг MAP_LAZY неявно устанавливает флаг SHMCTL_LAZY для объекта.
SHMCTL_LAZYWRITE
отображение этого объекта может использовать механизмы ленивой записи.
SHMCTL_LOWERPROT
система может отобразить этот объект с учетом меньшей защиты памяти в пользу лучшей производительности.
SHMCTL_PHYS
использовать физический адрес или выделить физически непрерывную память, если используется с SHMCTL_ANON.
SHMCTL_PRIV
отображение этого объекта может потребовать привилегированного доступа.

Note: Некоторые биты имеют особое значение для процессоров ARM.

paddr
Физический адрес для назначения объекту, если был установлен SHMCTL_PHYS в flags.
size
Новый размер объекта в байтах, независимо от флага ANON/PHYS.

Библиотека:

libc

Описание:

Функция shm_ctl() изменяет атрибуты объекта в разделяемой области памяти, идентифицированного дескриптором fd. Этот дескриптор является значением, возвращаемым shm_open().


Note:
  • Комбинация SHMCTL_ANON | SHMCTL_PHYS ведет себя так же, как и для mmap(): это указывает на необходимость выделения физически непрерывной оперативной память.

  • На целевых устройствах ARM, после вызова shm_ctl(), размер объекта разделяемой памяти изменить нельзя. Для этого необходимо отменить отображение и пересоздать объект.

  • Если указать флаг SHMCTL_PHYS, то paddr и size должны быть кратны размеру страницы (sysconf( _SC_PAGE_SIZE )).

Функция shm_ctl_special() аналогична shm_ctl(), но имеет дополнительный аргумент, зависящий от процессора.

Флаги для процессоров ARM

Для процессоров ARM поведение различных комбинаций flags может отличаться от других архитектур:

SHMCTL_ANON
Создать объект в разделяемой области памяти, используя анонимную память (т.е. заполненную нулями, динамически выделяемую ОЗУ). Не гарантируется, что эта память будет физически непрерывной. При использовании mmap(), она отображается в обычное адресное пространство процесса, поэтому на отображение распространяется ограничение в 32М адресного пространства на ARM.
SHMCTL_ANON | SHMCTL_PHYS
Аналогично SHMCTL_ANON, за исключением того, что выделенная память будет физически непрерывна. При использовании mmap(), она отображается в обычное адресное пространство процесса, поэтому на отображение распространяется ограничение в 32М адресного пространства на ARM.
SHMCTL_ANON | SHMCTL_GLOBAL
Выделить память как для SHMCTL_ANON. При использовани mmap(), она отображается в глобально видимый адрес за пределами обычного адресного пространства процесса. Это позволяет объекту иметь размер до 1 ГБ.

Если более чем один процесс отображает объект, он появляется по одному и тому же виртуальному адресу во всех процессах, которые его отображают. Этот виртуальный адрес назначается во время выполнения первого mmap() к объекту.

Вызов mmap() должен отображать весь объект (т.е. смещение должно быть 0, len должен быть равен размеру объекта, установленному при вызове shm_ctl()).

Объекты защищены таким образом, что только те процессы, которые отобразили данный объект, могут получить к нему доступ. Любой другой процесс, который пытается получить доступ к (глобально видимому) виртуальному адресу потерпит неудачу. Это влияет на процессы переключения контекстов, поскольку таблицы страниц MMU должны быть изменены для создания и удаления разрешений доступа при каждом переключении контекста.

Дополнительные затраты на эту операцию во время переключения контекста включают изменение одной записи таблицы уровня 1 для каждого мегабайта отображения с последующей очисткой TLB.
SHMCTL_ANON | SHMCTL_GLOBAL | SHMCTL_PRIV
То же, что SHMCTL_ANON | SHMCTL_GLOBAL, за исключением того, что защита для каждого процесса не выполняется. Вместо этого устанавливаются права доступа для (глобального) отображения, так что только процессы, имеющие привилегии ввода-вывода (т.е. вызвавшие ThreadCtl() с помощью команды NTO_TCTL_IO), могут получить доступ к отображениям.

Это позволяет избежать влияния на производительность во время переключения контекста, но обеспечивает потенциальный доступ любому процессу, имеющему привилегии ввода-вывода. Привилегии ввода-вывода обычно требуются только для драйверов или других системных процессов, поэтому эта комбинация обеспечивает некоторую защиту от потенциального доступа со стороны обычных пользовательских процессов.
SHMCTL_ANON | SHMCTL_GLOBAL | SHMCTL_LOWERPROT
То же, что SHMCTL_ANON | SHMCTL_GLOBAL, за исключением того, что защита для каждого процесса не выполняется; любой процесс может получить доступ к отображениям.

Это позволяет избежать влияния на производительность во время переключения контекста, а также не требует привилегий ввода-вывода для доступа к отображениям. Однако нет никакой защиты от потенциального доступа других процессов.
SHMCTL_PHYS
Создать объект для отображения физического адреса, указанного параметром смещения, с вызовом shm_ctl().

При использовании mmap(), объект отображается с глобально видимым адресом вне обычного адресного пространства процесса. Это позволяет объекту иметь размер до 1 ГБ. Всем отображениям принудительно устанавливается PROT_NOCACHE, чтобы избежать множественных ссылок в кэше (из-за виртуально индексированного кэша ARM). Каждый процесс получает новое отображение объекта. Только те процессы, которые отобразили объект, могут получить к нему доступ. Любой другой процесс, который пытается получить доступ к (глобально видимому) виртуальному адресу, потерпит неудачу. Это влияет на переключение контекста в процесс отображения и обратно, поскольку таблицы страниц MMU должны быть изменены для создания и удаления прав доступа при каждом переключении контекста. Дополнительные затраты на эту операцию во время переключения контекста включают изменение одной записи таблицы уровня 1 для каждого мегабайта сопоставления с последующей очисткой TLB.
SHMCTL_PHYS | SHMCTL_PRIV
То же, что и SHMCTL_PHYS, за исключением того, что отображения не защищены. Вместо этого доступ разрешен только процессам с привилегиями ввода-вывода. Это позволяет избежать влияния на производительность во время переключения контекста.
SHMCTL_PHYS | SHMCTL_LOWERPROT
То же, что и SHMCTL_PHYS, за исключением того, что отображения не защищены. Доступ разрешен для любого процесса.
SHMCTL_PHYS | SHMCTL_GLOBAL
То же, что и SHMCTL_PHYS, за исключением того, что все процессы, отображающие объект, используют один и тот же виртуальный адрес. Этот виртуальный адрес назначается первым вызовом mmap() при отображении объекта.

Поскольку все процессы используют один и тот же (глобальный) виртуальный адрес, эти отображения принудительно не используют PROT_NOCACHE. Если этот флаг необходим, следует указать PROT_NOCACHE при вызове mmap(). Только те процессы, которые отобразили объект, могут получить к нему доступ. Любой другой процесс, который попытается получить доступ к (глобально видимому) виртуальному адресу, потерпит неудачу. Это влияет на переключение контекста в процесс отображения и обратно, поскольку таблицы страниц MMU должны быть изменены для предоставления и удаления разрешений доступа при каждом переключении контекста. Дополнительные затраты на эту операцию во время переключения контекста включают изменение одной записи таблицы уровня 1 для каждого мегабайта сопоставления с последующей очисткой TLB.
SHMCTL_PHYS | SHMCTL_GLOBAL | SHMCTL_PRIV
То же, что SHMCTL_PHYS | SHMCTL_GLOBAL, за исключением того, что отображения не защищены. Вместо этого доступ разрешен только процессам с привилегиями ввода-вывода. Это позволяет избежать влияния на производительность во время переключения контекста.
SHMCTL_PHYS | SHMCTL_GLOBAL | SHMCTL_LOWERPROT
То же, что SHMCTL_PHYS | SHMCTL_GLOBAL, за исключением того, что отображения не защищены. Вместо этого доступ разрешен любому процессу. Это позволяет избежать влияния на производительность во время переключения контекста.

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

0
Успешное завершение.
-1
Возникла ошибка. Код ошибки записан в errno.

Коды ошибок:

EINVAL
Указана недопустимая комбинация флагов или объект из разделяемой области памяти уже является «специальным».

Примеры:

Следующие примеры взаимосвязаны. Сначала необходимо запустить sharephyscreator, а затем sharephysuser.

Процесс sharephyscreator отображает область физической памяти, а затем накладывает на нее объект из разделяемой области памяти. Процесс sharephysuser открывает этот объект из разделямой области памяти для доступа к физической памяти.

/*
* sharephyscreator.c
*
* This maps in an area of physical memory and then
* overlays it with a shared memory object. This way, another process
* can open that shared memory object in order to access the physical
* memory. The other process in this case is sharephysuser.
*
* Note that the size and address that you pass to shm_ctl() must be
* even multiples of the page size (sysconf(_SC_PAGE_SIZE)).
*
* For VGA color text mode video memory:
* sharephyscreator /wally b8000
* Note that for VGA color text mode video memory, each character
* is followed by an attribute byte. Here we just use a space.
*/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/stat.h>
char *progname = "sharephyscreator";
main( int argc, char *argv[] )
{
char *text = "H e l l o w o r l d ! ";
int fd, memsize;
char *ptr, *name;
uint64_t physaddr;
if ( argc != 3 )
{
printf( "Use: sharephyscreator shared_memory_object_name "
"physical_address_in_hex\n" );
printf( "Example: sharephyscreator wally b8000\n" );
exit( EXIT_FAILURE );
}
name = argv[1];
physaddr = atoh( argv[2] );
memsize = sysconf( _SC_PAGE_SIZE ); /* this should be enough
for our string */
/* map in the physical memory */
ptr = mmap_device_memory( 0, memsize, PROT_READ|PROT_WRITE, 0, physaddr );
if ( ptr == MAP_FAILED )
{
printf( "%s: mmap_device_memory for physical address %llx failed: %s\n",
progname, physaddr, strerror( errno ) );
exit( EXIT_FAILURE );
}
/* open the shared memory object, create it if it doesn't exist */
fd = shm_open( name, O_RDWR | O_CREAT, 0 );
if ( fd == -1 )
{
printf( "%s: error creating the shared memory object '%s': %s\n",
progname, name, strerror( errno ) );
exit( EXIT_FAILURE );
}
/* overlay the shared memory object onto the physical memory */
if ( shm_ctl( fd, SHMCTL_PHYS, physaddr, memsize ) == -1 )
{
printf( "%s: shm_ctl failed: %s\n", progname, strerror( errno ) );
close( fd );
munmap( ptr, memsize );
shm_unlink( name );
exit( EXIT_FAILURE );
}
strcpy( ptr, text ); /* write to the shared memory */
printf( "\n%s: Physical memory mapped in, shared memory overlaid onto it.\n"
"%s: Wrote '%s' to physical memory.\n"
"%s: Sleeping for 20 seconds. While this program is sleeping\n"
"%s: run 'sharephysuser %s %d'.\n",
progname, progname, ptr, progname, progname, name,
strlen( text ) + 1 );
sleep( 20 );
printf( "%s: Woke up. Cleaning up and exiting ...\n", progname );
close( fd );
munmap( ptr, memsize );
shm_unlink( name );
}

Следующий код характеризует sharephyscreator.

/*
* sharephysuser.c
*
* This one is meant to be run in tandem with sharephyscreator.
*
* Run it as: sharephysuser shared_memory_object_name length
* Example: sharephysuser wally 49
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/stat.h>
char *progname = "sharephysuser";
main( int argc, char *argv[] )
{
int fd, len, i;
char *ptr, *name;
if ( argc != 3 )
{
fprintf( stderr, "Use: sharephysuser shared_memory_object_name length\n" );
fprintf( stderr, "Example: sharephysuser wally 49\n" );
exit( EXIT_FAILURE );
}
name = argv[1];
len = atoi( argv[2] );
/* open the shared memory object */
fd = shm_open( name, O_RDWR, 0 );
if ( fd == -1 )
{
fprintf( stderr, "%s: error opening the shared memory object '%s': %s\n",
progname, name, strerror( errno ) );
exit( EXIT_FAILURE );
}
/* get a pointer to a piece of the shared memory, note that we
only map in the amount we need to */
ptr = mmap( 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
if ( ptr == MAP_FAILED )
{
fprintf( stderr, "%s: mmap failed: %s\n", progname, strerror( errno ) );
exit( EXIT_FAILURE );
}
printf( "%s: reading the text: ", progname );
for ( i = 0; i < len; i++ )
printf( "%c", ptr[i] );
printf( "\n" );
close( fd );
munmap( ptr, len );
}

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

ЗОСРВ «Нейтрино»

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

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

mmap(), munmap(), mprotect(), shm_ctl_special(), shm_open(), shm_unlink(), ThreadCtl()




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