페이징기법은 메모리 공간을 일정한 크기의 페이지로 나누어 다룬다. => 불연속적 할당

페이징은 CPU가 논리주소를 통해 메모리에 접근하고 운영체제가 이를 물리주소로 변환하여 실제 메모리에 올리는 방식임. 논리주소공간이 물리주소공간보다 크기때문에 부족한 공간은 스와핑 방법 으로 이뤄지는데, 페이징에서는 이 용어를 '페이지 인' 과 '페이지 아웃'으로 바꾸어 부름.
특징
페이징 기법은 프로세스에게 불연속적으로 주소를 할당함. 연속적으로 주소를 할당시 외부 단편화가 발생할 수 있지만 불연속적인 방법은 내부 단편화가 발생 할 수도 있음.
페이지 테이블은 페이지 번호와 프레임 번호를 짝지어 주는것이고 프로세스마다 각자의 페이지 테 이블을 가지고 있어 각 프로세스의 테이블은 메모리에 적제되어 있다.
따라서 물리공간에 불연속적으로 할당되어 있다고 해도 다음에 실행해야할 프로세스를 적절하게 찾 아갈 수 있다.
접근비트: 페이지가 메모리로 올라온 후 데이터에 접근성이 있었는지 알려주는 비트
메모리에 읽기나 실행작업을 했다면 1로 바뀌게 됨.
변경비트: 페이지에 메모리가 올라온 후 데이터의 변경이 있었는지 알려주는 비트
메모리에 쓰기작업이 있었다면 1로 바뀌게 됨.
유효비트: 페이지가 어디에 있는지 알려주는 비트. 0이라면 페이가 스왑영역, 1이라면 물리메모 리에 있다는 뜻. CPU가 유효비트가 0인 스왑영역에 접근하려 하면 페이지폴트라는
예외가 발생. 이가 발생하면 프로세스를 바로 실행할 수 없다는 의미.
보호비트: 페이지에 대한 읽기, 쓰기, 실행권한이 어떻게 되는지 나타내는 비트
100 은 읽기 권한만 있고, 111은 모든 권한이 다 있다는 뜻.
세그멘테이션과 페이징을 혼합한 방식
세그멘테이션은 가변분할방식이여서 데이터,스텍,코드 영역등 논리적으로 나눠져 있는 영역을 나눠 서 관리 가능, 벗 외부단편화 문제 발생가능
페이징은 논리적인 영역들을 나눠서 관리는 못함. 벗 메모리 효율이 좋음
페이지드 세그멘테이션에서는 세그멘테이션 테이블이라는 것을 관리.
세그먼트 번호, 권한비트, 페이지번호, 크기 등으로 구성되어 있음. 권한비트로 코드영역,스택영역등에 대한 권한에 차이를 부여할 수 있음.
foods = ["햄버거", "샐러드", "비스킷"]
print(id(foods))
# id: 참조자(변수)가 어떤 논리 메모리 주소(논리주소공간)를 참조하고 있는지 반환해주는 함수
print(hex(id(foods))) #16진수 값
mv = memoryview(b"happy day")
print(mv)
print(mv[0]) #h에 관한 주소
print(mv[1]) # a
print(mv[2]) # p
print(mv[3]) # p
import psutil
import os
print("메모리 사용량 조회하기")
memory_dict = dict(psutil.virtual_memory()._asdict()) #시스템메모리 사용량에 대한 통계를 튜플형태로 반환해줌/그것을 딕셔너리로 바꿈
print(memory_dict)
total = memory_dict['total'] #총량
available = memory_dict['available'] # 즉시사용가능한양
percent = memory_dict['percent'] # available제외한 비율(사용중인 비율)
print(f"메모리 총량 : {total}")
print(f"메모리 즉시 제공 가능량 : {available}")
print(f"메모리 사용량 : {percent}")
pid = os.getpid()
current_process = psutil.Process(pid)
kb = current_process.memory_info()[0] / 2 ** 20 # 현재 나의 프로세스가 몇키로바이트 쓰는지 알수 잇음.
print(f"메모리 사용량 : {kb:.2f} KB")
<실행결과>

import tracemalloc # 메모리 추적 파이썬 3.4부터 지원됨
tracemalloc.start()
# 메모리 할당이 진행되는 작업 아무거나 해본 것임!
data = [b'%d' % num for num in range(1,10001)]
joined_data = b' '.join(data)
current, peak = tracemalloc.get_traced_memory()
# 현재사용량, 최대사용량
print(f'현재 메모리 사용량: {current / 10 ** 6}MB')
print(f'최대 메모리 사용량: {peak / 10 ** 6}MB')
tracemalloc.stop()
traced = tracemalloc.get_tracemalloc_memory() #프로세스를 추적(트레이스말록)하느라 쓴 메모리
print(traced / 10 ** 6)
<실행결과>
