페이지는 초기화된 후에 <- 지금 해야되는 거
필요할 때 물리 주소로 변환하려고 하는데
frame에 이미 있었으면 그대로 줌
근데 disk나 swap 공간에 있었으면 스왑 인 해야됨
스왑 인 할 때 frame이 꽉 찼으면 페이지 추방 알고리즘에 따라 스왑 아웃
이 페이지 폴트가 유효하지 않은 페이지에 접근한 폴트라면 찐 페이지 폴트일 것입니다. 그렇지 않고 bogus 폴트라면 당신은 페이지에서 콘텐츠를 로드하고 유저 프로그램에게 제어권을 반환해야 합니다.
bogus 페이지 폴트가 일어나는 3가지 케이스가 있습니다. 지연 로딩 페이지, 스왑 아웃 페이지, 쓰기 보호 페이지. (Copy-on-Write (Extra)를 참고하세요.)
지금은 첫 번째 케이스인 지연 로드 페이지에 대해서만 생각해봅시다.
디버깅 잘 보이게 하려고 process.c에 있는 ifdef 2곳 (include와 맨 아래 함수) 주석처리 및 해당 처리 메모
지금은 첫 번째 케이스인 지연 로드 페이지에 대해서만 생각해봅시다. 만일 지연 로딩때문에 페이지 폴트가 일어나면, 커널은 이미 당신이 세그먼트를 지연 로딩하기 위해 vm_alloc_page_with_initializer 함수에서 세팅해 놓은 초기화 함수를 호출합니다. 당신은 userprog/process.c 에 있는 lazy_load_segment 함수를 구현해야 합니다.
lazy_load_segment는 'from the file'이라고 돼있는데 파일에서만?
load_segment는 세그멘테이션이라고는 돼있는데 페이지 얘기가 있는 걸로 보아 세그멘트로 나누고 페이징 기법?
일단 나중에 천천히 필요하면 구현
struct page *page = (struct page *)malloc(sizeof(struct page));
uninit_new();
page를 해야된다, uninit_new를 해야된다 까지는 답지를 보거나 물어봐서 알아냄.
저번에도 이렇게 답지 보다가 아무것도 배운게 없는 느낌이 들어서 일단 답지 다 닫고 다시 시작.
void uninit_new(struct page *page, void *va, vm_initializer *init,
enum vm_type type, void *aux,
bool (*initializer)(struct page *, enum vm_type, void *))
uninit_new에 무슨 인자를 넣어야 하는건지 알아내려면
해당 인자에 뭐가 들어가는 건지 알아야 할듯
page
무슨 페이지를 넣어야 됨?
1) vm_alloc_page_with_initializer 인자로 받았던 upage?
2) 페이지 만들라고 해서 malloc으로 만든 page?
1)은 애초에 뭐임?
load에서부터 시작해서 온, 가상 메모리의 주소
그니까 upage로 uninit해야됨
*page = (struct page){
.operations = &uninit_ops,
.va = va,
.frame = NULL, /* no frame for now */
.uninit = (struct uninit_page){
.init = init,
.type = type,
.aux = aux,
.page_initializer = initializer,
}};
uninit_new는 페이지를 초기화시켜주기만 할 뿐.
2) 페이지는 페이지에 대한 정보를 담고 있는 친구.
uninit_new(page,upage,);
page에는 새로 만든 1), va에는 upage 2)
vm_initializer *init
랑
bool (*initializer)(struct page *, enum vm_type, void *)
는
함수 포인터라는 거 알고 있음
근데 각각이 무엇이냐?
vscode 검색해도 안 나오니 깃북 보기
근데 깃북에도 vm_initializer에 대한 언급이 없음
struct uninit_page {
/* Initiate the contets of the page */
vm_initializer *init;
enum vm_type type;
void *aux;
/* Initiate the struct page and maps the pa to the va */
bool (*page_initializer) (struct page *, enum vm_type, void *kva);
};
init : 페이지의 내용물을 초기화
page_initializer : 페이지 구조체를 초기화하고 물리 주소를 가상 주소와 매핑
아 page_initializer가 file-backed냐 anonymous냐에 따라 달라지는듯?
ㅇㅋ 깃북에 나와있고
typedef bool vm_initializer(struct page *, void *aux);
도 함수 포인터라고 아까 했었고? 이제야 기억났고? uninit.h에 있었고?
아마 page_initializer들과 쌍으로 존재할거고? type따라 나뉠거고? 확인 해봐야 하고?
파일 확인해봤더니 그런거 없다. 다시 깃북 확인.
bool vm_alloc_page_with_initializer(enum vm_type type, void *upage, bool writable,
vm_initializer *init, void *aux)
아 ㅇㅋ 그건 내가 생각할 필요 없었다. init은 주네.
그리고 그것의 정체는 바로 lazy_load_segment
bool vm_alloc_page_with_initializer(enum vm_type type, void *upage, bool writable,
vm_initializer *init, void *aux)
{
ASSERT(VM_TYPE(type) != VM_UNINIT)
struct supplemental_page_table *spt = &thread_current()->spt;
/* Check wheter the upage is already occupied or not. */
if (spt_find_page(spt, upage) == NULL)
{
/* TODO: Create the page, fetch the initialier according to the VM type,
* TODO: and then create "uninit" page struct by calling uninit_new. You
* TODO: should modify the field after calling the uninit_new. */
/* 페이지를 만들고, 가상 메모리 타입에 따라 initialier를 가져오고,
* uninit_new를 호출해서 "초기화 안된" 페이지를 생성한다.
* uninit_new를 호출한 후에 field를 수정해야 한다. */
struct page *page = (struct page *)malloc(sizeof(struct page));
bool (*initializer)(struct page *, enum vm_type, void *kva);
if (type == VM_ANON)
initializer = anon_initializer;
if (type == VM_FILE)
initializer = file_backed_initializer;
uninit_new(page, upage, init, type, NULL, initializer);
/* TODO: Insert the page into the spt. */
hash_insert(&spt->pages, &page->hash_elem);
}
err:
return false;
}
해치웠나?
/* TODO: Set up aux to pass information to the lazy_load_segment. */
/* 할 것: lazy_load_segment에 정보를 넘기기 위해 aux를 설정하라 */
void *aux = NULL;
if (!vm_alloc_page_with_initializer(VM_ANON, upage,
writable, lazy_load_segment, aux))
aux에 뭘 넣으라는거지
aux는 load_segment에서 당신이 설정하는 정보입니다. 이 정보를 사용하여 당신은 세그먼트를 읽을 파일을 찾고 최종적으로는 세그먼트를 메모리에서 읽어야 합니다.
어디에서 lazy_load_segment가 실행되는 거지
이 함수는 실행 가능한 파일의 페이지들을 초기화하는 함수이고 page fault가 발생할 때 호출됩니다.
static bool
lazy_load_segment(struct page *page, void *aux)
{
/* TODO: Load the segment from the file */
/* TODO: This called when the first page fault occurs on address VA. */
/* TODO: VA is available when calling this function. */
/* 할것: 파일에서 세그먼트를 load한다 */
/* 할것: 이 함수는 주소 VA에서 첫번째 페이지 폴트가 일어날 때 호출된다. */
/* 할것: VA는 이 함수가 호출될 때 사용 가능하다 */
}
아까 물어볼 때 곁들여 들었던 거: #ifndef VM 안에 있던
Project 3 전의 load_segment를 참고하여 구현해보면 될 것
static bool
load_segment (struct file *file, off_t ofs, uint8_t *upage,
uint32_t read_bytes, uint32_t zero_bytes, bool writable)
이전 load_segment에 넣어지는 인자들은 이러하다.
무지성 복붙했을 때 빨간 줄 뜨는 변수들
/* **파일(FILE)**에서 **오프셋(Offset, OFS)**을 시작으로 UPAGE 주소에 세그먼트를 로드합니다.
총 READ_BYTES + ZERO_BYTES 바이트의 가상 메모리가 다음과 같이 초기화됩니다:
READ_BYTES 바이트는 UPAGE에서 **파일(FILE)**의 오프셋 OFS에서 읽어옵니다.
UPAGE + READ_BYTES 위치부터 ZERO_BYTES 바이트는 0으로 초기화됩니다.
이 함수에 의해 초기화된 페이지는 WRITABLE이 true인 경우, 사용자 프로세스가 쓰기 가능해야 하며, 그렇지 않으면 읽기 전용이어야 합니다.
성공하면 true를 반환하고, 메모리 할당 오류 또는 디스크 읽기 오류가 발생하면 false를 반환합니다. */
load_segment의 주석.
그니까 대충 이번 vm은 lazy loading을 해야 하니까
페이지에 lazy_load_segment만 담아두고
거기엔 인자로 page랑 aux만 주는데
load_segment에 전달됐던 인자들 중에 필요한 걸 aux를 통해 넘겨주면 된다는 것.
lazy_load_segement에선 페이지를 spt에도 저장하는 절차가 필요하다고 들음.
anonymous page는? : load_segment와 lazy_load_segment를 호출하는 함수는 load 뿐이고, load는 실행 파일을 불러오는 함수이므로 일단 왜 그런진 모르겠지만 anonymous page에 대해선 생각하지 않아도 될듯.
내일 해야될 것 : project 2까지에서 쓰였던 load_segment가 정확히 무슨 일을 어떻게 하는 건지 알아보기
오늘까지 정리한 핀토스 실행 흐름 도식
어제 생각했던 대로 구현하니까
50퍼에서 틀렸습니다 뜸.
생각해놨던 예외 케이스 돌려보니까 답과 다름.
n=int(input())
seq=list(map(int,input().split()))
Min = 0
temp = 0
Sum = 0
res = -float('inf')
for num in seq:
Sum+=num # 그래프 경로
temp+=num # 부분합
res = max(res, temp)
if Min > Sum: # 최소가 갱신되면 부분합 초기화
Min = Sum
temp = 0
print(res)
최소값을 0으로 초기화했어야 됐음.
그거 고치니까 일단 풀리긴 했는데
N=int(input())
arr=list(map(int,input().split()))
for i in range(1,N):
arr[i]=max(arr[i],arr[i]+arr[i-1])
print(max(arr))
다른 답 보니까 어처구니 없을 정도로 간단.
dp에 아직 안 익숙하니까 dp식 풀이가 머리에서 안 나오고
답을 봐도 바로 이해가 안 간다.
# dp[x]: x를 포함하는, x까지의 최대 연속 합
# x번째 정수까지의 최대 연속 합은 x-1번째 정수까지의 최대 연속합에 x 자신까지 더한 값과, x 자신 중 최댓값이다
# dp[x-1]+x 가 더 크면 x-1번째 정수까지 고르고 x도 고르면 되고, 그냥 x가 더 크면 x-1번째까지의 연속 합을 포기하고 x 자신만 선택하면 된다
또다른 풀이의 주석.
해당 풀이가 맞다는 거야 알겠지만
실전에서 이런 생각을 할 수 있겠느냐고 하면 절대 못할 것 같다.
여기까지 오는 사고 과정이 어떻게 되는거지?
오른쪽 결과는 나중에 구할거니까 왼쪽 결과까지와의 비교만 하면 된다는 게 살짝 어색.
내 풀이를 dp로 치환시켜서 생각해보기?
애초에 접근 방식 자체가 달라버려서 치환이 안될듯.
나는 메모이제이션을 안 했다.
각 숫자에게 '이전 숫자까지의 최대 연속 합'에 대한 정보를 주고,
더 합쳐지고 싶냐고 물어보는...?
n = int(input())
a = list(map(int,input().split()))
d = [0]
for i in a:
if d[-1] > 0:d.append(i + d[-1])
else: d.append(i)
print(max(d[1:]))
이건 다이아 풀이인데 확실히 뭔가 다르다.
시간도 더 빠름.
아 뭐 어떻게 한 건지 모르겠다
내일 봐야할듯. 핀토스 해야됨.