preface
We know, becausePHP
There is no multithreading model, soswoole
More use of multi process model, so the code is relatively more concise, reducing the blocking and synchronization of various thread locks, but it also brings a new problem: data synchronization. Compared with multithreading, process memory can be shared directly, and data synchronization between processes depends on shared memory. This article will explainswoole
Shared memory source code.
Pre knowledge:
-
mmap
Function usage:APUE learning notes – Advanced IO - Shared memory:APUE learning notes — interprocess communication
Shared memory data structure
typedef struct _swShareMemory_mmap
{
size_t size;
char mapfile[SW_SHM_MMAP_FILE_LEN];
int tmpfd;
int key;
int shmid;
void *mem;
} swShareMemory;
- be careful
mem
It’s avoid
Pointer of type, used to store the first address of shared memory. This member variable is equivalent to thethis
Pointer, through which you can accessswShareMemory
Each member of. -
size
Represents the size of shared memory (excludingswShareMemory
Structure size),mapfile[]
The name of the memory mapping file that represents the shared memory usage,tmpfd
Descriptor for the memory mapped file.key
Representative useSystem V
Ofshm
Shared memory created by a series of functionskey
Value,shmid
byshm
Shared memory created by a series of functionsid
(similar to FD), these two are notPOSIX
Standard definedapi
It has limited use.
Application and creation of shared memory
swoole
The function that is often called when applying for shared memory issw_shm_malloc
This function can anonymously request a large block of continuous shared memory for a process
void* sw_shm_malloc(size_t size)
{
swShareMemory object;
void *mem;
size += sizeof(swShareMemory);
mem = swShareMemory_mmap_create(&object, size, NULL);
if (mem == NULL)
{
return NULL;
}
else
{
memcpy(mem, &object, sizeof(swShareMemory));
return mem + sizeof(swShareMemory);
}
}
- from
sw_shm_malloc
Function can be seen, although we are applying forsize
However, the actual application memory is slightly larger, because it needs to be addedswShareMemory
This structure. When the function returns, it will not directly return the first memory address of the application, but copy itobject
After the value of each member variable, addswShareMemory
The size of the.
void *swShareMemory_mmap_create(swShareMemory *object, size_t size, char *mapfile)
{
void *mem;
int tmpfd = -1;
int flag = MAP_SHARED;
bzero(object, sizeof(swShareMemory));
#ifdef MAP_ANONYMOUS
flag |= MAP_ANONYMOUS;
#else
if (mapfile == NULL)
{
mapfile = "/dev/zero";
}
if ((tmpfd = open(mapfile, O_RDWR)) < 0)
{
return NULL;
}
strncpy(object->mapfile, mapfile, SW_SHM_MMAP_FILE_LEN);
object->tmpfd = tmpfd;
#endif
#if defined(SW_USE_HUGEPAGE) && defined(MAP_HUGETLB)
if (size > 2 * 1024 * 1024)
{
flag |= MAP_HUGETLB;
}
#endif
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flag, tmpfd, 0);
#ifdef MAP_FAILED
if (mem == MAP_FAILED)
#else
if (!mem)
#endif
{
swWarn("mmap(%ld) failed. Error: %s[%d]", size, strerror(errno), errno);
return NULL;
}
else
{
object->size = size;
object->mem = mem;
return mem;
}
}
- because
swoole
All the processes in the process are controlled bymaster
The process is established, that is, there is a kinship between the processes, soswShareMemory_mmap_create
Function directly withanonymous mapping
、(/dev/zero
How to use (equipment)mmap
There’s no way to build shared memoryopen
Specific shared memory file, or callshm_open
openPOSIX IPC
name. - It is worth noting that
MAP_HUGETLB
This islinux
kernel2.6.32
An introductionflags
To allocate shared memory using large pages. Big pages are relatively traditional4K
For small pages, generally speaking, common architectures provide two kinds of large page sizes, such as common2M
Big page and1G
Big page. Using a large page can reduce the number of page table entries, thus reducing the number of pagesTLB Miss
In order to improve the memory access performance of the system. Of course, there are advantages and disadvantages. Using large pages reduces the granularity and flexibility of memory management. If the program does not use a large amount of memory, using large pages may also cause a waste of memory.
Shared memorycalloc
calloc
Andmalloc
It’s the same, but one morenum
parameter
void* sw_shm_calloc(size_t num, size_t _size)
{
swShareMemory object;
void *mem;
void *ret_mem;
int size = sizeof(swShareMemory) + (num * _size);
mem = swShareMemory_mmap_create(&object, size, NULL);
if (mem == NULL)
{
return NULL;
}
else
{
memcpy(mem, &object, sizeof(swShareMemory));
ret_mem = mem + sizeof(swShareMemory);
bzero(ret_mem, size - sizeof(swShareMemory));
return ret_mem;
}
}
Shared memoryrealloc
realloc
Function is used to modify the size of the applied memory. The logic is very simple. First apply for new memory, copy it, and then release the old memory
void* sw_shm_realloc(void *ptr, size_t new_size)
{
swShareMemory *object = ptr - sizeof(swShareMemory);
void *new_ptr;
new_ptr = sw_shm_malloc(new_size);
if (new_ptr == NULL)
{
return NULL;
}
else
{
memcpy(new_ptr, ptr, object->size);
sw_shm_free(ptr);
return new_ptr;
}
}
Permission to modify shared memory
After the memory mapping is completed, read, write and execute permissions are markedPROT_READ
、PROT_WRITE
andPROT_EXEC
And other permissions can still be usedmprotect
System call.
int sw_shm_protect(void *addr, int flags)
{
swShareMemory *object = (swShareMemory *) (addr - sizeof(swShareMemory));
return mprotect(object, object->size, flags);
}
Release of shared memory
void sw_shm_free(void *ptr)
{
swShareMemory *object = ptr - sizeof(swShareMemory);
swShareMemory_mmap_free(object);
}
int swShareMemory_mmap_free(swShareMemory *object)
{
return munmap(object->mem, object->size);
}