1. 메모리

  - 16비트
    1) jmp A : 3 은 결국 3번지로 이동하라는 명령이다. 이는 CS : 3 ( CS레지스터리부터 3번지로 개선됐다. )
    2) 16bit 시절부터 offset을 이용하여 주소를 결정하였다.
code Segment : CS
data  Segment : DS
stack Segment : SS
TEB Segment : FS

mov [10], 100 : DS로부터 10떨어진곳에 100을 넣어라
mov [500], 100 : DS로부터 500떨어진곳에 100을 넣다가 다른 메모리에 접근할 수도 있다. 보안문제 발생

  - 32비트
    1) 재배치를 해준다. GDT( Global Descripter Table ) 을 거쳐야 가상주소가 논리주소,선형주소가 된다.
Index Address Size Access
1 1000 5000 R
2 7000 3000 R/W

    2) mov [100], 100  : DS가 Index 2라면 7000에서 100떨어진곳에 100을 추가한다.
    3) mov[6000], 100 : 하지만 잘못된접근이나 권한밖의 일은 리셋시켜서 보호해준다. Table의 역할!!!
    4) Windows 나 Linux는 GDT 를 쓰지 않고 Intel CPU와의 호환을 위해 그냥 만들어 놓기만 한다.
    5) 그러므로 결국 가상주소가 논리주소,선형주소가 된다.

  - 가상주소 + 세그먼트 => GDT => 선형주소(linear Address ) // Segmentation 이라 한다.

2. 페이징

  - GDT 테이블을 거친 선형주소는 4G가의 메모리를 참조 할 수 있다.(가상주소랑 일치)

  - Page Table
    1) PFN (Page Frame Number) : 메모리 관리를 효율적으로 하기 위하여 물리 메모리를 4k로 잘라서 보관!
    2) 물리메모리가 1MB 라면 이를 잘게 나눠서 0~255 번의  PFN 를 매기는 것이다!!
    3) 하지만 물리메모리가 4G 라면 너무 많은 PFN이 생성되므로 2단 주소로 바꿔서 관리를 해준다.

사용자 삽입 이미지

    4) 선형주소 => PageDirectory => PageTable => PageFrame => Offset  의 순서 물리메모리의 주소를 찾아간다. 이 모든것이 선형주소에 담겨 있는것을 볼 수 있다.
    5) 선형주소는 CR3 레지스터를 참고하여 페이지디렉토리를 찾아간다.

  - 이 모든 작업은 Intel CPU가 알아서 해준다. 그저 테이블과 CR3에 주소만 담아 놓으면 된다.
  - PFN 에는 32bit의 주소만 갖고 있는것이 아니라 48bit로 구성되어 16bit는 HDD에 백업되어 있는 물리메모리 값을 파악해서 다시 물리메모리에 올려 놓는 작업도 하고 있다.

3. 공유 메모리

  - A.exe 에 전역으로 선언된 변수가 있다면 이를 2번 실행시 데이터와 코드를 공유하여 물리메모리에 올린다.
  - 하지만 전역 변수에 데이터를 쓰게 되면 Copy On Write 를 하여 새로운 메모리 공간을 만들어 준다.
  - 즉, 처음에는 메모리 영역을 공유하지만 쓸때에는 복사본을 만들어서 딴 공간을 만들게 된다.

  - Copy On Write 를 하지 않는다면 전역변수를 서로 공유할 수 있게 되는 것이다.
// 일반 전역 변수..  .data section에 놓인다. 기본적으로 COW하는 속성을 가지고 있다.
int x = 0;

// exe에 새로운 data 섹션을 만든다.
#pragma data_seg("AAA")
int y = 0;      // 공유 섹션으로 만드려면 반드시 초기값이 필요하다.
#pragma data_seg()

// 특정 섹션의 속성을 지정한다. - Read, Write, Share( COW 속성이 제거된다. )
#pragma comment( linker, "/section:AAA,RWS")    // Copy On Write
- .exe 에 Share 속성을 가진 AAA 섹션이 생긴것을 알 수 있다.
- 전역변수는 .data 에 있지만 AAA라는 Section을 만들어서 물리메모리 상에서 같이 사용하는 것이다.
- 같은 프로세스 끼리는 공유가 필요 없으므로 DLL에 써서 다른 프로그램에도 읽게 해준다면 더 효율적..
- A.exe => int x;(전역), x.dll에 선언 <= B.exe
// SHARE.dll - COW를 하지않는 DLL상에서의 전역 변수 만들기
// 공유 메모리는 반드시 초기화 해야 한다.,!!!!!!!!!!!!!!

#pragma data_seg("SHARED")
char buf[1024] = { 0 };
#pragma data_seg()
#pragma comment( linker, "/section:SHARED,RWS" )
/////////////////////////////////////////////////////
extern "C" __declspec(dllexport) void SetData(char* s)
{
    strcpy( buf, s );
}
extern "C" __declspec(dllexport) void GetData(char* s)
{
    strcpy( s, buf );
}
/////////////////////////////////////////////////////
// A.cpp - DLL에서 가져와서 사용하기!!!

    HMODULE hDll = LoadLibrary( "SHARED.dll" );
    F SetData = (F)GetProcAddress( hDll, "SetData" );
    F GetData = (F)GetProcAddress( hDll, "GetData" );

Tag | ,

Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다