티스토리 뷰
프로세스 사이의 공유자원쓸때 문제점
프로세스가 fork()로 분기 되었을때의 상황입니다. 두개로 나뉨에 따라, 원래 프로세스가 가리키고 있던 메모리를 같이 가리키고 있습니다. Table1 이 부모프로세스이고, Table2가 자식 프로세스입니다. 먼저 저번에는 한개의 process만 메모리를 건드리고 있었다면 지금은 새로운 process가 생겨 두개의 process가 동시에 실제 메모리를 가리키고 있는상황입니다.
- READ상황
-두 프로세스가 동시에 VP 1을 읽으려고 한다고 가정할때, 동시에 읽는건 가능합니다. 읽는건 실제 메모리를 건드리지않고 데이터만 가져오는 과정이기 때문에 실제메모리에 변화가 없기에 괜찮습니다. - WRITE상황 (실제메모리의 공유자원을 변경할때)
-두 프로세스가 VP 1이라는 공유자원을 가지고 있을때 한 프로세스가 공유자원을 수정을 하게되면, 다른 프로세스입장에서도 공유자원이 바뀌기 때문에 이부분을 막기위해 복사과정이 일어나게됩니다.
Copy-on Write
-가상 메모리 기술 중 하나로 프로세스가 새로운 페이지를 복사할때 기존페이지를 공유하게 하고 필요한 경우에만 페이지를 복사하여 쓰는 방식입니다. 이는 메모리 사용량을 줄이는 효과가 있으며, fork()호출시 더욱 빠르게 수행할 수 있게 합니다.
맨위의 그림을 보시면 fork()로 프로세스가 만들어 졌을때 Table 1과 Table 2 는 같은 VP 1을 가리키고 있었습니다. 공유자원을 수정을 안하고 쓸때는 계속 그렇게 같은 공유자원을 가리키고 있지만, 공유자원의 수정(Write)이 일어나게될때에는 해당 공유자원을 새롭게 복사하여 만든후에 수정한 프로세스에서 그곳을 가리키는 방식으로 바뀌게 됩니다. 이런식으로 메모리자원을 절약할 수 있고 복사시에 속도도 빨라집니다.
mm_struct
-가상 메모리를 구현할 수 있게하는 정보인데, 커널에서 각각의 가상메모리를 관리하기 위해 mm_struct라는 구조체에 정보를 저장해 각 프로세스의 가상 메모리를 추적하고 관리합니다. mm_struct의 구조는 다음과 같습니다.
fork()로 프로세스 복사시 이 정보도 같이 복사가 됩니다.
struct mm_struct {
struct {
struct vm_area_struct *mmap; /* list of VMAs */
struct rb_root mm_rb;
/**
* @mm_users: The number of users including userspace.
*
* Use mmget()/mmget_not_zero()/mmput() to modify. When this
* drops to 0 (i.e. when the task exits and there are no other
* temporary reference holders), we also release a reference on
* @mm_count (which may then free the &struct mm_struct if
* @mm_count also drops to 0).
*/
atomic_t mm_users;
/**
* @mm_count: The number of references to &struct mm_struct
* (@mm_users count as 1).
*
* Use mmgrab()/mmdrop() to modify. When this drops to 0, the
* &struct mm_struct is freed.
*/
atomic_t mm_count;
unsigned long total_vm; /* Total pages mapped */
unsigned long locked_vm; /* Pages that have PG_mlocked set */
atomic64_t pinned_vm; /* Refcount permanently increased */
unsigned long data_vm; /* VM_WRITE & ~VM_SHARED & ~VM_STACK */
unsigned long exec_vm; /* VM_EXEC & ~VM_WRITE & ~VM_STACK */
unsigned long stack_vm; /* VM_STACK */
unsigned long def_flags;
spinlock_t arg_lock; /* protect the below fields */
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
} __randomize_layout;
/*
* The mm_cpumask needs to be at the end of mm_struct, because it
* is dynamically sized based on nr_cpu_ids.
*/
unsigned long cpu_bitmap[];
};
vm_area_struct
-mm_struct 내부에 있는 구조체로 mm_struct가 여러개를 가지고 있는 가상 메모리 영역의 정보를 담고 있는 구조체입니다.
fork()로 프로세스 복사시 이 정보도 같이 복사가 됩니다. 구조체의 정보는 다음과같습니다.
/*
* This struct describes a virtual memory area. There is one of these
* per VM-area/task. A VM area is any part of the process virtual memory
* space that has a special rule for the page-fault handlers (ie a shared
* library, the executable area etc).
*/
struct vm_area_struct {
/* The first cache line has the info for VMA tree walking. */
unsigned long vm_start; /* Our start address within vm_mm. */
unsigned long vm_end; /* The first byte after our end address
within vm_mm. */
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct *vm_next, *vm_prev;
struct rb_node vm_rb;
/*
* Largest free memory gap in bytes to the left of this VMA.
* Either between this VMA and vma->vm_prev, or between one of the
* VMAs below us in the VMA rbtree and its ->vm_prev. This helps
* get_unmapped_area find a free area of the right size.
*/
unsigned long rb_subtree_gap;
/* Second cache line starts here. */
struct mm_struct *vm_mm; /* The address space we belong to. */
/*
* Access permissions of this VMA.
* See vmf_insert_mixed_prot() for discussion.
*/
pgprot_t vm_page_prot;
unsigned long vm_flags; /* Flags, see mm.h. */
/*
* For areas with an address space and backing store,
* linkage into the address_space->i_mmap interval tree.
*/
struct {
struct rb_node rb;
unsigned long rb_subtree_last;
} shared;
/*
* A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
* list, after a COW of one of the file pages. A MAP_SHARED vma
* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
* or brk vma (with NULL file) can only be in an anon_vma list.
*/
struct list_head anon_vma_chain; /* Serialized by mmap_sem &
* page_table_lock */
struct anon_vma *anon_vma; /* Serialized by page_table_lock */
/* Function pointers to deal with this struct. */
const struct vm_operations_struct *vm_ops;
/* Information about our backing store: */
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
units */
struct file * vm_file; /* File we map to (can be NULL). */
void * vm_private_data; /* was vm_pte (shared mem) */
#ifdef CONFIG_SWAP
atomic_long_t swap_readahead_info;
#endif
#ifndef CONFIG_MMU
struct vm_region *vm_region; /* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMA
struct mempolicy *vm_policy; /* NUMA policy for the VMA */
#endif
struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
} __randomize_layout;
이 구조체들이 어떻게 쓰이냐 하면, 맨처음에 프로그램을 실행하게 되면 execve를 통해 vm_area_struct를 새롭게 만들고,
Create할때도 똑같이 vm_area_struct를 새로운지역에다 생성을 합니다. Free로 메모리 해제시 vm_area_struct가 삭제된다.
그림을 보시면 프로세스는 mm_struct를 한개씩만 가질 수 있습니다. 이 구조체에 vm_area_Struct 여러개가 저장이되어 프로세스에서 가지고 있는 가상메모리를 가지고 있으며, 이제 프로세스가 실행되면서 실제메모리로 올려야할때, vm_area_struct를 참고하여 가상메모리를 실제 메모리로 올리게 됩니다.
mmap()
-리눅스에서 프로세스가 가상 주소 공간에 대해 메모리 매핑을 수행할 때 사용되는 시스템 호출 함수입니다. mmap 함수는 파일, 디바이스, 익명 메모리 등 다양한 소스에서 메모리 매핑을 지원합니다.
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- addr - 매핑될 가상 주소를 지정합니다.(NULL을 입력시 시스템이 자동으로 매핑함)
- length - 매핑될 메모리 영역의 크기를 지정합니다.
- prot - 메모리 영역에 적용할 보호모드(읽기,쓰기,실행 등)을 지정합니다.
- flags - 메모리 매핑에 대한 옵션을 지정합니다. (MAP_PRIVATE, MAP_SHARED등이 있습니다.)
- fd - 매핑될 파일의 파일 디스크립터를 지정합니다.
- offset - 매핑될 파일의 오프셋을 지정합니다.
mmap vs malloc
mmap | malloc | |
종류 | 시스템 콜 | 인터페이스 |
할당크기 | large memory 할당 | small memory 할당 |
생성위치 | stack과 heap 사이 | heap |
mmap의 장점
- Lazy loading(지연로딩)
-데이터나 자원을 필요할때만 그 부분만 로딩하는 방식입니다. 사용을하지않을땐 메모리에 매핑을하지않습니다. 이로 인해 메모리 사용량을 최소화 할 수 있습니다. - Memory management
-munmap()이라는 함수로 해제를하게 될시 os로 빠르게 리턴해서 메모리 관리속도가 빨라진다.
[참고]
'OS' 카테고리의 다른 글
메모리 Stack변화 (0) | 2023.05.15 |
---|---|
Address Translation 변환 과정 (VA -> PA) (0) | 2023.05.15 |
가상 메모리(Virtual Memory) (0) | 2023.05.05 |
프로그램 -> 프로세스 변환과정 (컴파일) (0) | 2023.04.06 |
파일모드란? (0) | 2023.04.06 |