개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
경성대학교 양희재 교수님 수업 영상을 듣고 정리하였습니다.
메모리 낭비방지
Dynamic Loading
Dynamic Linking
Swapping
동적적재(Dynamic Loading)
loading: 어플리케이션(만들어진 실행파일)을 메인메모리로 올리는 것(적재하는 것) 프로그램 실행에 반드시 필요한 루틴/데이터만 적재
모든 루틴(routine, 함수, 프로시저)이 다 사용되는 것은 아니다(ex.오류처리)
모든 데이터(data)가 다 사용되는 것은 아니다(ex.배열)
자바: 모든 클래스가 다 사용되는 것은 아니다.
실행 시 필요하면 그때 해당 부분을 메모리에 올린다 cf. <->정적적재(static loading)
동적연결(Dynamic Linking)
여러 프로그램에 공통 사용되는 라이브러리(네트워크 관련된 라이브러리(ftp, 이메일..), printf.o 기계어코드 등..)
공통 라이브러리 루틴(library routine)을 메모리에 중복으로 올리는 것은 낭비
라이브러리 루틴 연결을 실행 시까지 미룬다
오직 하나의 라이브러리 루틴만 메모리에 적재되고 다른 애플리케이션 실행 시 이 루틴과 연결(link)된다. cf. <->정적연결(static linking)
공유 라이브러리(shared library, .so) - linux 또는,
동적 연결 라이브러리(Dynamic Linking Library, dll) - Windows
즉, 원래는 실행파일(exe file)을 만들기 전에 링크가 되는데(=정적연결), 링크를 미룬다. 일단 로드된 다음에(p1, p2가 메모리에 올라온 다음에) 링크를 한다.
p1과 p2 둘다 공통적으로 코드 내에 printf를 가지고 있다고 한다면, p1을 실행하려할 때 하드디스크에서 printf를 메인메모리에 가져온다.
printf가 메모리에 올라오면 p1과 p2가 실행될때 그때그때 메인메모리에 있는 printf를 링크를 하여 사용한다.
Swapping
메모리에 적재되어 있으나 현재 사용되지 않고 있는 프로세스 이미지를 하드디스크의 특정부분으로 몰아냄
(컴퓨터 한참 사용하다가 중단하는 경우, 그때에도 내 프로그램은 여전히 메모리에 남아있는데 이 부분도 낭비이다.)
메모리 활용도를 높이기 위해 Backing store(swap device, 하드디스크의 일부) 로 몰아내기
프로그램 실행: code + data + stack(함수호출해서 돌아오는 주소 저장, 지역변수 저장)
실행파일을 메모리에 올리기
메모리 몇번지에?
다중 프로그래밍 환경에서는?
MMU사용: 재배치 레지스터(Relocation register) > base/limit외에도 Relocation이 있음 os가 Relocation register를 이용해 번지수를 지정(address translation)해줌으로써 실제 메인메모리 어디에 들어가있는지와는 상관없이 프로그램이 실행될 수 있도록 함
그래서 메모리의 몇번지에 올리는지는 중요한 이슈가 아니다.
프로그램 설계자가 처음 hwp를 만들때 번지를 0번지로 설정을 해놓았는데 hwp가 실제 1000번지에 있다면 프로그램이 실행이 안된다.
이를 제대로 실행될 수 있는 방법은 Relocation register가 담당한다
os가 hwp를 실행할 적에는 Relocation register에 1000이라는 값을 넣는다. 그래서 cpu가 hwp를 실행하려면 0번지에 있다고 생각하니
cpu는 0번지를 내어도 limit이 1000이 되어있어 1000번지에 있는 hwp도 실행이 가능하게 된다. (사실은 cpu가 속은것이다.)
cpu는 0에 있는줄 알지만, 실제로는 1000에 있는것이다.
주소구분
논리주소(logical address, cpu가 내는 주소) vs 물리주소(physical address, 실제로 mmu를 통과해서 메인메모리오 오는 주소)
cpu는 항상 모든 주소가 0번지에서 돌고있다고 생각하며 Relocation register를 통해 프로그램들이 메인메모리의 어느 위치든 올리기가 가능해진다.
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
경성대학교 양희재 교수님 수업 영상을 듣고 정리하였습니다.
이전에 동기화도구로 세마포에 대해서 공부를 했는데, 이 세마포는 굉장히 옛날에 사용하던 방식이다. 이제 많이 사용되는 것은 Monitors이고 이는 자바에서 사용된다.
모니터 (Monitors)
세마포 이후 프로세스 동기화 도구
세마포보다 고수준 개념
개념
공유자원 + 공유자원 접근함수로 구성됨
2개의 queues: 배타동기(Mutual exclusion queue) + 조건동기(Conditional synchronization)
공유자원 접근함수에는 최대 1개의 쓰레드만 집입가능: 나머지는 큐에서 진입못하고 기다리고 있어야한다.(Mutual exclusion queue에서 대기)
진입 쓰레드가 조건 동기로 블록되면 새 쓰데르 진입가능: wait call> 들어왔던 쓰레드는 Conditions synchronization에 갇히게 된다. 그러면 새 쓰레드가 진입가능하다.
새 쓰레드는 조건동기로 블록된 쓰레드를 깨울 수 있음: notify()> 블록된 쓰레드를 깨워준다.
깨워진 쓰레드는 현재 쓰레드가 나가면 재진입할 수 있음: 하나의 쓰레드만 있을 수 있으니까, 그 비어진 자리에 깨워진 쓰레드가 들어올 수 있게 된다.
자바 모니터
자바에서는 모든 객체가 모니터가 될 수 있다.
배타동기: synchronization 키워드를 사용하여 지정 > 한 쓰레드에만 접근이 가능하다.
조건동기: wait(), notify(), notifyAll() 메소드를 사용
classC{privateintvalue;synchronizationvoidf(){// f를 호출하면 다른 쓰레드는 접근 불가능////////code//////////}synchronizationvoidg(){////////code//////////}voidh(){// 공통변수를 업데이트하는 함수가 아니라는 의미, 이때 이 쓰레드는 동작이 가능////////code//////////}}
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
경성대학교 양희재 교수님 수업 영상을 듣고 정리하였습니다.
교착상태: Deadlocks
간혹 동기화를 하다보면 Deadlock에 빠지는 경우가 있다. (프로세스 관리에서 해결해야하는 문제중 하나!)
프로세스는 실행을 위해 여러 자원을 필요로 한다. (CPU, 메모리, 파일, 프린터 등..) 어떤 자원은 갖고 있으나 다른 자원은 갖지 못할때(다른 프로세스가 이미 사용중일때) 나머지는 대기를 해야한다. 그리고 다른 프로세스 역시 다른 자원을 가지려고 대기할 때 교착상태 가능성 > 이를 os가 잘못 나누어주면 교착상태에 빠진다.
교착상태 필요조건(Necessary Conditions)
Mutual exclusive(상호배타): 하나가 사용하면 나머지는 기다려야한다.
Hold and wait(보유 및 대기): 하나 가지고 있으면서 나머지가꺼도 기다린다.
No Preemption(비선점): 순서를 강제할 수 없고 순서대로 이루어진다.
Circular wait(환형대기): 하나의 원을 만들어놓고 있다.
자원(Resource)
Deadlock이 일어나는 이유는 결국 자원 때문이다. 자원(=하드웨어 자원)
자원을 할당받기 위해서는 os에 요청을 하고 요청이 올바르면 자원을 할당해주는데, 이를 다 사용하면 다시 os에게 반납을 하게 되는데, 이런식으로 자원을 사용하게 된다. 이 똑같은 자원이 여러개 있을 수도 있다.(여러개의 자원 = instance)
동일 자원
동일 형식(type)자원이 여러개 있을 수 있다.
예) 동일 CPU 2개, 동일 프린터 3개 등
자원의 사용
요청(request) -> 사용(use) -> 반납(release)
- 자원 할당도(Resource Allocation Graph)
어떤 자원이 어떤 프로세스에게 할당되었는가?
어떤 프로세스가 어떤 자원을 할당받으려고 기다리고 있었는가?
자원: 사각형, 프로세스: 원, 할당: 화살표
교착상태가 되려면 이 그림이 원을 만들고 있어야 한다.
교착상태의 필요조건
자원 할당도 상에 원이 만들어져야 한다(환형조건): 충분조건은 아님!
피하려면: 짝수(오->왼), 홀수(왼->오)
위 경우에는 교착상태가 아니다
교착상태를 처리하는 방법
교착상태 방지(Deadlock Prevention)
교착상태의 4가지 필요조검 중 한 가지 이상을 불만족시킨다.
상호배타(Mutual exclusive): 자원을 공유 가능하게 -> 원천적으로는 실현이 불가능하다.
보유 및 대기(Hold & Wait): 자원을 가지고 있으면서 다른 자원을 기다리지 않게 -> 일부는 가능하다.
예) 자원이 없는 상태에서 모든 자원 대기, 일부 자원만 가용하면 보유자원을 모두 놓아주기(혹은 가지고 있다면 두개를 동시에 가지도록!)
단점: 자원 활용률 저하, 기아 (starvation)
비선점(NonPreemptive): 자원을 선점가능하게 -> 원천적으로는 실현이 불가능하다. (예; 프린터)
환형대기(Circular wait)
예) 자원에 번호부여하여 번호 오름차순으로 자원 요청
단점: 자원 활용률 저하
교착상태 회피(Deadlock Avoidance)
교착상태 자체를 자원 요청에 대해 os에서의 잘못된 승인이 이루어져 발생한 것으로 생각한다.
첫번째 예제 - 안전한 할당(Safe Allocation)
12개의 magnetic tape 및 3개의 process
Process
Max needs
Current needs
P0
10
5
P1
4
2
P2
9
2
두번째 예제 - 불안전한 할당(Unsafe Allocation)
12개의 magnetic tape 및 3개의 process
Process
Max needs
Current needs
P0
10
5
P1
4
2
P2
9
3
운영체제는 자원을 할당할 때 불안전 할당이 되지 않도록 해야한다. (불안전할당 -> 교착상태, 대출전문 은행과 유사:Banker’s algorithm)
자원을 할당할때 위험한 불안전할당을 하지 않도록 하는 방법
교착상태 검출 및 복수(Deadlock Detection & Recovery)
위의 두가지 방법은 애초에 교착상태가 일어나지 않게 하는 방법이었다면 이는 교착상태는 일어나도록 허용은 하되, 발생하면 복구하도록 하는 방법이다.
교착상태가 일어나는 것을 허용
주기적 검사: 검사에 따른 추가 부담(overhead)
교착상태 발생 시 복수: 프로세스 일부 강제 종료, 자원 선정하여 일부 프로세스에게 할당
이 방법은 os로 하여금 교착상태가 일어나지 않도록 유의하세요. 라고 알려주는게 아니라 프로세스가 필요한대로 자원을 일단 다 나눠주는데, 나눠주다보면 잘 일어나지 않지만 어쩌다가 교착상태가 발생할 수 있다. 이렇게 교착상태가 나타나면 시스템은 동작을 멈추게 되고 이때 이를 해결해줘야 한다.
os의 프로세스 관리부서에서 프로그램이 돌면서 계속적으로 컴퓨터 내부를 교착상태가 일어났는지를 주기적으로 확인한다. 그런데 주기적 검사에서 주기적이라는 단어가 상당히 모호한데, 자주하면 할수록 교착상태를 빨리 알아챌 수 있기 때문에 좋지만 우리가 사용할 수 있는 자원은 한정적이기 때문에 오버헤드의 문제점이 존재한다. 그리고 더 나아가 이렇게 검사를 통해 교착상태를 발견하게 되면 이를 복구해줘야 하는데, 이를 복구해주기 위해서는 주기적으로 현재 상태를 기억을 해야한다. (그러면 또 메모리가 들게 된다) -> 이렇듯 비용이 많이 발생하게 된다.
교착상태가 발생하면 한 프로세스를 강제로 종료를 시키던가, 그게 불가능하다면 자원을 강제로 뺏어서 다른 프로세스에게 할당을 해주면 된다.
이 방법은 말그대로 교착상태 자체가 잘 일어나는 것이 아니기 때문에 자원을 그때그때 그냥 할당을 해주는것을 허용해주는 것인데, 사실 현실적으로 이 방법을 사용하기에는 추가적으로 드는 비용적인 부분들이 많이 들게된다.
교착상태 무시 (Don’t Care)
방법이라고 하기도 그렇지만 이런 교착상태 자체를 무시하는 것이다. 실제로 교착상태가 자주 일어나기도 힘들고(4가지의 필수조건을 충족시키기가 힘들다) pc는 일반적으로 우리가 혼자 쓰고 있기때문에 아예 무시하는 방법을 적용하기도 한다.
파이썬 3.7부터 표준 라이브러리로 등재된 dataclass에 대해 알아봅니다. (파이썬 3.6에서 데이터클래스를 사용하기 위해서는 pip install dataclasses를 해줬어야 했다.) 파이썬 3.7에서는 데이터클래스를 보다 용이하게 선언해주기 위해 데코레이터 @dataclass를 사용하면 되고 이를 사용하면 보다 간편하게 __init__,__repr__ 등의 메소드를 자동으로 정의할 수 있다.(사용자 정의 클래스에 자동으로 추가할 수 있다.)
fromdataclassesimportdataclass@dataclassclassBook:title:str# 필드
price:int=Nonebook=Book('당신은 데이터의 주인이 아니다...')book
이 데이터클래스 데코레이터는 클래스를 검사하여 필드를 찾는다. 필드는 형 어노테이션을 가진 클래스 변수로 정의된다. 필드의 특징은 아래와 같다.
@dataclassclassC:a:int# 'a' has no default value
b:int=0# assign a default value for 'b'
이렇게 기본값이 없는 필드는 항상 기본값이 있는 필드위에 정의되어야 한다. 그렇지 않으면 TypeError가 발생한다.
romdataclassesimportdataclass@dataclassclassWebtoon:# 이 클래스에서 공통적으로 사용할 변수는 클래스변수로 선언
URL_WEBTOON_LIST='https://comic.naver.com/webtoon/weekday.nhn'URL_EPISODE_LIST='https://comic.naver.com/webtoon/list.nhn?titleId={id}'WEBTOON_LIST_HTML=Noneid:strurl_thumbnail:strtitle:strdef__post_init__(self):self.author=Noneself.description=Noneself.genres=Noneself.age=Nonedef__repr__(self):# 객체의 표현값
returnf'Webtoon({self.title}, {self.id})'