Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
O
os-repo3
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
kim hakjun
os-repo3
Commits
5b447a23
Commit
5b447a23
authored
1 year ago
by
kim hakjun
Browse files
Options
Downloads
Patches
Plain Diff
핸들링 수정
parent
e940c2c7
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
pa3.c
+68
-62
68 additions, 62 deletions
pa3.c
with
68 additions
and
62 deletions
pa3.c
+
68
−
62
View file @
5b447a23
...
@@ -16,7 +16,7 @@
...
@@ -16,7 +16,7 @@
#include
<stdio.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<stdlib.h>
#include
<string.h>
#include
<string.h>
#include
<assert.h>
#include
"list_head.h"
#include
"list_head.h"
#include
"vm.h"
#include
"vm.h"
...
@@ -63,26 +63,24 @@ extern unsigned int mapcounts[];
...
@@ -63,26 +63,24 @@ extern unsigned int mapcounts[];
* Return true if the translation is cached in the TLB.
* Return true if the translation is cached in the TLB.
* Return false otherwise
* Return false otherwise
*/
*/
bool
lookup_tlb
(
unsigned
int
vpn
,
unsigned
int
rw
,
unsigned
int
*
pfn
)
{
int
lookup_tlb
(
unsigned
int
vpn
,
char
access_type
)
{
// TLB 항목을 순회
// TLB 항목을 순회
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
// 항목이 유효하고 VPN이 일치하는지 확인
// 항목이 유효하고 VPN이 일치하는지 확인
if
(
tlb
[
i
].
valid
&&
tlb
[
i
].
vpn
==
vpn
)
{
if
(
tlb
[
i
].
valid
&&
tlb
[
i
].
vpn
==
vpn
)
{
// 요청된 접근 유형에 대한 권한 확인
// 요청된 접근 유형에 대한 권한 확인
if
((
rw
&
ACCESS_READ
&&
tlb
[
i
].
rw
&
ACCESS_READ
)
||
if
((
access_type
==
'r'
&&
(
tlb
[
i
].
rw
&
ACCESS_READ
)
)
||
(
rw
&
ACCESS_WRITE
&&
tlb
[
i
].
rw
&
ACCESS_WRITE
))
{
(
access_type
==
'w'
&&
(
tlb
[
i
].
rw
&
ACCESS_WRITE
))
)
{
// TLB 히트
// TLB 히트
*
pfn
=
tlb
[
i
].
pfn
;
return
tlb
[
i
].
pfn
;
return
true
;
}
else
{
}
else
{
// 권한 불일치, TLB 미스
// 권한 불일치, TLB 미스
return
false
;
return
-
1
;
}
}
}
}
}
}
// TLB 미스
// TLB 미스
return
false
;
return
-
1
;
}
}
/**
/**
...
@@ -98,6 +96,7 @@ bool lookup_tlb(unsigned int vpn, unsigned int rw, unsigned int *pfn) {
...
@@ -98,6 +96,7 @@ bool lookup_tlb(unsigned int vpn, unsigned int rw, unsigned int *pfn) {
*/
*/
void
insert_tlb
(
unsigned
int
vpn
,
unsigned
int
rw
,
unsigned
int
pfn
)
{
void
insert_tlb
(
unsigned
int
vpn
,
unsigned
int
rw
,
unsigned
int
pfn
)
{
int
index
=
-
1
;
int
index
=
-
1
;
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
// 기존 엔트리 업데이트
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
// 기존 엔트리 업데이트
if
(
tlb
[
i
].
valid
){
if
(
tlb
[
i
].
valid
){
if
(
tlb
[
i
].
vpn
==
vpn
)
{
if
(
tlb
[
i
].
vpn
==
vpn
)
{
...
@@ -144,17 +143,17 @@ unsigned int alloc_page(unsigned int vpn, unsigned int rw) {
...
@@ -144,17 +143,17 @@ unsigned int alloc_page(unsigned int vpn, unsigned int rw) {
if
(
mapcounts
[
i
]
==
0
)
{
if
(
mapcounts
[
i
]
==
0
)
{
mapcounts
[
i
]
=
1
;
mapcounts
[
i
]
=
1
;
if
(
ptbr
->
pdes
[
first_pte_index
]
==
NULL
)
{
// 빈 페이지 테이블의 경우
if
(
current
->
pagetable
.
pdes
[
first_pte_index
]
==
NULL
)
{
// 빈 페이지 테이블의 경우
ptbr
->
pdes
[
first_pte_index
]
=
malloc
(
sizeof
(
struct
pte_directory
));
current
->
pagetable
.
pdes
[
first_pte_index
]
=
malloc
(
sizeof
(
struct
pte_directory
));
memset
(
ptbr
->
pdes
[
first_pte_index
],
0
,
sizeof
(
struct
pte_directory
));
memset
(
current
->
pagetable
.
pdes
[
first_pte_index
],
0
,
sizeof
(
struct
pte_directory
));
}
}
struct
pte
*
pte
=
&
ptbr
->
pdes
[
first_pte_index
]
->
ptes
[
second_pte_index
];
struct
pte
*
pte
=
&
current
->
pagetable
.
pdes
[
first_pte_index
]
->
ptes
[
second_pte_index
];
pte
->
valid
=
true
;
pte
->
valid
=
true
;
pte
->
rw
=
rw
;
pte
->
rw
=
rw
;
pte
->
pfn
=
i
;
pte
->
pfn
=
i
;
pte
->
private
=
(
rw
==
ACCESS_READ
)
?
0
:
1
;
pte
->
private
=
(
rw
==
ACCESS_READ
)
?
0
:
1
;
current
->
pagetable
=
*
ptbr
;
insert_tlb
(
vpn
,
rw
,
i
);
insert_tlb
(
vpn
,
rw
,
i
);
return
i
;
return
i
;
...
@@ -185,6 +184,8 @@ void free_page(unsigned int vpn)
...
@@ -185,6 +184,8 @@ void free_page(unsigned int vpn)
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
pfn
=
0
;
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
pfn
=
0
;
}
}
/**
/**
* handle_page_fault()
* handle_page_fault()
*
*
...
@@ -203,37 +204,37 @@ void free_page(unsigned int vpn)
...
@@ -203,37 +204,37 @@ void free_page(unsigned int vpn)
*/
*/
bool
handle_page_fault
(
unsigned
int
vpn
,
unsigned
int
rw
)
bool
handle_page_fault
(
unsigned
int
vpn
,
unsigned
int
rw
)
{
{
int
out_idx
=
0
;
unsigned
int
first_vpn
=
vpn
!=
0
?
vpn
/
NR_PTES_PER_PAGE
:
0
;
int
vpn_idx
=
vpn
%
NR_PTES_PER_PAGE
;
unsigned
int
second_vpn
=
vpn
%
NR_PTES_PER_PAGE
;
if
(
vpn
!=
0
)
out_idx
=
vpn
/
NR_PTES_PER_PAGE
;
if
(
!
ptbr
->
pdes
[
out_idx
])
//case 0
if
(
!
ptbr
->
pdes
[
first_vpn
]
||
!
ptbr
->
pdes
[
first_vpn
]
->
ptes
[
second_vpn
].
valid
)
{
return
false
;
return
false
;
if
(
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
valid
==
false
)
//case 1
}
return
false
;
if
(
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
private
==
1
)
//case 2, writable
{
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
rw
=
ACCESS_WRITE
;
if
(
mapcounts
[
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
pfn
]
!=
1
)
//more then 2 process
if
(
ptbr
->
pdes
[
first_vpn
]
->
ptes
[
second_vpn
].
private
==
1
)
{
{
ptbr
->
pdes
[
first_vpn
]
->
ptes
[
second_vpn
].
rw
=
ACCESS_WRITE
+
ACCESS_READ
;
for
(
unsigned
int
i
=
0
;
i
<
NR_PAGEFRAMES
;
i
++
)
{
if
(
rw
==
ACCESS_WRITE
&&
mapcounts
[
ptbr
->
pdes
[
first_vpn
]
->
ptes
[
second_vpn
].
pfn
]
!=
1
)
{
if
(
mapcounts
[
i
])
continue
;
int
original_pfn
=
ptbr
->
pdes
[
first_vpn
]
->
ptes
[
second_vpn
].
pfn
;
mapcounts
[
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
pfn
]
--
;
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
pfn
=
i
;
//use other pfn
mapcounts
[
i
]
++
;
for
(
unsigned
int
i
=
0
;
i
<
NR_PAGEFRAMES
;
i
++
)
{
if
(
mapcounts
[
i
]
==
0
)
{
// 빈 프레임을 찾아서 매핑
mapcounts
[
original_pfn
]
--
;
ptbr
->
pdes
[
first_vpn
]
->
ptes
[
second_vpn
].
pfn
=
i
;
mapcounts
[
i
]
++
;
break
;
break
;
}
}
}
}
}
else
if
(
rw
==
ACCESS_READ
||
rw
==
2
){
//cannot write wanna write
insert_tlb
(
vpn
,
rw
,
ptbr
->
pdes
[
out_idx
]
->
ptes
[
vpn_idx
].
pfn
);
return
false
;
}
}
return
true
;
//wanna read, write on 1
}
else
if
(
rw
==
ACCESS_WRITE
)
{
return
false
;
}
}
return
true
;
}
/**
/**
* switch_process()
* switch_process()
...
@@ -259,7 +260,7 @@ void switch_process(unsigned int pid)
...
@@ -259,7 +260,7 @@ void switch_process(unsigned int pid)
struct
process
*
new_process
;
struct
process
*
new_process
;
struct
list_head
*
pos
,
*
n
;
struct
list_head
*
pos
,
*
n
;
//
processes 리스트에서
주어진
pid
를 가진 프로세스를 찾습니다
// 주어진
PID
를 가진 프로세스를 찾습니다
.
list_for_each_safe
(
pos
,
n
,
&
processes
)
{
list_for_each_safe
(
pos
,
n
,
&
processes
)
{
struct
process
*
p
=
list_entry
(
pos
,
struct
process
,
list
);
struct
process
*
p
=
list_entry
(
pos
,
struct
process
,
list
);
if
(
p
->
pid
==
pid
)
{
if
(
p
->
pid
==
pid
)
{
...
@@ -268,37 +269,39 @@ void switch_process(unsigned int pid)
...
@@ -268,37 +269,39 @@ void switch_process(unsigned int pid)
}
}
}
}
// 프로세스를 찾은 경우
if
(
target
)
{
if
(
target
)
{
// 현재 프로세스를 processes 리스트의 끝으로 이동합니다
// PID를 가진 프로세스가 존재하는 경우
// 현재 프로세스를 processes 리스트에 추가합니다.
list_add_tail
(
&
current
->
list
,
&
processes
);
list_add_tail
(
&
current
->
list
,
&
processes
);
// target 프로세스를 processes 리스트에서 제거합니다
// target 프로세스를 processes 리스트에서 제거합니다
.
list_del
(
&
target
->
list
);
list_del
(
&
target
->
list
);
// 현재 프로세스를 target 프로세스로 설정합니다
// 현재 프로세스를 target 프로세스로 설정합니다
.
current
=
target
;
current
=
target
;
// 페이지 테이블 베이스 레지스터를
새 프로세스의 페이지 테이블로
설정합니다
// 페이지 테이블 베이스 레지스터를 설정합니다
.
ptbr
=
&
current
->
pagetable
;
ptbr
=
&
current
->
pagetable
;
// TLB
의 모든 엔트리를 무효화
합니다
// TLB
를 플러시
합니다
.
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
tlb
[
i
].
valid
=
false
;
tlb
[
i
].
valid
=
false
;
}
}
// 프로세스를 찾지 못한 경우
}
else
{
}
else
{
// 새 프로세스를 현재 프로세스로부터 포크합니다
// PID를 가진 프로세스가 존재하지 않는 경우
// 현재 프로세스를 복제하여 새로운 프로세스를 생성합니다.
new_process
=
(
struct
process
*
)
malloc
(
sizeof
(
struct
process
));
new_process
=
(
struct
process
*
)
malloc
(
sizeof
(
struct
process
));
assert
(
new_process
!=
NULL
);
new_process
->
pid
=
pid
;
new_process
->
pid
=
pid
;
INIT_LIST_HEAD
(
&
new_process
->
list
);
INIT_LIST_HEAD
(
&
new_process
->
list
);
// 현재 프로세스의 페이지 테이블을 복사합니다
// 현재 프로세스의 페이지 테이블을
새로운 프로세스로
복사합니다
.
for
(
int
i
=
0
;
i
<
NR_PDES_PER_PAGE
;
i
++
)
{
for
(
int
i
=
0
;
i
<
NR_PDES_PER_PAGE
;
i
++
)
{
if
(
current
->
pagetable
.
pdes
[
i
]
!=
NULL
)
{
if
(
current
->
pagetable
.
pdes
[
i
]
!=
NULL
)
{
new_process
->
pagetable
.
pdes
[
i
]
=
(
struct
pte_directory
*
)
malloc
(
sizeof
(
struct
pte_directory
));
new_process
->
pagetable
.
pdes
[
i
]
=
(
struct
pte_directory
*
)
malloc
(
sizeof
(
struct
pte_directory
));
assert
(
new_process
->
pagetable
.
pdes
[
i
]
!=
NULL
);
for
(
int
j
=
0
;
j
<
NR_PTES_PER_PAGE
;
j
++
)
{
for
(
int
j
=
0
;
j
<
NR_PTES_PER_PAGE
;
j
++
)
{
struct
pte
*
src_pte
=
&
current
->
pagetable
.
pdes
[
i
]
->
ptes
[
j
];
struct
pte
*
src_pte
=
&
current
->
pagetable
.
pdes
[
i
]
->
ptes
[
j
];
struct
pte
*
dest_pte
=
&
new_process
->
pagetable
.
pdes
[
i
]
->
ptes
[
j
];
struct
pte
*
dest_pte
=
&
new_process
->
pagetable
.
pdes
[
i
]
->
ptes
[
j
];
...
@@ -306,15 +309,15 @@ void switch_process(unsigned int pid)
...
@@ -306,15 +309,15 @@ void switch_process(unsigned int pid)
if
(
src_pte
->
valid
)
{
if
(
src_pte
->
valid
)
{
*
dest_pte
=
*
src_pte
;
*
dest_pte
=
*
src_pte
;
//
쓰기 가능 페이지는 읽기 전용으로 변경하고, private 비트를 설정합니다
//
Copy-on-Write 처리
if
(
src_pte
->
rw
&
ACCESS_WRITE
)
{
if
(
src_pte
->
rw
&
ACCESS_WRITE
)
{
src_pte
->
rw
&=
~
ACCESS_WRITE
;
src_pte
->
rw
&=
~
ACCESS_WRITE
;
// 원본을 읽기 전용으로 만듭니다.
dest_pte
->
rw
&=
~
ACCESS_WRITE
;
dest_pte
->
rw
&=
~
ACCESS_WRITE
;
// 복사본을 읽기 전용으로 만듭니다.
src_pte
->
private
=
1
;
src_pte
->
private
=
1
;
// COW로 표시
dest_pte
->
private
=
1
;
dest_pte
->
private
=
1
;
// COW로 표시
}
}
//
공유 페이지에 대한
map
count
를
증가
시킵니다
// mapcount
s
증가
mapcounts
[
src_pte
->
pfn
]
++
;
mapcounts
[
src_pte
->
pfn
]
++
;
}
}
}
}
...
@@ -323,13 +326,16 @@ void switch_process(unsigned int pid)
...
@@ -323,13 +326,16 @@ void switch_process(unsigned int pid)
}
}
}
}
// 현재 프로세스를 processes 리스트
의 끝으로 이동
합니다
// 현재 프로세스를 processes 리스트
에 추가
합니다
.
list_add_tail
(
&
current
->
list
,
&
processes
);
list_add_tail
(
&
current
->
list
,
&
processes
);
// 현재 프로세스를 새 프로세스로 설정합니다
// 현재 프로세스를 새로운 프로세스로 설정합니다.
current
=
new_process
;
current
=
new_process
;
// 페이지 테이블 베이스 레지스터를 새 프로세스의 페이지 테이블로 설정합니다
// 페이지 테이블 베이스 레지스터를 설정합니다.
ptbr
=
&
current
->
pagetable
;
ptbr
=
&
current
->
pagetable
;
// TLB의 모든 엔트리를 무효화합니다
// TLB를 플러시합니다.
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
for
(
int
i
=
0
;
i
<
NR_TLB_ENTRIES
;
i
++
)
{
tlb
[
i
].
valid
=
false
;
tlb
[
i
].
valid
=
false
;
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment