Задать атрибуты для объекта в разделяемой области памяти
#include <sys/mman.h>int shm_ctl( int fd,int flags,uint64_t paddr,uint64_t size );
<sys/mman.h>
: MAP_ANON
| MAP_SHARED
и файловым дескриптором -1
), флаг MAP_LAZY
неявно устанавливает флаг SHMCTL_LAZY
для объекта. SHMCTL_ANON
. Некоторые биты имеют особое значение для процессоров ARM. |
SHMCTL_PHYS
в flags.libc
Функция shm_ctl() изменяет атрибуты объекта в разделяемой области памяти, идентифицированного дескриптором fd. Этот дескриптор является значением, возвращаемым shm_open().
|
Функция shm_ctl_special() аналогична shm_ctl(), но имеет дополнительный аргумент, зависящий от процессора.
Флаги для процессоров ARM
Для процессоров ARM поведение различных комбинаций flags может отличаться от других архитектур:
SHMCTL_ANON
, за исключением того, что выделенная память будет физически непрерывна. При использовании mmap(), она отображается в обычное адресное пространство процесса, поэтому на отображение распространяется ограничение в 32М адресного пространства на ARM. SHMCTL_ANON
. При использовани mmap(), она отображается в глобально видимый адрес за пределами обычного адресного пространства процесса. Это позволяет объекту иметь размер до 1 ГБ. 0
, len должен быть равен размеру объекта, установленному при вызове shm_ctl()). SHMCTL_ANON
| SHMCTL_GLOBAL
, за исключением того, что защита для каждого процесса не выполняется. Вместо этого устанавливаются права доступа для (глобального) отображения, так что только процессы, имеющие привилегии ввода-вывода (т.е. вызвавшие ThreadCtl() с помощью команды NTO_TCTL_IO
), могут получить доступ к отображениям. SHMCTL_ANON
| SHMCTL_GLOBAL
, за исключением того, что защита для каждого процесса не выполняется; любой процесс может получить доступ к отображениям. PROT_NOCACHE
, чтобы избежать множественных ссылок в кэше (из-за виртуально индексированного кэша ARM). Каждый процесс получает новое отображение объекта. Только те процессы, которые отобразили объект, могут получить к нему доступ. Любой другой процесс, который пытается получить доступ к (глобально видимому) виртуальному адресу, потерпит неудачу. Это влияет на переключение контекста в процесс отображения и обратно, поскольку таблицы страниц MMU должны быть изменены для создания и удаления прав доступа при каждом переключении контекста. Дополнительные затраты на эту операцию во время переключения контекста включают изменение одной записи таблицы уровня 1 для каждого мегабайта сопоставления с последующей очисткой TLB. SHMCTL_PHYS
, за исключением того, что отображения не защищены. Вместо этого доступ разрешен только процессам с привилегиями ввода-вывода. Это позволяет избежать влияния на производительность во время переключения контекста. SHMCTL_PHYS
, за исключением того, что отображения не защищены. Доступ разрешен для любого процесса. SHMCTL_PHYS
, за исключением того, что все процессы, отображающие объект, используют один и тот же виртуальный адрес. Этот виртуальный адрес назначается первым вызовом mmap() при отображении объекта. PROT_NOCACHE
. Если этот флаг необходим, следует указать PROT_NOCACHE
при вызове mmap(). Только те процессы, которые отобразили объект, могут получить к нему доступ. Любой другой процесс, который попытается получить доступ к (глобально видимому) виртуальному адресу, потерпит неудачу. Это влияет на переключение контекста в процесс отображения и обратно, поскольку таблицы страниц MMU должны быть изменены для предоставления и удаления разрешений доступа при каждом переключении контекста. Дополнительные затраты на эту операцию во время переключения контекста включают изменение одной записи таблицы уровня 1 для каждого мегабайта сопоставления с последующей очисткой TLB. SHMCTL_PHYS
| SHMCTL_GLOBAL
, за исключением того, что отображения не защищены. Вместо этого доступ разрешен только процессам с привилегиями ввода-вывода. Это позволяет избежать влияния на производительность во время переключения контекста. SHMCTL_PHYS
| SHMCTL_GLOBAL
, за исключением того, что отображения не защищены. Вместо этого доступ разрешен любому процессу. Это позволяет избежать влияния на производительность во время переключения контекста.
Следующие примеры взаимосвязаны. Сначала необходимо запустить 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 enoughfor 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 weonly 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 системной библиотеки