TIL 2022-08-11 Copy on Write
Copy on Write
동일한 메모리 위치를 참조하다가 수정이 일어나면 값을 복제한 것을 새로운 메모리 주소에 할당하고 그다음 Write를 진행하는 것,
위키위키에 있는 C++98 스탠다드의 예제
std::string x("Hello");
std::string y = x; // x and y use the same buffer.
y += ", World!"; // Now y uses a different buffer; x still uses the same old buffer.
리눅스에선...
보통의 fork라면 메모리 수정이 아니라 아예 exec을 통해 아예 주소 공간을 대체하는 경우가 잦음. 이런 경우 모든 메모리를 복사하는 것은 낭비임... 그래서 COW 씀
Linux에서 parent process가 child process를 fork해서 생성하면, parent process의 이미지를 복사하지 않고 동일한 메모리를 공유함. 그리고 parent page에 수정할일이 있으면 그떄 해당 페이지를 복사하여 이를 할당해줌. 실제 수정(Write)할떄 복사하여 페이지를 새로 만들어주는 형식으로 복사를 최대한 뒤로 미뤄주는 것.
메모리의 특정 페이지를 Read Only로 바꾸고 reference를 체크하므로써 효율적으로 구현가능함.
이 특정 페이지에 write 동작이 오면 커널이 끼어서 새 physical page를 할당해서 copy-on-write data로 초기화함. (reference가 하나라면 스킵함)
그리고 page table를 새로운 쓰기 가능 페이지로 업데이트하고 reference 수를 하나 감소시킴. 그리고 write 진행함.
왜 이렇게 하냐?
말했듯 수정되지 않을 작업들에 대한 불필요한 리소스 소비를 줄일수 있음.
다만 자식 프로세스가 생겨 작업하는 도중에 수정사항이 발생하면 복사하는 오버헤드가 추가로 있어 평소보다 메모리를 많이 쓰게 됨
어따 쓰냐?
btrfs, ZFS 등의 파일 시스템, 혹은 마이크로소프트 SQL 서버 데이터베이스 등에서 제공하는 스냅샷 원리로 사용함.
스냅샷은 해당 시점으로 값을 돌릴수 있는 기능을 의미함.
COW 스냅샷은 어떻게 이루어지는가?
스냅샷 생성시에 바로 값들을 복제하지 않고 값들의 포인터들이 담긴 메타데이터만 저장해놓음.
그리고 여기서 포인터로 가리키고 있는 값들에 대한 변경 요청이 들어오면 변경 요청이 들어온 값에 대해 COPY를 진행하고 스냅샷 메타데이터가 가리키는 포인터를 변경하는 식으로 작동됨.
Incremental backup의 weak form이고 full backup의 대체제가 아니라는데 위의 두 개념을 내일 공부해야징