Публичный аккаунт WeChat:Чжэн Эрдос
Подпишитесь, чтобы узнать большеNginx
знание. Любые вопросы или предложения, пожалуйста, оставьте сообщение в публичном аккаунте;
Обратите внимание на официальный аккаунт, интересные и содержательные статьи будут доставлены в ближайшее время!
Общая память
Общая память — это самый простой метод межпроцессного взаимодействия в Linux. Он создает непрерывное линейное адресное пространство в памяти с помощью системных вызовов mmap или shmget, которые можно освободить с помощью системных вызовов munmap или shmdt. Преимущества использования разделяемой памяти: Когда несколько процессов используют один и тот же участок разделяемой памяти, если какой-либо процесс изменяет содержимое в разделяемой памяти, другие процессы могут получить измененное содержимое, обратившись к этой разделяемой памяти.
структура данных
Структура данных, используемая nginx, выглядит следующим образом:
1 typedef struct {
2 u_char *addr; /* 共享内存的起始地址 */
3 size_t size; /* 共享内存的长度 */
4 ngx_str_t name; /* 共享内存的名字 */
5 ngx_log_t *log; /* 记录日志的对象 */
6
7/* unsigned exists:1; */ /*共享内存是否已经分配过,1:已经分配 */
8 ngx_uint_t exists;
9} ngx_shm_t;
API общей памяти
nginx
оперативная разделяемая памятьAPI
Их два, а именно:
1ngx_int_t ngx_shm_alloc(ngx_shm_t *shm); /* 分配新的共享内存 */
2void ngx_shm_free(ngx_shm_t *shm); /*释放已经存在的共享内存 */
Метод реализации
вышеnginx
Два операционных общей памяти вapi
. Мы должны использовать два вышеупомянутыхapi
Работает с общей памятью.
Для портативности,nginx
Есть три способа достичь выше дваapi
, три способа следующие:
1. Использовать без файлов сопоставленияmmap
Выделить общую память
2, с/dev/zero
использование файлаmmap
Карта общей памяти.
3. Используйтеshmget
вызов для выделения общей памяти
Анализ исходного кода
Исходный код очень прост, мыmmap
Проведение простого анализа
1#if (NGX_HAVE_MAP_ANON)
2
3ngx_int_t
4ngx_shm_alloc(ngx_shm_t *shm)
5{
6 /* MAP_ANON:不使用文件映射方式,因此fd,offset无用,相当于在内存开辟一块空间用于共享,由master创建 */
7 shm->addr = (u_char *) mmap(NULL, shm->size,
8 PROT_READ|PROT_WRITE,
9 MAP_ANON|MAP_SHARED, -1, 0);
10
11 if (shm->addr == MAP_FAILED) {
12 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
13 "mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size);
14 return NGX_ERROR;
15 }
16
17 return NGX_OK;
18}
19
20
21void
22ngx_shm_free(ngx_shm_t *shm)
23{
24 if (munmap((void *) shm->addr, shm->size) == -1) {
25 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
26 "munmap(%p, %uz) failed", shm->addr, shm->size);
27 }
28}
29
30#elif (NGX_HAVE_MAP_DEVZERO)
можно увидетьngx_shm_alloc
иngx_shm_free
это такmmap
иmunmap
упакован отдельно. и используетсяMAP_ANON
, заключается в том, чтобы освободить место в памяти для общей памяти, а не для сопоставления файлов на жестком диске.
Как nginx использует разделяемую память
Во-первых, мы должны знать: по умолчанию, поfork
Порожденный дочерний процесс не разделяет область памяти со своим родительским процессом. ноmaster
иworker
Процесс является родительско-дочерним процессом, что мне делать? как сделатьmaster
процесс сworker
Как насчет общей памяти процесса?
Решениеmmap
изflags
параметр.master
В процессе звонкаfork
указать доflags
заMAP_SHARED
звонитьmmap
,В настоящее время,POSIX
Это делается для того, чтобы отношения отображения памяти в родительском процессе сохранялись в дочернем процессе, а изменения, внесенные родительским процессом в разделяемую память, могли быть видны дочернему процессу, и наоборот. Итак, поток:master
процесс в памяти сMAP_SHARED
способ открыть часть общей памяти и сопоставить ее с областью общей памяти в адресном пространстве своего собственного процесса, а затемmaster
перечислитьfork
, дочерний процесс является производным, и дочерний процесс также унаследует эту общую область памяти в своем собственном адресном пространстве. Это решает проблему.
функции mmap/munmap
1void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
Возвращаемое значение: успех: начальный адрес отображаемой области; ошибка:MAP_FAILED
addr
: указанный дескриптор fd должен быть сопоставлен с начальным адресом адресного пространства процесса, как правилоNULL
, Это означает, что ядро выберет свой собственный начальный адресlen
: Сопоставить количество байтов, сопоставленных на промежуточное пространствоprot
: мы можем обрабатывать данные в этой общей памяти следующим образом:
prot | инструкция |
---|---|
PROT_READ | данные доступны для чтения |
PROT_WRITE | данные доступны для записи |
PROT_EXEC | Данные могут быть реализованы |
PROT_NONE | Данные недоступны |
flags
: Является ли поведение изменения данных в области разделяемой памяти общим или частным, т. е. видимым для всех процессов или только для этого процесса. следующее:
flags | инструкция |
---|---|
MAP_SHARED | Изменения доступны |
MAP_PRIVATE | Изменения являются частными |
MAP_FIXED | Точная интерпретация параметров ADDR |
fd
: Сопоставленный файловый дескрипторoffset
: начальная позиция отображаемой области в файле.
Подробности смотрите на рисунке ниже:
нужно знать, это:nginx
Общая память — это не то, что находится в отображаемом файле. когдаflags
параметрMAP_ANON
илиMAP_ANONYMOUS
, что означает, что он не отображается из файла, а открывает только непрерывное линейное адресное пространство из памяти в качестве общей памяти. Поэтому в этом случаеfd
иoffset
Параметры бессмысленны, устанавливайте их отдельно-1
и0
Вот и все.
Чтобы удалить отображение из адресного пространства процесса, вызовитеmunmap
.
1int munmap(void *addr, size_t len);
Успех: 0 Ошибка: -1
Друзья, которым понравилась эта статья, пожалуйста, нажмите и удерживайте изображение, чтобы подписаться на номер подписки Чжэн Эрдос, более интересный контент будет доставлен как можно скорее.