<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>alwayslee_12.log</title>
        <link>https://velog.io/</link>
        <description>Always's Archives</description>
        <lastBuildDate>Tue, 22 Feb 2022 07:57:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>alwayslee_12.log</title>
            <url>https://images.velog.io/images/alwayslee_12/profile/91b5b701-8fba-4667-bb1b-04061bd7f2db/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. alwayslee_12.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/alwayslee_12" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Virtual Memory]]></title>
            <link>https://velog.io/@alwayslee_12/Virtual-Memory</link>
            <guid>https://velog.io/@alwayslee_12/Virtual-Memory</guid>
            <pubDate>Tue, 22 Feb 2022 07:57:08 GMT</pubDate>
            <description><![CDATA[<p>물리적인 메모리의 주소변환은 운영체제가 관여하지 않지만,
virtual memory 기법은 운영체제가 전적으로 관여함</p>
<h3 id="demand-pagingpaging-기법을-사용하는-것으로-가정">Demand Paging(paging 기법을 사용하는 것으로 가정)</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/abb245b2-024b-4ceb-bae6-f90eb0831021/image.png" alt=""></p>
<ul>
<li><p>실제로 필요할 때 page를 메모리에 올림(요청이 있으면 페이지를 메모리에 올림. 모든 페이지를 메모리에 올리는 것이 아닌) </p>
<ul>
<li>I/O 양 감소</li>
<li>Memory 사용량 감소</li>
<li>빠른 응답 시간</li>
<li>더 많은 사용자 수용</li>
</ul>
</li>
<li><p>Valid/Invalid 비트 사용</p>
<ul>
<li>Invalid의 의미: 사용되지 않는 주소 영역인 경우, 페이지가 물리적 메모리에 없는 경우</li>
<li>처음에는 모든 page entry가 invalid로 초기화(demand paging 기법이기에 처음에는 모든 페이지가 물리적 메모리에 로드되어 있지 않음)</li>
<li>주소 변환을 하려는 페이지가 page table에서 i로 되어있다면 물리적 메모리에 로드되어있지 않다는 뜻(MMU가 trap 발생시킴)
  <img src="https://images.velog.io/images/alwayslee_12/post/be02df64-5fff-4e31-834f-605a918b957d/image.png" alt=""><ul>
<li>page fault(요청한 페이지가 메모리에 없음)</li>
<li>해당 페이지를 디스크에서 메모리로 올려야 함(I/O 작업. CPU 제어권이 OS로 넘어감)</li>
<li>OS에서 잘못된 요청이 아닌지 확인(페이지 번호가 유효하지 않거나 접근 권한 문제)</li>
<li>메모리내에서 빈 페이지 불러옴(없으면 하나 쫓아냄)</li>
<li>해당 페이지를 디스크에서 메모리로 읽어옴<ul>
<li>페이지 주소 변환을 요청한 프로세스를 block시키고, 다른 프로세스에 CPU 제어권 넘김</li>
<li>디스크 I/O가 끝나면, OS가 page table entry에 해당 페이지에 대한 처리 결과 기록(i -&gt; v)</li>
<li>해당 프로세스를 ready queue로 옮김</li>
</ul>
</li>
<li>CPU 제어권을 얻으면 작업 재개</li>
</ul>
</li>
</ul>
</br>

<h3 id="performance-of-demand-paging">Performance of Demand Paging</h3>
<hr>
<ul>
<li>page fault rate(0&lt;=p&lt;=1.0)<ul>
<li>if 0 = no page fault</li>
<li>if 1 = every reference is a fault</li>
</ul>
</li>
<li>메모리 접근 시간 <ul>
<li>(1-p) * memory access (no page fault)</li>
<li>p(OS로 CPU가 넘어가고 HW적으로 page fault 처리 + 메모리에서 page 쫓아냄 + 메모리에 page 로드 + OS 읽어온 page entry 작성, restart) (page fault occur)</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="빈-페이지가-없는-경우메모리에-로드-된-페이지-중-하나-쫓아냄">빈 페이지가 없는 경우(메모리에 로드 된 페이지 중 하나 쫓아냄)</h3>
<hr>
<p>OS가 하는 일
<img src="https://images.velog.io/images/alwayslee_12/post/d1e04752-23c3-4de2-aeb3-3095cec6f3d2/image.png" alt=""></p>
<ul>
<li>Page Replacement<ul>
<li>어떤 frame을 내릴지 결정</li>
<li>곧바로 사용되지 않을 page를 쫓아내는 것이 좋음</li>
<li>동일한 페이지가 여러 번 메모리에서 쫓겨났다가 다시 돌아올 수 있음</li>
</ul>
</li>
<li>Replacement Algorithm<ul>
<li>page-fault rate를 최소화하는 것이 목표</li>
<li>알고리즘 평가<ul>
<li>주어진 page references string에 대해 page fault를 얼마나 내는지 조사</li>
<li>references string? 1,2,3,4,1,2,5,1,2,3,4,5</li>
</ul>
</li>
<li>가장 좋은 알고리즘<ul>
<li>가장 먼 미래에 참조되는 page를 replace
  <img src="https://images.velog.io/images/alwayslee_12/post/b56cc85d-8a97-45e6-b7df-fc8e16baa6c3/image.png" alt=""></li>
<li>Optimal Algorithm(page fault를 가장 적게하는 alg)<ul>
<li>실제 시스템은 미래에 대한 참조를 하기가 어려움</li>
</ul>
</li>
<li>이 알고리즘은 미래에 대한 참조를 할 수 있다 가정</li>
<li>실제 시스템에서 구현하기 어려움(offline optimal algorithm)</li>
<li>다른 알고리즘의 성능에 대한 upper bound 제공(이 alg보다 더 좋을 수는 없음. 다른 alg의 성능을 평가하는 기준이 됨)</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="page-replacement-algorithm">Page Replacement Algorithm</h3>
<hr>
<p>미래에 대한 참조를 할 수 없으니 과거 이력을 이용하자!</p>
<ul>
<li>FIFO: 먼저 들어온 것을 먼저 내쫓음
  <img src="https://images.velog.io/images/alwayslee_12/post/120f8ac7-7d31-4c08-ba53-31755c21dc5a/image.png" alt=""><ul>
<li>메모리 크기를 늘리면 보통 성능이 좋아져야 하는데, 이 알고리즘의 경우에는 성능이 더 안좋아지는 상황(Belady&#39;s Anomaly)</li>
</ul>
</li>
<li>LRU(Least Recently Used): 가장 오래 전에 참조된 것을 내쫓음
  <img src="https://images.velog.io/images/alwayslee_12/post/49063624-a409-49f0-a8b3-aafdb22f862d/image.png" alt=""><ul>
<li>참조 횟수에 대한 고려를 하지 않는 문제</li>
<li>구현
<img src="https://images.velog.io/images/alwayslee_12/post/10b0ba27-aa41-4a70-9424-b7d56792ec47/image.png" alt="">
 가장 최근에 참조된 페이지가 맨 밑(linked list로 구현)
 최근에 참조가 되면 맨 밑으로 내림
 맨 위에 페이지를 쫓아냄
 시간 복잡도 : O(1) 쫓아내기 위한 비교가 필요 없음</li>
</ul>
</li>
<li>LFU(Least Frequently Used): 참조 횟수가 가장 적은 페이지를 지움<ul>
<li>최저 참조 횟수가 여럿 있는 경우<ul>
<li>알고리즘 자체적으로 규정하고 있는 것은 없지만, 성능 향상을 위해 마지막 참조 시점이 더 오래된 page를 내쫓는게 좋다</li>
</ul>
</li>
<li>가장 최근에 참조된 page를 내쫓는 문제</li>
<li>구현
<img src="https://images.velog.io/images/alwayslee_12/post/ca9f9d29-8f8d-430d-b124-565f709622fc/image.png" alt="">
참조 횟수가 가장 적은 페이지는 맨 위
참조 횟수가 가장 많은 페이지는 맨 밑
페이지끼리 참조횟수를 비교해야 함
시간 복잡도 : O(n) </li>
<li><blockquote>
<p>Heap 자료구조 이용
<img src="https://images.velog.io/images/alwayslee_12/post/14de2c4a-6496-4efe-921f-add098846563/image.png" alt="">
맨 위에는 참조횟수가 가장 적은 페이지
맨 위에 있는 페이지 쫓아내고 트리 재구성
참조횟수가 늘어나면 자리바꿈(트리의 크기만큼 비교)
시간 복잡도 : O(logn)</p>
</blockquote>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="다양한-캐싱-환경">다양한 캐싱 환경</h3>
<hr>
<ul>
<li>캐싱: 한정된 빠른 공간(캐시)에 요청된 데이터를 저장해 두었다가 후속 요청 시 캐시로부터 직접 서비스하는 방식(느린 저장 장치까지 가지 않음)<ul>
<li>paging 시스템 외에도 cache memory, buffer caching, Web caching 등 다양한 분야에서 사용</li>
</ul>
</li>
<li>캐시 운영의 시간 제약<ul>
<li>교체 알고리즘에서 삭제할 항목을 결정하는 일에 지나치게 많은 시간이 걸리는 경우 실제 시스템에서 사용할 수 없음</li>
<li>Buffer caching이나 Web Caching의 경우 O(1)에서 O(logn) 정도까지만 허용</li>
<li>Paging system인 경우<ul>
<li>page fault인 경우에만 OS가 관여</li>
<li>페이지가 이미 메모리에 존재하는 경우 참조시각 등의 정보를 OS가 알 수 없음(참조된지 오래되었거나 참조횟수가 얼마나 되는지에 대해 OS는 모름)</li>
<li>LRU나 LFU 알고리즘을 Paging 기법에 적용못함(Buffer Caching이나 Web Caching에는 적용가능)</li>
<li>O(1)인 LRU의 list 조작도 불가능</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="clock-algorithm">Clock Algorithm</h3>
<hr>
<p>LRU나 LFU는 Paging System에 적용할 수 없는 알고리즘이다.
그렇다면 Paging System을 위한 알고리즘은 무엇이 있을까? 바로 Clock Algorithm이다.
<img src="https://images.velog.io/images/alwayslee_12/post/933e31fb-9e99-4f18-a6aa-55b6cef7ba6b/image.png" alt=""></p>
<ul>
<li>LRU의 근사 알고리즘</li>
<li>여러 명칭으로 불림(Second chance algorithm, Not Used Recently, Not Recently Used)</li>
<li>Reference bit(메모리에 로드된 페이지가 참조되면 하드웨어가 reference bit을 1로 세팅해줌)를 사용해 교체 대상 페이지 선정(circular list)</li>
<li>Reference bit가 0인 것을 찾을 때가지 포인터를 하나씩 앞으로 이동</li>
<li>포인터 이동중에 Reference bit 1은 모두 0으로 교체</li>
<li>Reference bit가 0인 것을 찾으면 해당 페이지 교체</li>
<li>한 바퀴 돌아와도(=second chance) 0이면 그때는 replace 당함(한 바퀴 돌아도 0이라는 소리는 한 바퀴 돌때 동안 해당 페이지가 참조가 안됐다는 것을 의미)</li>
<li>자주 사용되는 페이지라면 second chance가 올 때 1</li>
<li>Clock Algorithm의 개선<ul>
<li>만약 변경 사항이 있는 페이지를 쫓을 경우 변경 사항이 반영 안된채로 지워버림(Backing Store에는 변경 전에 내용이 저장되어 있음)</li>
<li>reference bit과 modified bit(dirty bit)을 함께 사용</li>
<li>reference bit = 1 : 최근에 참조된 페이지</li>
<li>modified bit = 1 : 최근에 변경된 페이지(I/O를 동반하는 페이지)</li>
<li>modified bit을 이용해 1이 세팅되어 있다면, 변경 사항을 Swap Area(Backing Stage)에 반영하고 해당 페이지를 메모리에서 지움</li>
<li>변경 사항을 반영하는 작업을 I/O 작업이기때문에 시간이 걸림</li>
<li>그렇기 때문에 modified bit이 1인 페이지는 놔두고, 0인 페이지를 우선적으로 지워줌</li>
</ul>
</li>
</ul>
</br>

<h3 id="page-frame의-allocation">Page Frame의 Allocation</h3>
<hr>
<p>여태까지 물리적 메모리에 로드된 페이지들을 내쫓고 로드하는 작업이(알고리즘을 통한) 특정 프로세스에 국한된 것이 아닌, 아무 페이지에 대해서 이루어졌다.
그러나 프로그램이 원활하게 수행되기 위해서는 일련의 페이지들이 메모리에 같이 로드되어 있어야 한다.
즉, 프로세스별로 page를 적절하게 allocation 해주어야 한다.</p>
<ul>
<li>Allocation Problem: 각 프로세스에 얼만큼의 page frame을 할당할 것인가</li>
<li>Allocation의 필요성<ul>
<li>메모리 참조 명령어 수행시 명령어, 데이터 등 여러 페이지 동시 참조<ul>
<li>명령어 수행을 위해 최소한 할당되어야 하는 frame의 수가 있음</li>
</ul>
</li>
<li>Loop를 구성하는 page들은 한꺼번에 allocate 되는 것이 유리함<ul>
<li>최소한의 allocation이 없으면 매 loop마다 page fault 발생</li>
</ul>
</li>
</ul>
</li>
<li>Allocation Scheme(할당 방법)<ul>
<li>Equal allocation: 모든 프로세스에 똑같은 갯수 할당</li>
<li>Proportional allocation: 프로세스 크기에 비례해 할당</li>
<li>Priority allocation: 프로세스의 priority에 따라 다르게 할당</li>
</ul>
</li>
<li>Global Replacement<ul>
<li>미리 할당을 하지 않고 replacement algorithm을 사용하면 알아서 프로세스별로 메모리 할당량이 조절됨</li>
<li>LRU, LFU같은 알고리즘은 프로그램에 페이지를 할당하는 효과는 없음, Working set, PFF 알고리즘은 이러한 효과가 있음</li>
</ul>
</li>
<li>Local Replacement<ul>
<li>프로그램들에게 frame 할당</li>
<li>자신에게 할당된 frame내에서만 replacement</li>
<li>FIFO, LRU, LFU 등의 알고리즘을 process 별로 운영시</li>
</ul>
</li>
</ul>
</br>

<h3 id="thrashing">Thrashing</h3>
<hr>
<p>프로세스가 적당한 frame을 할당받지 못해 page fault가 자주 발생하는 현상
<img src="https://images.velog.io/images/alwayslee_12/post/5999f9e0-cdf3-4c0d-95c9-e7b52854e1ef/image.png" alt=""></p>
<ul>
<li>프로세스의 원활한 수행에 필요한 최소한의 page frame 수를 할당 받지 못한 경우 발생</li>
<li>page fault rate이 매우 높아짐</li>
<li>CPU 이용률이 낮아짐</li>
<li>OS는 MPD(Multiprogramming degree)를 높여야 한다고 판단</li>
<li>또 다른 프로세스가 시스템에 추가됨(higher MPD)</li>
<li>프로세스 당 할당된 frame의 수가 더욱 감소</li>
<li>프로세스는 page의 swap in/ swap out으로 매우 바쁨</li>
<li>대부분의 시간에 CPU는 한가함</li>
<li>low throughput</li>
<li>이를 방지하기 위해서는 Multiprogramming Degree를 조절해줘야 함(이를 해주는 알고리즘이 Worgin set, PFF)</li>
</ul>
</br>

<h3 id="working-set">Working-Set</h3>
<hr>
<ul>
<li>Locality of reference<ul>
<li>프로세스는 특정 시간 동안 일정 장소만을 집중적으로 참조</li>
<li>집중적으로 참조되는 해당 page들의 집합을 locality set이라 함</li>
</ul>
</li>
<li>Working-set Model<ul>
<li>Locality에 기반해 프로세스가 일정 시간 동안 월활하게 수행되기 위해 한꺼번에 메모리에 로드되어야 있어야 하는 page들의 집합을 Working Set이라 정의</li>
<li>Working set 모델에서는 프로세스의 working set 전체가 메모리에 올라와 있어야 수행되고 그렇지 않을 경우 모든 frame을 반납한 후 swap out</li>
<li>Thrashing 방지</li>
<li>Multiprogramming degree 결정</li>
</ul>
</li>
<li>Working-Set Algorithm<ul>
<li>Working set의 결정<ul>
<li>Working set window를 알아냄<ul>
<li>window size(현재 시점에서 window size 시간 전까지 참조한 페이지들)</li>
</ul>
</li>
</ul>
</li>
<li>Working set page들은 메모리에 로드</li>
<li>프로세스들의 working set size의 합이 page frame의 수보다 큰 경우, 일부 프로세스를 swap out 시켜 남은 프로세스의 working set을 우선적으로 충족시켜 줌</li>
<li>working set을 다 할당하고도 page frame이 남는 경우, swap out 되었던 프로세스에 working set을 할당</li>
</ul>
</li>
</ul>
</br>

<h3 id="pffpage-fault-frequency-scheme">PFF(Page-Fault Frequency) Scheme</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/11d73c07-9e9a-4f5a-8b0b-3de41f10dc6d/image.png" alt=""></p>
<ul>
<li>page-fault rate의 상한값과 하한값을 둠<ul>
<li>page fault rate이 상한값을 넘으면 frame을 더 할당</li>
<li>page fault rate이 하한값 이하면 할당 frame 수를 줄임</li>
</ul>
</li>
<li>빈 frame이 없으면 일부 프로세스를 swap out</li>
</ul>
</br>

<h3 id="page-size의-결정">Page Size의 결정</h3>
<hr>
<ul>
<li>page size를 감소시키면<ul>
<li>페이지 수 증가</li>
<li>페이지 테이블 크기 증가</li>
<li>내부 단편화 감소</li>
<li>disk transfer의 효율성 감소(페이지 크기가 작으면, 찾아야 하는 데이터 수는 늘어나고, 디스크에서 탐색하는데 시간이 오래걸림)<ul>
<li>seek/rotation VS transfer</li>
</ul>
</li>
<li>필요한 정보만 메모리에 올라와 메모리 이용이 효율적<ul>
<li>Locality의 활용 측면에서는 좋지 않음</li>
</ul>
</li>
</ul>
</li>
<li>Trend<ul>
<li>큰 사이즈의 페이지</li>
</ul>
</li>
</ul>
<h1 id="참고">참고</h1>
<p><a href="https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f">https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Prisma Client CRUD 함수의 리턴 타입]]></title>
            <link>https://velog.io/@alwayslee_12/Prisma-Client-CRUD-%ED%95%A8%EC%88%98%EC%9D%98-%EB%A6%AC%ED%84%B4-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@alwayslee_12/Prisma-Client-CRUD-%ED%95%A8%EC%88%98%EC%9D%98-%EB%A6%AC%ED%84%B4-%ED%83%80%EC%9E%85</guid>
            <pubDate>Mon, 10 Jan 2022 06:28:23 GMT</pubDate>
            <description><![CDATA[<h3 id="문제점">문제점</h3>
<hr>
<p>Graphql 찍먹을 위해 작고 귀여운 개인 프로젝트를 진행하던 중 service layer에서 <code>prisma</code> orm을 통해 CRUD를 하는 코드의 타입 설정부분에서 다음과 같은 오류 덕분에 하루 정도 헤매었다....
<code>(parameter) collectionId: string
Type &#39;(CollectionPlace &amp; { collection: Collection; place: Place; })[]&#39; is not assignable to type &#39;CollectionPlaceModel[]&#39;.
  Type &#39;CollectionPlace &amp; { collection: Collection; place: Place; }&#39; is not assignable to type &#39;CollectionPlaceModel&#39;.
    Types of property &#39;collection&#39; are incompatible.
      Property &#39;user&#39; is missing in type &#39;Collection&#39; but required in type &#39;CollectionModel&#39;.ts(2322)
collection.model.ts(11, 3): &#39;user&#39; is declared here.</code>
그니까 쉽게 말해서 왜 너가 선언한 <code>CollectionPlaceModel</code>에는 <code>collection</code> 타입을 갖는 속성이 없냐는 것이었다.(<del>아니 있는데 왜그러지...</del>)</p>
<p>계속된 삽질 끝에 그 원인을 파악하게 되었다.</p>
</br>

<h3 id="원인">원인</h3>
<hr>
<p>prisma client를 이용한 CRUD 함수의 리턴값은 prisma client에 정의되어있는 즉, <code>schema.prisma</code>에 정의해놓은 타입(모델?)들이다.
해당 타입과 모양이 다르다면, 위와 같은 에러를 뱉는 것이다.</p>
<p>그렇다면 나의 코드의 prisma client를 이용해 CRUD를 하고 그에 대한 결과를 리턴하는 함수의 타입이 prisma client에 정의되어 있는 타입과 불일치한다는 것이라는 결론이 나온다.</p>
<p>어느부분인지 보면,</p>
<pre><code class="language-typescript">async getCollection(collectionId: string): Promise&lt;CollectionPlaceModel[]&gt; {
    return await this.prisma.collectionPlace.findMany({
      ...
    });
  }</code></pre>
<p>위 코드의 리턴 타입 중 <code>CollectionPlaceModel[]</code>에 문제가 있는 것이다.</p>
<p>그럼 이제 <code>CollectionPlaceModel</code>이 어떻게 정의되어있는지를 본다.</p>
<pre><code class="language-typescript">import { Field, ID, Int, ObjectType } from &#39;@nestjs/graphql&#39;;
import { CollectionModel } from &#39;./collection.model&#39;;
import { PlaceModel } from &#39;../../places/models/place.model&#39;;

import { Collection, CollectionPlace, Place } from &#39;.prisma/client&#39;;

@ObjectType()
export class CollectionPlaceModel implements CollectionPlace {
  @Field(() =&gt; ID)
  id: string;

  @Field(() =&gt; CollectionModel)
  collection: CollectionModel;    //이 부분

  @Field(() =&gt; PlaceModel)
  place: Place;

  collectionId: string;
  placeId: string;
}
</code></pre>
<p>아하.... <code>collection: CollectionModel</code> 이 부분이 문제였던 것이다.
이유는 <code>CollectionModel</code>이라는 것은 내가 정의한 엔터티이고, 이는 prisma client에 정의된 스키마에 포함되지 않는 것이기때문이다.
즉, prisma client에서는 <code>collection</code>이라는 속성의 타입이 <code>Collection</code>(정의한 schema중 하나)라고 되어있는데, 위 코드에서는 <code>CollectionModel</code>(내가 정의한 엔터티)타입이라는 것이다.</p>
<blockquote>
<p>++@Field(()=&gt;CollectioModel) 부분은 왜 Collection이 아닌 CollectionModel로 써준 것일까?
해당 부분에는 값(value)가 들어가야 한다. 즉, 값으로 들어갈 수 있는 형식만이 저 부분에 들어갈 수 있는 것이다.(반대로 그렇지 못한 부분을 저곳에 할당하게 되면, 에러가 발생)
</br>
<code>Collection</code>은 type으로 취급된다. type은 컴파일 타임에만 남아있다(런타임에는 사라짐)
그래서 값이 될 수 없는 것이다.(interface도 마찬가지)
그래서 런타임에도 사라지지 않는 것들을 넣어야 하는 것이다.(class, const 등, 보통 class)
그래서 class 형식으로 된 엔터티인 <code>CollectionModel</code>을 넣어준 것이다.(모양은 Collection과 똑같음)</p>
</blockquote>
</br>

<h3 id="해결">해결</h3>
<hr>
<p>해당 부분을 prisma client의 부분과 일치시켜줌으로써 해결하게 되었다.
<code>collection: Collection</code>
<code>import {Collection} &#39;./prisma/client</code>(prisma client에 정의되어있는 <code>Collection</code> 타입으로...)</p>
</br>

<h3 id="깨달은-점">깨달은 점</h3>
<hr>
<p>타입 설정에 관련해서 보다 더 디테일하게 신경쓰자!
어떤 타입을 리턴하는지 등등을 생각하면서!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VLAN(Virtual LAN)]]></title>
            <link>https://velog.io/@alwayslee_12/VLANVirtual-LAN</link>
            <guid>https://velog.io/@alwayslee_12/VLANVirtual-LAN</guid>
            <pubDate>Thu, 06 Jan 2022 12:50:46 GMT</pubDate>
            <description><![CDATA[<p>한 대의 스위치를 마치 여러 대의 분리된 스위치처럼 사용</p>
<p>하나의 스위치에 여러개의 포트들이 있는데 이 포드들을 파트별로 나눠 마치 여러 대의 분리된 스위치처럼 사용하는 것</p>
<p><strong>VLAN에 대해 알아야 할 몇 가지</strong></p>
<ol>
<li>VLAN을 지원한다면, 스위치 이상의 장비이다.</li>
<li>VLAN은 한 대의 스위치를 여러 개의 네트워크(브로드캐스트 도메인)로 나누기 위해 사용한다.(나누어진 VLAN 간 통신은 라우터를 통해)</li>
<li>하나의 스위치에는 여러 개의 VLAN이 있고, 이 서로 다른 여러 개의 VLAN을 하나의 포트로 전송할 수 있는 하는 포트를 <code>트렁크 포트</code>라 한다.(같은 VLAN끼리는 통신 가능)</li>
</ol>
<p><strong>static VLAN과 dynamic VLAN</strong></p>
<ul>
<li>static VLAN: 스위치의 각 포트들을 원하는 VLAN에 하나씩 배정(고정으로 VLAN 배정)</li>
<li>dynamic VLAN: 포트에 접속하는 장비의 맥 어드레스를 보고 그 주소에 따라 VLAN을 배정하는 방식(이동이 잦은 사무 환경에 적합. 일일이 VLAN을 수동으로 세팅해주지 않아도 자신의 맥 어드레스에 따라 해당 네트워크를 자동으로 찾아주기 때문)<ul>
<li>특정 장비가 스위치에 접속</li>
<li>스위치는 Learning 기능을 이용해 해당 장비의 맥 어드레스를 학습</li>
<li>학습 후 스위치는 VMPS(VLAN Membership Policy Server) 서버에 해당 장비의 맥 어드레스를 알려줌</li>
<li>해당 장비의 맥 어드레스를 전달받은 VMPS 서버는 자신의 DB에서 해당 맥 어드레스와 VLAN을 매핑 후 이를 스위치에 알려줌</li>
<li>VLAN 정보를 받은 스위치는 해당 VLAN 값으로 세팅</li>
<li>즉, 장비의 맥 어드레스에 따라 VLAN을 세팅</li>
</ul>
</li>
</ul>
<p><strong>트렁킹과 VTP(VLAN Trunking Protocol)</strong></p>
<ul>
<li><p>트렁킹이란?</p>
<ul>
<li>여러 개의 VLAN들을 함께 실어나르는 것</li>
<li>실어나르는 VLAN의 패킷별로 어떤 VLAN 소속인지 구분(이름표 달기)<ul>
<li>구분짓는 방식은 두 가지가 있음</li>
<li>ISL 트렁킹: 시스코 장비끼리만 사용하는 방식. 모든 VLAN에 이름표를 붙임</li>
<li>IEEE 802.IQ: 트렁킹에 대한 표준 프로토콜. 이름표를 달지 않은 VLAN은 네이티브 VLAN</li>
</ul>
</li>
</ul>
<blockquote>
<p>각 VLAN의 패킷들은 같은 링크를 통해 전송되지만, 서로 다른 VLAN에 속해 있기 때문에 통신은 라우터를 통해서만 가능(강조)</p>
</blockquote>
</li>
<li><p>VTP이란?</p>
<ul>
<li><p>스위치들 간 VLAN 정보를 서로 주고받아 스위치들이 가지고 있는 VLAN 정보를 항상 일치시켜 주기 위한 프로토콜(일종의 동기화?)</p>
</li>
<li><p>VTP 서버는 하나의 스위치에서 VLAN 정보를 업데이트 하면 트렁크 링크를 통해서 자동으로 다른 스위치들의 VLAN 정보를 업데이트 함(다른 스위치들에 일일이 VLAN 정보를 업데이트를 하지 않아도 된다는 장점이 있음)</p>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2021 회고록]]></title>
            <link>https://velog.io/@alwayslee_12/2021-%ED%9A%8C%EA%B3%A0%EB%A1%9D</link>
            <guid>https://velog.io/@alwayslee_12/2021-%ED%9A%8C%EA%B3%A0%EB%A1%9D</guid>
            <pubDate>Tue, 04 Jan 2022 04:52:34 GMT</pubDate>
            <description><![CDATA[<p>2021/12/31에 회고록을 작성하려 했지만, 연말이고 각종 이벤트들이 겹쳐 계획대로 하진 못했었다.
그래도 한 해를 되돌아 보고 돌아오는 해를 잘 맞이하기 위해 늦게라도 회고록을 작성해보려 한다.</p>
</br>

<h3 id="issue">Issue</h3>
<hr>
<p>코로나 상황이라 그렇게 다이나믹한 이슈들이 많지는 않았다. 
그 부분이 아쉽지만, 한편으로는 덕분에 잘 된 것들도 있어 나쁘진 않았다.</p>
<ol>
<li>일학습병행제(인턴)<ul>
<li>졸업 필수 요건으로 인턴을 해야했기에 학교에서 운영하는 제도인 일학습병행제를 시작했다.</li>
<li>짧은 기간 일학습병행제에 대한 설명도 듣고, 참여 기업 탐방을 다녔다.(회사에서 일하시는 분들을 보며 멋지다는 느낌을 많이 받았고, 얼른 실무에 투입해 실력을 쌓고, 어디에든 기여를 해보고싶다는 생각이 들었다.)</li>
<li>탐방 기업 중 한군데에 면접을 봐 합격을 하게 되었다.(<del>인턴 되자마자 졸업요건에서 인턴이 폐지되었다......</del>)<ul>
<li>2021/8/2~2022/2/28까지 인턴 중이다.</li>
</ul>
</li>
<li>RPA 부서에서 유지보수를 담당하고 있다.(유지보수는 한번에 들어갔다 나오기때문에 널널한 시간들이 많긴하다. 그때는 다른 분들이 부탁하신 것들을 해드리거나, 개인 공부를 하곤한다.)</li>
<li>타인이 작성한 코드를 보면서, 특정 작은 부분을 수정하는 일이기에 남의 코드 보는 능력이 조금은 생긴 것 같고, 고객사의 유지보수 요구사항을 수용해 이루어지는 작업이기에 이 부분에 대한 대응 능력도 조금은 생긴 것 같다.</li>
</ul>
</li>
</ol>
</br>

<ol start="2">
<li>장학금<ul>
<li>코로나로 비대면 수업을 들으면서, 놓친 부분들을 다시 또 다시 볼 수 있다는 점 덕분에 코로나 이후 성적을 좋게 받을 수 있었다.</li>
<li>집중도도 더 높아지고, 무엇보다 내가 듣고 싶을 때 들을 수 있다는 점이 좋았다.</li>
<li>그 덕분에 처음 학기에는 30% 장학금을 받고, 인턴가기 전 막학기에는 5등으로 50% 장학금을 받았다. </li>
<li>너무 뿌듯했고, 보람찼다.(장학금을 받아본지가 1년만이라 그런가..)</li>
</ul>
</li>
</ol>
</br>

<ol start="3">
<li>동아리<ul>
<li>사람들과 협업해 무언가를 해결하고 만들어가는 것을 좋아해서 스터디나, 프로젝트 하기를 좋아한다.</li>
<li>나는 같이 했을 때의 시너지가 좋은 것 같고, 책임감과 해야한다는 강제성이 생길 때 실력 향상이 이루어지는 것 같다.</li>
<li>그래서 IT 동아리에 들어가 스터디와 프로젝트를 다양한 분야의 사람들과 진행해보고 싶었다.</li>
<li>이 전에 두번정도 지원 했었지만 떨어졌고, 자소서에 쓴 내용에 대한 증명?(예를 들면, 개발을 열심히 했다고 해놓고 깃을 까보니 10커밋?처럼)이 안된 것이 패인이라고 생각했다.</li>
<li>그래서 1일 1커밋을 약 100일 정도 진행해보았다. 개인 프로젝트도 하고, 개인 공부도 하고 하면서</li>
<li>그 다음 지원한 동아리는 이러한 노력이 보였는지 합격할 수 있었다.</li>
<li>참 기분이 좋았다. 들어가서 열심히 적극적으로 참여해보리라 다짐한다.</li>
<li>Node(Server)팀에 들어가 NestJS를 배우게 된다.</li>
<li>그리고 디자인팀과 IOS팀과 하나의 팀을 이루어 해커톤을 진행한다.</li>
<li><code>미츄</code>라는 비대면 자기소개 서비스이며, 이를 <code>AppStore</code>에 성공적으로 배포하게되었다.</li>
<li>반응이 좋았고, 동아리 종무식에서 <code>최고의 아이디어</code> 상을 받게 된다.</li>
<li>동아리는 나태해지지 않기 위해, 항상 함께하기 위해, 발전하기 위해, 양질의 정보를 얻기 위해 계속 할 생각이다.</li>
</ul>
</li>
</ol>
 </br>

<h3 id="2022">2022</h3>
<hr>
<p>오는 해(이미 온 해) 2022에 하는 다짐과 이루고 싶을 것들을 적어본다.</p>
<ol>
<li>계획적인(주도적인) 생활<ul>
<li>하루하루를 내가 계획한대로, 주도적으로 살아볼 생각이다.</li>
<li>플래너를 하나 샀다. 하루하루 ToDO 리스트를 적을 수 있으며, 거기에 하루 할일을 적어놓고, 이루는대로 체크하고 있다.</li>
<li>중요한 일정들도 까먹지 않게 적어본다.(뇌에 다시 새기는 느낌)</li>
<li>할 수 있는 한 최대한 구체적으로 적어보려 한다.</li>
</ul>
</li>
</ol>
<p><img src="https://images.velog.io/images/alwayslee_12/post/200fbc32-9ff2-4425-812a-13346c9de554/image.png" alt=""></p>
<ol start="2">
<li>취뽀<ul>
<li>사실 최고로 바라는 것이다.</li>
<li>많이 부족하기에 많이 성장하고 싶기에 하루하루 차근차근 해보고, 배워보면서 나아갈 생각이다.</li>
<li>공고도 많이 보고, 지원도 해볼 것이다.</li>
<li>많이 배우고, 성장할 수 있고, 함께하기 좋은 곳이었으면 좋겠다.</li>
</ul>
</li>
</ol>
</br>

<ol start="3">
<li>책 꾸준히 읽어보기<ul>
<li>하루에 30분이라도 책을 꾸준히 읽어보려 한다.</li>
<li>이해하지 못하더라고 매일 읽고, 어려운 내용이라도 그냥 읽어보려 한다.</li>
<li>일단은 집에 사놓은 책들부터(Clean Code 등등)</br>

</li>
</ul>
</li>
</ol>
<h3 id="마무리">마무리</h3>
<hr>
<p>처음 적어보는 회고록이라 두서없이 적었던 것 같다.
이번 한 해는 후회없이 노력해보고 싶다. 
여태까지는 무언가를 꾸준히, 하루도 빠짐없이 해본 것들이 없다.
이제부터라도 후회없이, 꾸준히 무엇이라도 해보고자 한다.
또한, 좋은 곳에서 좋은 사람들과 함께 많이 배우고 성장하고 싶다.
즐거웠던 2021이었고, 즐거울 2022를 맞으며, 나를 포함한 모든 사람들이 잘되고 행복했으면 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[.gitignore가 .env를 인식못하다]]></title>
            <link>https://velog.io/@alwayslee_12/.gitignore%EA%B0%80-.env%EB%A5%BC-%EC%9D%B8%EC%8B%9D%EB%AA%BB%ED%95%98%EB%8B%A4</link>
            <guid>https://velog.io/@alwayslee_12/.gitignore%EA%B0%80-.env%EB%A5%BC-%EC%9D%B8%EC%8B%9D%EB%AA%BB%ED%95%98%EB%8B%A4</guid>
            <pubDate>Wed, 29 Dec 2021 05:35:15 GMT</pubDate>
            <description><![CDATA[<h3 id="배경">배경</h3>
<hr>
<p>DB 연결을 위해 orm 세팅 작업을 진행하고, DB 연결에 필요한 설정 값들(DB_URL, DB_PORT 등)을 .env 파일에 추가해주었다.</p>
<p>그리고 이제 설정 값들의 정보를 보안을 위해 저장소에 올라가지 않도록 하기 위해 .gitignore에 .env 파일을 무시하도록 추가해주었다.</p>
</br>

<h3 id="문제">문제</h3>
<hr>
<p>그런데, .gitignore에 .env 파일을 추가해도 파일을 인식하지 못했는지 무시되지 않는 것이었다.(파일이 밝은 회색으로 되지 않음. VSCode 기준)</p>
<p>이후 약 1~2시간 정도의 삽질이 시작된다...</p>
<p>그러다 문제가 무엇인지 알게되었다.</p>
<p>문제는 커밋을 나눠서 찍기 위해 하는 작업마다 커밋을 찍는 과정에서 .env 파일도 같이 커밋되어 staging area에 들어가버린 것이었다.</p>
<p><code>Stack Overflow</code>
<img src="https://images.velog.io/images/alwayslee_12/post/41dcfa76-e005-4bb3-b15e-839214b328b0/image.png" alt=""></p>
</br>

<h3 id="해결">해결</h3>
<hr>
<p>staging area에서 <code>git rm env --cached</code> 명령어로 .env 파일을 지워주고, 다시 새로운 .env 파일을 생성했다.</p>
<p>.env 파일이 인식되었고, 드디어 이 파일을 무시하기 시작했다...</p>
</br>

<h3 id="깨달음">깨달음</h3>
<hr>
<p>아무 생각없이 커밋하지 말자.</p>
<p>.gitignore 파일은 이미 커밋된 파일을 무시하지는 못한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[REST vs GraphQL]]></title>
            <link>https://velog.io/@alwayslee_12/REST-vs-GraphQL</link>
            <guid>https://velog.io/@alwayslee_12/REST-vs-GraphQL</guid>
            <pubDate>Sun, 26 Dec 2021 05:04:30 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/alwayslee_12/post/a5fc567d-a370-427f-a6e6-1ac90c1db428/1.JPG" alt="">
최근 facebook에서 개발한 GraphQL이라는 API 쿼리 언어를 접하고 한번 공부해보기로 했다. 
GraphQL에 대해 학습을 하기 전 REST와 다른점은 무엇인지에 대해 궁금해져 그 부분들을 먼저 짚고 시작해보려 한다.</p>
<h3 id="공통점">공통점</h3>
<hr>
<ol>
<li>자원에 ID를 표기해 구분할 수 있음</li>
<li>응답으로 JSON 데이터를 받음</li>
<li>해당 자원을 읽는 행위인지 쓰는 행위인지에 대한 구분이 있음</li>
<li>요청이 서버측의 특정 함수에 매핑됨</li>
</ol>
<h3 id="차이점">차이점</h3>
<hr>
<p>*<em>자원의 정보와 자원에 대한 행위
*</em>
REST는 한 URL에 자원의 정보와 자원에 대한 행위(HTTP Method)가 묶여 있음
<code>GET /books/1</code></p>
<p>GraphQL은 자원의 정보와 행위가 분리되어 있음</p>
<pre><code class="language-typescript">  //자원의 정보
  type Book {
      id: ID
        title: String
        published: Date
           price: String
        author: Author
  }
  type Author {
        id: ID
        firstName: String
        lastName: String
        books: [Book]
  }
  //자원에 대한 행위
  type Query {
        book(id: ID!): Book
        author(id: ID!): Author
  }
  ```</code></pre>
</br>

<p><strong>자원의 종류와 양에 대한 결정</strong></p>
<p>REST는 서버에서 정의</p>
<p>GraphQL은 필요한 자원의 종류와 양을 클라이언트에서 정의</p>
</br>


<p><strong>요청 형식</strong></p>
<p>REST는 <code>GET /books/:id</code>, <code>GET /authors/:id</code>과 같이 API가 접근할 수 있는 자원의 정보가 리스트로 되어 있는 linear 형식 </p>
<p>GraphQL은 자원의 정보 및 자원에 대한 행위를 URL에 표기하지 않고 <code>GraphQL schema</code>에 표기</p>
<pre><code>//Query- 조회
type Query {
  book(id: ID!): Book
  author(id: ID!): Author
}
//Mutation- 수정(삽입, 삭제, 변경)
type Mutation {
  addComment(input: AddCommentInput): Comment
}

type Book { ... }
type Author { ... }
type Comment { ... }
input AddCommentInput { ... }</code></pre><br>

<p><strong>complex resources</strong></p>
<p>REST는 복잡한 관계로 얽힌 자원들에 대한 정보를 여러 요청으로 얻음</p>
<p>GraphQL은 한번의 요청으로 복잡한 관계로 얽혀있는 자원들에 대한 정보를 얻을 수 있음</p>
</br>

<p><strong>handler와 resolver</strong></p>
<p>REST에서는 하나의 요청 당 하나의 <strong>handler 함수</strong>를 호출하지만,</p>
<p>GrapghQL에서는 하나의 쿼리로 많은 <strong>resolvers</strong>를 호출해 여러 자원에 접근한 응답을 얻을 수 있음</p>
</br>

<h3 id="결론">결론</h3>
<hr>
<p>REST와 GraphQL의 동작 과정들은 유사하다.</p>
<p>결국, 근간은 원하는 자원에 접근해서 원하는 응답을 받는데 있기 때문이다.</p>
</br>

<p>차이점 중에 가장 핵심인 부분은 <strong>GraphQL은 한번의 요청으로 여러 자원에 대한 정보를 얻을 수 있다</strong>는 것이다.</p>
<p>이로 인해 API를 설계할 때, 여러 엔드 포인트를 정의할 필요가 없어지고, 클라이언트는 필요한 데이터만 얻을 수 있게 해주어 개발의 효율성과 더불어 많은 것들을 절약할 수 있게 해준다.</p>
</br>

<p>아직은 REST에 비해 reference와 tool 등이 적지만, 유용하고 배워봄직하다는 것은 틀림없다.</p>
</br>

<p>++ GQL 사용해보면서 느낀점 쓰기. GQL과 REST의 사용 시기 구분하기(언제 GQL이 유리하고, 언제 REST가 유리한지) </p>
<h1 id="참고">참고</h1>
<p><a href="https://www.apollographql.com/blog/graphql/basics/graphql-vs-rest/">https://www.apollographql.com/blog/graphql/basics/graphql-vs-rest/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Hot Reload]]></title>
            <link>https://velog.io/@alwayslee_12/Hot-Reload</link>
            <guid>https://velog.io/@alwayslee_12/Hot-Reload</guid>
            <pubDate>Fri, 24 Dec 2021 07:39:13 GMT</pubDate>
            <description><![CDATA[<p>NestJS 프로젝트를 빌드할 때 빌드 시간에 가장 큰 영향을 미치는 것이 바로 TypeScript 컴파일이다. 
원래라면 프로젝트에 변경사항을 적용하고 다시 실행시킬때마다 <strong>전체적으로 다시 TypeScript 컴파일</strong>을 해야한다.
조그마한 변경에도 이 일을 똑같이 반복하게 된다면, 프로젝트의 빌드 시간을 계속 꽤 오랫동안 기다려야 할테고, <strong>개발의 효율성도 떨어질 것이다.</strong></p>
<p>이러한 상황을 해결하기 위해 NestJS에서는 <code>Hot Reload</code>라는 기능을 제공한다.
<code>Hot Reload</code>는 변경 사항을 적용하고 다시 프로젝트를 빌드할 때, 전체적으로 TypeScript 컴파일을 진행하는 것이 아닌 <strong>변경된 부분만 컴파일</strong> 하도록 함으로써 <strong>개발 시간을 단축</strong>시켜 준다.(프로젝트가 빌드되기를 기다리는 시간이 많이 줄여주기 때문)</p>
<p><code>Hot Reload</code>를 사용하기 위해선 다음과 같은 세팅을 해주면 된다.
Nest CLI를 이용한 세팅을 할 것이다.</p>
</br>

<h3 id="installation">Installation</h3>
<hr>
<p><code>npm install --save webpack-node-externals run-script-webpack-plugin webpack</code>
이렇게 필요한 패키지 설치한다.</p>
<blockquote>
<p>변경 된 사항만 컴파일 할 수 있게 해주는 게 webpack HMR(Hot-Module Replacement)이다.
<strong>webpack</strong>은 파일들을 그룹핑 해주는 도구인 번들러 중 하나이며, 여러 개의 파일을 하나로 묶어주어 <strong>네트워크 접속의 부담을 줄여 빠른 서비스를 제공</strong>하게 하며, 모듈을 사용해 복잡하고 긴 코드를 작성할 때 사용 용도에 따라 파일 단위로 구분해, 다<strong>른 파일에서 해당 클래스나 함수가 필요할 때 가져와서 사용</strong>할 수 있게 한다.
또한, 외부 라이브러리의 의존성도 쉽게 관리할 수 있다.
이러한 webpack은 모듈 시스템의 구성, 로더 사용, 빠른 컴파일 속도 등의 장점을 가지고 있으며, <strong>HMR은 webpack에 속하며, 그 중에서 빠른 컴파일 속도를 담당</strong>한다.</p>
</blockquote>
</br>

<h3 id="configuration">Configuration</h3>
<hr>
<p>필요한 패키지를 설치하고, 루트 디렉터리에 <code>webpack-hmr.config.js</code> 파일을 생성한다.</p>
<pre><code class="language-typescript">const nodeExternals = require(&#39;webpack-node-externals&#39;);
const { RunScriptWebpackPlugin } = require(&#39;run-script-webpack-plugin&#39;);

module.exports = function (options, webpack) {
  return {
    ...options,
    entry: [&#39;webpack/hot/poll?100&#39;, options.entry],
    externals: [
      nodeExternals({
        allowlist: [&#39;webpack/hot/poll?100&#39;],
      }),
    ],
    plugins: [
      ...options.plugins,
      new webpack.HotModuleReplacementPlugin(),
      new webpack.WatchIgnorePlugin({
        paths: [/\.js$/, /\.d\.ts$/],
      }),
      new RunScriptWebpackPlugin({ name: options.output.filename }),
    ],
  };
};</code></pre>
</br>

<h3 id="hmr-활성화">HMR 활성화</h3>
<hr>
<p>이제 main.ts에 webpack 관련 코드를 추가해 HMR을 활성화한다.</p>
<pre><code class="language-typescript">declare const module: any;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);

  if (module.hot) {
    module.hot.accept();
    module.hot.dispose(() =&gt; app.close());
  }
}
bootstrap();</code></pre>
<p>그리고 <code>package.json</code> 파일에 스크립트를 추가하면, CLI에 <code>npm run start:dev</code> 명령으로 사용할 수 있다.</p>
<pre><code class="language-json">&quot;start: dev&quot;:&quot;nest build --webpack --webpackPath webpack-hmr.config.js --watch&quot;</code></pre>
<h1 id="참고">참고</h1>
<p><a href="https://docs.nestjs.kr/recipes/hot-reload">https://docs.nestjs.kr/recipes/hot-reload</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[null과 undefined는 공집합?]]></title>
            <link>https://velog.io/@alwayslee_12/null%EA%B3%BC-undefined%EB%8A%94-%EA%B3%B5%EC%A7%91%ED%95%A9</link>
            <guid>https://velog.io/@alwayslee_12/null%EA%B3%BC-undefined%EB%8A%94-%EA%B3%B5%EC%A7%91%ED%95%A9</guid>
            <pubDate>Thu, 02 Dec 2021 11:57:11 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 하던 중 인터페이스로 타입을 선언하는 과정에서 null 타입도 아니고 유니언 타입으로 null을 포함해주지도 않았는데 null 값을 넣었을 때 오류가 나지 않는 것을 보고 의아해 했었다.</p>
<p>바로 구글링에 들어갔고, 도움이 되는 정보를 얻을 수 있었다.</p>
<h3 id="null-undefined-like-공집합">null, undefined like 공집합?</h3>
<hr>
<p>기본적으로 모든 타입은 null과 undefined를 포함한다고 한다.(default. 자동으로)</p>
<pre><code class="language-typescript">//예시
const num: number= null                //OK
const str: string= undefined            //OK
...</code></pre>
<p>마치, 집합들은 항상 부분집합으로 공집합을 가지는 것과 같다고 생각했다.</p>
</br>

<h3 id="null-undefined가-포함되지-않게-하는-방법">null, undefined가 포함되지 않게 하는 방법</h3>
<hr>
<p>자동으로 null과 undefined를 포함하지 않으려면?
<code>strictNullChecks</code>를 설정해주면 된다고 한다.</p>
<p><strong>Where?</strong>
<code>tsconfig.json</code>의 <code>compilerOPtions</code> 부분에 있는 <code>strictNullChecks</code>를 <code>true</code>로 해주면 된다고 한다.</p>
<pre><code class="language-typescript">//tsconfig.json
{
  &quot;compilerOptions&quot;: {
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;declaration&quot;: true,
    &quot;removeComments&quot;: true,
    &quot;emitDecoratorMetadata&quot;: true,
    &quot;experimentalDecorators&quot;: true,
    &quot;allowSyntheticDefaultImports&quot;: true,
    &quot;target&quot;: &quot;es2017&quot;,
    &quot;sourceMap&quot;: true,
    &quot;outDir&quot;: &quot;./dist&quot;,
    &quot;baseUrl&quot;: &quot;./&quot;,
    &quot;incremental&quot;: true,
    &quot;skipLibCheck&quot;: true,
    &quot;strictNullChecks&quot;: false,            //true로 변경!!
    &quot;noImplicitAny&quot;: false,
    &quot;strictBindCallApply&quot;: false,
    &quot;forceConsistentCasingInFileNames&quot;: false,
    &quot;noFallthroughCasesInSwitch&quot;: false
  }
}</code></pre>
<h3 id="결론">결론</h3>
<hr>
<p>타입스크립트에서 기본적으로 모든 타입들은 null, undefined를 포함한다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Express.JS의 Route Handler Mapping]]></title>
            <link>https://velog.io/@alwayslee_12/Express.JS%EC%9D%98-Route-Handler-Mapping</link>
            <guid>https://velog.io/@alwayslee_12/Express.JS%EC%9D%98-Route-Handler-Mapping</guid>
            <pubDate>Fri, 26 Nov 2021 05:13:52 GMT</pubDate>
            <description><![CDATA[<p>NestJS로 API를 뽑아내는 작업을 하면서, 직면한 문제이다.</p>
</br>

<h3 id="문제">문제</h3>
<hr>
<p><strong><em><code>a/:id</code>가 <code>a/b</code>를 먹다</em></strong>
굉장히 신중하게 Route Handler의 URL을 작업했기 때문에 URL을 바꾸는 방법은 저 뒤로 하고, 왜 params를 포함한 url이 그 뒤에꺼를 먹을까에 대해 계속 분석해 보았다.(<del>바보</del>)</p>
<p>무조건 <code>:id</code>는 <code>number</code> 형식일 것이라 생각해 <code>string</code> 형식이 들어오면 당연히 그 뒤에 Handler로 매핑될 것이라 생각한 것이다.
실상은 그렇지 않았고, <code>a/b</code>에서 <code>a</code>뒤에 <code>b</code>가 <code>:id</code>로 인식되어 <code>a/:id</code>로 매핑된 것이다.
그래서 나는 <code>a/b</code>로 매핑되기를 의도하고 API를 쏘는데 계속 <code>a/:id</code>로 매핑되었던 것이다.</p>
<p>문제를 알았으니 이제 어떻게 해결할지를 강구해보았다.</p>
</br>

<h3 id="해결">해결</h3>
<hr>
<p>처음에는 params를 포함한 URL이 더 높은 <strong>우선순위</strong>를 가진다고 생각했었다.
하지만, Route Handler가 매핑되는 순서는 우선순위에 기반한 것이 아니었고, <strong>Controller에 나열된 순서</strong>대로 매핑되는 것이었다.(by Express.JS. 다른건 모르겠지만, Express는 그렇다) </p>
<p>그래서 params를 포함한 URL을 가진 Route Handler 위에 위치시켰고, 그에 따라 문제가 해결되었다(<del>허무...</del>)</p>
</br>

<h3 id="짚어보기">짚어보기</h3>
<hr>
<p>어떤 프레임워크를 이용하던, 의도한 API로 매핑이되지 않을때는 Route Handler가 어떤 순서로 매핑이 되는지부터 확인하자!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스위치]]></title>
            <link>https://velog.io/@alwayslee_12/%EC%8A%A4%EC%9C%84%EC%B9%98</link>
            <guid>https://velog.io/@alwayslee_12/%EC%8A%A4%EC%9C%84%EC%B9%98</guid>
            <pubDate>Tue, 23 Nov 2021 14:11:05 GMT</pubDate>
            <description><![CDATA[<h3 id="스패닝-트리-프로토콜">스패닝 트리 프로토콜</h3>
<hr>
<p>스위치나 브리지에서 발생하는 루핑을 막아주기 위한 프로토콜</p>
<p>출발지에서 목적지로 가는 경로가 2개 이상 존재할 떄 1개의 경로만을 남겨두고 나머지는 모두 끊었다가, 사용하던 경로에 문제가 생기면 끊었던 경로를 하나씩 살림</p>
</br>

<p><strong>두 가지 개념</strong></p>
<ol>
<li><p><strong>브리지ID:</strong> 브리지나 스위치들이 통신 시 서로를 확인하기 위한 고유 번호</p>
<ul>
<li>브리지 ID 생성 방법<ul>
<li>16비트의 브리지 우선순위와 48비트의 맥 어드레스로 만들어짐<ul>
<li>브리지 우선순위에 올 수 있는 수는 0~2^16-1까지(아무런 구성도 하지 않을 시 디폴트는 중간값인 32768)</li>
<li>그 뒤의 자신의 고유 맥 어드레스가 옴</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Path Cost</strong></p>
<ul>
<li><p>한 스위치에서 다른 스위치로 가는 데 드는 비용</p>
</li>
<li><p>Path Cost 계산 방법</p>
<ul>
<li><p>Path Cost는 속도가 빠를수록 값이 작음</p>
</li>
<li><p>속도에 따른 Path Cost 표</p>
<ul>
<li><table>
<thead>
<tr>
<th>Bandwidth</th>
<th>Path Cost</th>
</tr>
</thead>
<tbody><tr>
<td>4Mbps</td>
<td>250</td>
</tr>
<tr>
<td>10Mbps</td>
<td>100</td>
</tr>
<tr>
<td>16Mbps</td>
<td>62</td>
</tr>
<tr>
<td>45Mbps</td>
<td>39</td>
</tr>
<tr>
<td>100Mbps</td>
<td>19</td>
</tr>
<tr>
<td>155Mbps</td>
<td>14</td>
</tr>
<tr>
<td>622Mbps</td>
<td>6</td>
</tr>
<tr>
<td>1Gbps</td>
<td>4</td>
</tr>
<tr>
<td>10Gbps</td>
<td>2</td>
</tr>
</tbody></table>
</li>
<li><p>ex) 스위치 A와 스위치 B가 10Mbps 링크로 연결되어 있으면, Path Cost= 1000</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</br>

<p><strong>세 가지 기본적인 동작</strong></p>
<ol>
<li><strong>네트워크당 하나의 루트 브리지를 갖음</strong><ul>
<li>하나의 브로드캐스트 도메인에 하나씩의 루트 브리지가 있음</li>
<li>루트 브리지는 스패닝 트리 프로토콜 수행 시 기준이 되는 브리지(스위치)</li>
<li><strong>루트 브리지 선정</strong><ul>
<li>BID가 가장 낮은 값이 루트 브리지가 됨<ul>
<li>ex) 스위치 A,B,C가 있다고 가정, 스위치 A의 BID= 32768.1111.1111.1111, 스위치 B의 BID= 32768.2222.2222.2222, 스위치 C의 BID= 32768.3333.3333.3333</li>
<li>먼저, 스위치 B, C 부팅 -&gt; BPDU(Bridge Protocol Data Unit. 스패닝 트리에 대한 여러가지 정보를 담고 있으면서 2초에 한 번 뿌려지는 프레임) 공유(초기 Sender BID는 자신의 BID, 루트 브리지의 BID는 자신의 BID) -&gt; 자신의 BPDU에 있는 루트 브리지 BID가 상대방의 루트 브리지 BID보다 작으면 BPDU의 BID를 변경</li>
<li>스위치 A 부팅 -&gt; 초기 BPDU를 뿌림(Sender BID가 자신의 BID, 루트 브리지의 BID가 자신의 BID인) -&gt; 다같이 BPDU 공유 -&gt; BPDU의 루트 브리지의 BID는 BID가 제일 작은 스위치 A의 BID가  됨</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>루트 브리지가 아닌 나머지 모든 브리지는 무조건 하나씩의 루트 포트를 갖음</strong><ul>
<li>루트 포트란 루트 브리지에 가장 빨리 갈 수 있는 포트</li>
<li>루트 브리지가 아닌 브리지들은 루트 브리지 쪽과 가장 가까이 있는 루트 포트를 하나씩 지정해주어야 함</li>
<li><strong>루트 포트 선정</strong><ul>
<li>Root Path Cost(루트 브리지까지의 Path Cost)가 가장 작은 포트가 루트 포트</li>
</ul>
</li>
</ul>
</li>
<li><strong>세그먼트당 하나씩의 Designated 포트를 갖음</strong><ul>
<li>세그먼트란 브리지 또는 스위치 간 서로 연결된 링크</li>
<li>이 링크에서 반드시 한 포트는 Designated 포트로 선출되어야 함</li>
<li><strong>Designated 포트 선정</strong><ul>
<li>링크 양끝에 달려있는 두 포트 중 Root Path Cost가 작은 포트가 Designated 포트가 됨</li>
<li>루트 브리지의 모든 포트들은 항상 Designated 포트가 됨(Root Path Cost가 0이기때문)</li>
<li>두 포트의 Root Path Cost가 같다면?<ul>
<li><strong>1단계</strong>: 누가 더 작은 Root BID를 가졌는지</li>
<li><strong>2단계</strong>: Root Path Cost 값은 누가 더 작은지</li>
<li><strong>3단계</strong>: 누구의 BID가 더 낮은지</li>
<li><strong>4단계</strong>: 누구의 포트 ID가 더 낮은지</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>스패닝 트리 프로토콜은 위 세가지 규칙을 적용해 어느 쪽 링크를 살려두고, 어느 쪽 링크를 끊을지 결정(루트 포트나 Designated 포트가 아닌 포트는 다 끊음)</p>
</br>

<p><strong>5가지 상태 변화</strong></p>
<p>이렇게 스패닝 트리 프로토콜을 구현해 나가는 과정에서 모든 스위치나 브리지의 포트들을 5가지 상태로 변한다.</p>
<ul>
<li>Disabled: 포트가 고장나서 사용할 수 없거나 네트워크 관리자가 포트를 일부러 Shut Down 시켜놓은 것<ul>
<li>데이터 전송 x</li>
<li>맥 어드레스 학습 x</li>
<li>BPDU 공유 x</li>
</ul>
</li>
<li>Blocking: 스위치를 맨 처음 켤 때, 또는 Disabled 되어 있는 포트를 관리자가 다시 켰을 때<ul>
<li>데이터 전송 x</li>
<li>맥 어드레스 학습 x</li>
<li>BPDU 공유 o</li>
</ul>
</li>
<li>Listening: Blocking 상태에 있던 스위치 포트가 루트 포트나 Designated 포트로 선정되면, Listening 상태로 변화<ul>
<li>데이터 전송 x</li>
<li>맥 어드레스 학습 x</li>
<li>BPDU 공유 o</li>
</ul>
</li>
<li>Learning: Listening 상태에 있던 스위치 포트가 포워딩 딜레이 디폴트 시간인 15초 동안 상태를 유지하면, Learning 상태로 넘어감<ul>
<li>데이터 전송 x</li>
<li>맥 어드레스 학습 o</li>
<li>BPDU 공유 o</li>
</ul>
</li>
<li>Forwarding: 스위치 포트가 Learning 상태에서 다른 상태로 넘어가지 않고 다시 포워딩 딜레이 디폴트 시간인 15초 동안 상태를 유지하면, Forwarding 상태로 넘어감<ul>
<li>데이터 전송 o</li>
<li>맥 어드에스 학습 o</li>
<li>BPDU 공유 o</li>
</ul>
</li>
</ul>
<p><img src="https://images.velog.io/images/alwayslee_12/post/a601b036-5f9a-4150-8c5c-95d546a5b7cf/1.JPG" alt=""></p>
<p>Listening, Learning, Forwarding 상태에 있던 포트도 루트 포트나 Designated 포트에서 탈락되면, Blocking 상태로 넘어갈 수 있음</p>
<p>또한, 포트의 고장이나 사용자에 의한 Shut Down으로 인해 Disabled 상태로 넘어갈 수 있음</p>
<p>이제 Root Port와 Designated Port는 <code>Forwarding</code> 상태, Non Designated Port는 <code>Blocking</code> 상태가 되어 출발 노드에서 도착 노드로 가는 경로가 하나만 존재하게 됨</p>
<blockquote>
<p>루트 브리지가 어디로 선정되냐와 링크의 속도가 얼마나 빠르냐에 따라 어떤 링크가 살고, 어떤 링크가 죽을지 결정 됨</p>
</blockquote>
</br>

<h3 id="스패닝-트리-재편성">스패닝 트리 재편성</h3>
<hr>
<p><strong>필수 용어</strong></p>
<ul>
<li>Hello Time: 루트 브리지가 얼마 만에 한 번씩 헬로 BPDU를 보내는지에 대한 시간(디폴트 헬로 타임은 2초)</li>
<li>Max Age: 브리지들이 루트 브리지로부터 헬로 패킷을 받지 못하면 맥스 에이지 시간 동안 기다린 후 스패닝 트리 구조 변경 시작</li>
<li>Forwarding Delay: 브리지 포트가 블로킹 상태에서 포워딩 상태로 넘어갈 때까지 걸리는 시간(디폴트 15초)</li>
</ul>
<p><strong>스패닝 트리 재편성</strong></p>
<ul>
<li>루트 브리지는 자신과 연결된 나머지 브리지들에게 헬로 패킷을 매 2초(디폴트 헬로 타임)마다 뿌림</li>
<li>이 패킷을 받은 브리지들은 자신의 Designated 포트로 다시 그 헬로 패킷 전달</li>
<li>만약 헬로 패킷을 받는 포트쪽의 링크 연결이 끊어졌다면, 맥스 에이지 시간동안 기다림(디폴트 20초)</li>
<li>맥스 에이지 시간 동안에도 헬로 패킷이 오지 않는다면, 스패닝 트리 변경 시작</li>
<li>블로킹 상태에 있는 포트 중 헬로 패킷을 받고 있는 포트를 Designated 포트로 재선정하고(Forwarding 상태로 변경), 연결이 끊긴 포트를 Blocking 상태로 변경(디폴트 30초= 15+15)</li>
</ul>
<p>=&gt; 대략 50초 정도 소요(생각보다 오래 걸림)</p>
</br>

<h3 id="카타리스트-스위치">카타리스트 스위치</h3>
<hr>
<p>CISCO에서 만든 스위치의 한 종류</p>
<p><strong>Cisco Catalyst 2960-24PC-L</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/2bf519d1-8e8e-49ce-ab33-6daa9f994406/2.JPG" alt=""></p>
<p>24는 포트 수 즉, 24개의 포트</p>
<p>P= PoE를 지원하는 스위치</p>
<p>C= Dual Purpose Uplink(오른쪽 네개 포트중 위 두 포트는 SFP포트(광케이블) 아래 2 포트는 10/100/1000 Base T 포트. 두 방식 중 선택해서 사용(UTP). 동시 사용은 불가)</p>
</br>

<p><strong>Cisco Catalyst 2960-48PST-L</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/98601fa8-4cfa-4895-b7ee-1865b6d5a784/3.JPG" alt=""></p>
<p>48은 포트 수 즉, 48개의 포트</p>
<p>P= PoE를 지원하는 스위치(PoE= Power over Ethernet. 이더넷 케이블 위에 데이터뿐만 아니라 전원까지 같이 보냄, IP 전화기, AP 무선 랜 장비, IP 감시 카메라 등에 전원까지 같이 제공해야 함)</p>
<p>ST= SFP와 TP 방식의 업링크 포트를 제공한다는 뜻(TP는 UTP 방식. SFP는 광케이블용 접속 방식, 속도는 1Gbps)</p>
</br>

<h3 id="카타리스트-스위치-구성">카타리스트 스위치 구성</h3>
<hr>
<p><strong>디폴트 구성</strong></p>
<ul>
<li>show interface status: 스위치에서 각 포트들의 현재 상황을 볼 수 있는 명령</li>
<li>각 포트들의 상태는 아직 연결되어 있지 않음</li>
<li>모두 Vlan 1번으로 구성</li>
<li>Duplex는 Auto(상대방의 상태에 맞추겠다(Full Duplex와 Half Duflex 중))</li>
<li>Speed는 Auto(상대방에 맞추겠다(10Mbps와 100Mbps 중))</li>
<li>IP 주소나 패스워드는 세팅을 하지 않았으니 없음</li>
<li>스패닝 트리 프로토콜은 자동으로 활성화되어 있어, 루핑 방지 중</li>
</ul>
</br>

<p><strong>IP 주소 세팅(선택 사항. 권장 사항)</strong></p>
<ul>
<li>IP 주소 세팅은 스위치를 제대로 관리하기 위해 필요(스위치 구성을 확인하거나 변경하고자 할 때 텔넷을 이용한 접속이 가능+NMS 같은 장비에서 스위치 관리하는데도 필요)</li>
<li>스위치 자체에 하나의 IP 주소만을 부여</li>
<li><code>enable</code> 명령을 통해 <code>privileged</code> 모드로 접속</li>
<li><code>configure terminal</code> 명령으로 구성 모드로 접속</li>
<li><code>vlan 1</code> 인터페이스에서 IP 주소 세팅<ul>
<li><code>interface vlan 1</code></li>
<li><code>ip address 192.168.100.1 255.255.255.0</code></li>
</ul>
</li>
<li><code>privileged</code> 모드에서 <code>show interface vlan 1</code> 명령으로 세팅 확인</li>
<li>디폴트 게이트웨이 구성<ul>
<li><code>configure terminal</code></li>
<li><code>ip default-gateway 192.168.1.1</code></li>
<li>vlan 인터페이스가 아닌 일반 구성 모드에서 하면 됨</li>
</ul>
</li>
</ul>
</br>

<p><strong>스위치 포트 속도와 Duplex 세팅</strong></p>
<ul>
<li><p><code>configure terminal</code> 명령으로 <code>privileged</code> 모드로 들어감</p>
</li>
<li><p><code>interface fastethernet 0/1</code> 명령으로 변경해주고자 하는 인터페이스로 들어감</p>
</li>
<li><p><code>speed 10</code> 명령으로 스위치 포트 속도를 10mbps로 세팅</p>
</li>
<li><p><code>duplex half</code> 명령으로 duplex를 half duplex로 세팅</p>
</li>
<li><p><code>show interface fastethernet 0/1</code> 명령으로 세팅 확인</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Memory Management]]></title>
            <link>https://velog.io/@alwayslee_12/Memory-Management</link>
            <guid>https://velog.io/@alwayslee_12/Memory-Management</guid>
            <pubDate>Tue, 16 Nov 2021 05:52:36 GMT</pubDate>
            <description><![CDATA[<h3 id="logical-vs-physical-address">Logical vs Physical Address</h3>
<hr>
<ul>
<li><strong>Logical Address(Virtual Address)</strong><ul>
<li>프로세스마다 독립적으로 가지는 주소 공간</li>
<li>각 프로세스마다 0번지부터 시작</li>
<li><strong>CPU가 보는 주소는 logical address</strong></li>
</ul>
</li>
<li><strong>Physical Address</strong><ul>
<li>메모리에 실제 올라가는 위치</li>
</ul>
</li>
<li><strong>주소 바인딩</strong><ul>
<li>주소를 결정하는 것</li>
<li>Symbolic Address(숫자가 아닌 프로그래머 입장에서의 address) -&gt; Logical Address -&gt; Physical Address</li>
<li>실행을 위해서는 물리적인 메모리 공간에 로드되어야 하기때문에, 주소 변환이 필요함</li>
</ul>
</li>
</ul>
</br>

<h3 id="주소-바인딩">주소 바인딩</h3>
<hr>
<ul>
<li><p><strong>Compile Time binding</strong></p>
<ul>
<li>물리적 메모리 주소가 컴파일 시 알려짐</li>
<li>무조건 0번지부터 물리적 메모리 주소가 매겨짐(비효율적)</li>
<li>시작 위치 변경 시 재컴파일(메모리 주소 변경 원할 시, 재컴파일 해야함)</li>
<li>컴파일러는 절대 코드(컴파일 타임에 만들어진 코드) 생성</li>
</ul>
</li>
<li><p><strong>Load Time Binding</strong></p>
<ul>
<li><p>프로그램이 시작하고 메모리에 로드될 때, 물리적 메모리 주소 결정(컴파일 타임까지는 논리적 메모리 주소만 결정)</p>
</li>
<li><p>비어있는 메모리 주소부터 매겨짐</p>
</li>
<li><p>Loader의 책임하에 물리적 메모리 주소 부여</p>
</li>
<li><p>컴파일러가 재배치가능코드를 생성한 경우 가능(재실행 후 비어있는 메모리 주소에 재배치 가능)</p>
</li>
</ul>
</li>
<li><p><strong>Execution Time Binding(=Run Time Binding)</strong></p>
<ul>
<li>프로그램이 시작할 때 , 물리적 메모리 주소 결정</li>
<li>수행이 시작된 후에도 프로세스의 메모리 주소를 바꿀 수 있음(현대 컴퓨터)</li>
<li>CPU가 주소를 참조할 때마다 binding을 점검(address mapping table)</li>
<li>하드웨어적 지원 필요(like MMU)</li>
</ul>
</li>
</ul>
</br>

<h3 id="mmumemory-management-unit">MMU(Memory-Management Unit)</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/b1ea5706-700e-4291-83d0-1b49f3377ecf/1.PNG" alt=""></p>
<ul>
<li><p>logical address를 physical address로 매핑해주는 하드웨어 장치</p>
</li>
<li><p>내부의 relocation register(=Base Register)와 limit register를 이용해 주소변환을 함</p>
<ul>
<li><p><strong>Base Register:</strong> 들어온 논리적 메모리 주소에 실제 프로세스가 메모리에 로드된 주소 값을 더함</p>
</li>
<li><p><strong>limit register:</strong> 프로그램의 크기를 담고 있음(논리적 주소의 범위. 위 예의 경우 3000. base register 계산 이전에 검사)</p>
<p>악의적인 프로그램에 대비하기 위함. </p>
<p>예를 들어 프로그램이 3000크기의 프로그램인데 메모리 4000에 있는 값을 달라고 한다? </p>
<p>악의적인 프로그램 </p>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="몇가지-용어들">몇가지 용어들</h3>
<hr>
<ul>
<li><p><strong>Dynamic Loading</strong></p>
<ul>
<li>프로그램을 메모리에 동적으로 올림(프로그램 전체를 메모리에 통째로 올려놓는 것이 아니라 해당 루틴이 불려질 때마다 메모리에 로드하는 것)</li>
<li>운영체제의 특별한 지원 없이 프로그램 자체에서 구현 가능(OS의 <strong>라이브러리를 통해</strong> 프로그래머에게 지원 가능)</li>
</ul>
</li>
<li><p><strong>Overlays</strong></p>
<ul>
<li>메모리에 프로세스의 부분 중 실제 필요한 정보만을 올림</li>
<li>용량이 작은 메모리를 사용하던 초창기 시스템에서 수작업으로 <strong>프로그래머가 구현</strong>(구현 복잡)</li>
</ul>
</li>
<li><p><strong>Swapping</strong></p>
<ul>
<li>프로세스를 일시적으로 메모리에서 backing store(=swap area)로 쫓아내는 것(swap out)</li>
<li>backing store에서 다시 메모리로 로드(swap in)</li>
</ul>
</li>
<li><p><strong>Dynamic Linking</strong></p>
<ul>
<li><p><strong>Linking:</strong> 여러 곳에 존재하는 컴파일된 파일들을 묶어 하나의 실행파일을 만드는 과정</p>
<ul>
<li><p><strong>Static Linking:</strong> 라이브러리가 프로그램의 실행 파일 코드에 포함됨. </p>
<p>동일한 라이브러리를 각각의 프로세스가 메모리에 올리므로 메모리 낭비</p>
</li>
<li><p><strong>Dynamic Linking:</strong> 라이브러리가 실행 시 연결됨. </p>
<p>라이브러리가 이미 메모리에 있으면, 그 루틴이 주소로 가고 없으면 디스크에서 읽어옴</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="allocation-of-physical-memory">Allocation Of Physical Memory</h3>
<hr>
<ul>
<li><p>메모리는 일반적으로 OS 상주 영역(interrupt vector와 함께 낮은 주소 영역 사용)과 사용자 프로그램 영역(높은 주소 영역 사용)으로 나뉨</p>
</li>
<li><p>사용자 프로그램 영역 할당 방법</p>
<ul>
<li><p><strong>Contiguous Allocation(연속적 할당 방법. 프로그램 통째로 올림. 주소변환 간단)</strong></p>
<ul>
<li><p>각각의 프로그램이 통째로 메모리에 올라감</p>
<ul>
<li><p><strong>Fixed Partition Allocation</strong></p>
<ul>
<li><p>프로그램이 들어갈 영역을 미리 나눠놓음</p>
</li>
<li><p>외부 조각(프로그램의 크기보다 작은 영역이 남음), 내부 조각(프로그램의 크기보다 큰 영역에서 남은 영역)</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/b948b93f-b004-4d09-944d-a276977e7207/2.PNG" alt=""></p>
</li>
</ul>
</li>
<li><p><strong>Variable Partition Allocation</strong></p>
<ul>
<li><p>프로그램이 들어갈 영역을 미리 나눠놓지 않음(B가 수행을 끝내고 나가서 빈 자리가 남음. Hole 발생)</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/9447ab76-2686-4961-b1d0-e416fab82b89/3.PNG" alt=""></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/c4d4d57f-994a-4b2e-8498-b89f87d4b584/4.PNG" alt=""></p>
</li>
<li><p>어느 hole에 후속 프로그램을 넣을까에 대한 문제</p>
<ul>
<li><strong>First-fit:</strong> 가장 최초로 맞는 hole에 할당</li>
<li><strong>Best-fit:</strong> 가장 잘 맞는 hole에 할당</li>
<li><strong>Worst-fit</strong>: 제일 큰 hole에 할당(상대적으로 속도와 공간 이용률 측면에서 뒤쳐짐)</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Compaction</strong></p>
<ul>
<li><p>외부 조각 문제를 해결하는 한 가지 방법</p>
</li>
<li><p>사용 중인 메모리 영역을 한군데로 몰고 hole들을 다른 곳으로 몰아 큰 block을 만듦</p>
</li>
<li><p>매우 비용이 많이 듦</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Noncontiguous Allocation</strong></p>
<ul>
<li>하나의 프로그램이 메모리의 여러 영역에 분산되어 올라갈 수 있음(주소변환 복잡)</li>
<li><strong>Paging</strong>
  <img src="https://images.velog.io/images/alwayslee_12/post/0d835f16-9c4c-45b9-b2e8-ff7348abea67/image.png" alt=""><ul>
<li>프로세스의 가상 메모리를 동일한 크기의 페이지로 자름</li>
<li>가상 메모리의 내용이 페이지 단위로 불연속적으로 저장됨</li>
<li>일부는 backing storage에 일부는 physical memory에 저장</li>
<li>물리적 메모리를 동일한 크기의 frame으로 나눔</li>
<li>논리적 메모리는 동일 크기의 page로 나눔(frame과 같은 크기)</li>
<li>모든 가용 frame들을 관리</li>
<li>page table(각 프로세스별로 존재)을 사용해 주소 변환<ul>
<li>page table을 main memory에 위치</li>
<li>메모리 접근 연산에는 2번의 memory access 필요(메모리에 접근에서 page table로 가서 실제 메모리에서의 주소를 찾고, 다시 메모리에 접근해서 해당 주소로 가서 데이터 이용)</li>
<li>두 개의 레지스터는 paging 기법에서는 page-table base register와 page-table length register로 사용됨</li>
<li>이렇게 메모리에 두번 접근하는 작업은 시간이 꽤나 걸림
그래서 속도 향상을 위해 associative register나 translation look-aside buffer이라 불리는 고속의 하드웨어 캐시 사용
<img src="https://images.velog.io/images/alwayslee_12/post/09ffed54-c64d-404d-98c4-609edc72d5af/image.png" alt="">
TLB(프로세스마다 존재. 문맥교환이 일어날 때 flush 시켜야 함): 주소변환을 위한 캐시메모리(자주 사용하는 page의 물리 주소를 캐싱해놓음)
TLB에서 주소를 매핑하기 위해서는 원래는 순차적으로 탐색해야 함(시간 많이 걸림)
associative register를 이용해 병렬 탐색이 가능하게 함으로써 이를 해소
TLB Hit(캐싱되어 있음)면 주소변환
TLB Miss(TLB에 없으면) page table에서 찾음(인덱스로 접근해서)</li>
<li>valid, invalid bit: 사용하는 주소공간은 page table에 v(valid)로 표시하고 사용하지 않는 주소공간 or swap area에 있는 경우 page table에 i(invalid)로 표시</li>
<li>protection bit: page에 대한 접근 권한(code page는 read-only, data나 stack page는 read/write 권한)</li>
</ul>
</li>
<li>2단계 page table
<img src="https://images.velog.io/images/alwayslee_12/post/23fd871c-99d3-40c7-8029-eadb38f51e77/image.png" alt=""><ul>
<li>현대의 컴퓨터는 메모리 주소체계의 크기가 큼(32bit, 64bit. 표현 가능한 byte 주소는 각각 2^32, 2^64. 메모리 주소가 0~2^32-1 주소를 매길 수 있음)
<img src="https://images.velog.io/images/alwayslee_12/post/b29c4d6d-666f-4d54-af7d-d6ba295d9df8/image.png" alt="">
p1은 outer page table에서의 번호(inner page table을 가리키는 포인터)
p2는 inner page table에서의 번호
offset은 메모리 내에서의 page 위치</li>
<li>페이지 테이블을 위한 공간을 절약하기 위해 사용
사용되지 않은 메모리 영역에 대한 inner page table entry를 만들지 않음</li>
</ul>
</li>
<li>다단계 page table <ul>
<li>다단계 page table을 사용하면, 페이지 테이블을 위한 공간을 절약할 수는 있지만, 메모리에 접근하는데 드는 시간때문에 오버헤드가 크게됨(주소변환시간 오래걸림)</li>
<li>TLB를 이용해서 이를 해소. 대부분의 주소변환은 TLB를 통해 이루어짐(결과적으로 주소변환 시간이 그렇게 오래걸리지는 않음)</li>
</ul>
</li>
<li>Inverted page table<br><img src="https://images.velog.io/images/alwayslee_12/post/479c24f0-6287-4739-8c79-cae608a33ce1/image.png" alt=""><ul>
<li>시스템 안에 page table 하나 존재</li>
<li>page table의 entry가 물리적 메모리 page frame 개수만큼 존재</li>
<li>논리적인 메모리 주소뿐만 아니라 프로세스의 id로 같이 page table에 저장해야 함</li>
<li>page table을 위한 공간을 줄이기 위해 사용(단, 시간적인 오버헤드 존재. page table을 전체 탐색 해야하기 때문) -&gt; assiciative register 사용해서 병렬적으로 entry 탐색하게 함으로써 해결</li>
</ul>
</li>
<li>shared pages           <ul>
<li>공유하는 페이지에 대해서는 각각을 물리적인 메모리에 로드하는 것이 아닌, 하나만 올림(공유하는 code page는 하나만 메모리에 로드함. 해당 page는 반드시 read-only and 동일한 논리적 메모리 위치를 가져야 함)</li>
</ul>
</li>
<li>외부조각 발생 안함, 내부조각 발생 가능    </li>
</ul>
</li>
<li><strong>Segmentation</strong>
  <img src="https://images.velog.io/images/alwayslee_12/post/099d0bdd-9984-4218-8668-df02ae80c648/image.png" alt=""><ul>
<li>프로세스를 구성하는 주소공간을 의미단위로 쪼갬(code, data, stack과 같은)</li>
<li>또는 code 중에서도 함수별로 쪼갬</li>
<li>logical address는 [segment-number, offset]으로 구성</li>
<li>세그먼트별로 주소변환을 하기에 segment table이 존재          <ul>
<li>세그먼트의 길이가 균일하지 않을 수 있음(의미 단위로 쪼개기때문. segment table에서의 limit)</li>
<li>세그먼트 번호(s)가 잘못되었을 때, segmant 개수보다 크면, trap 발생</li>
<li>offset(d)가 limit보다 크면, trap 발생</li>
<li>정상적인 요구면 주소변환(segment의 시작위치(base)에 offset(d)을 더함)</li>
<li>segment 크기가 각각 다르기때문에 정확한 byte 단위의 크기로 base를 알려주어야 함</li>
</ul>
</li>
<li>두 개의 레지스터는 segment table의 시작위치(STBR), segment table의 길이(STLR)로 사용됨</li>
<li>의미 단위로 쪼개는 것이기 때문에 공유(process간 sharing)와 보안에 있어 paging보다 훨씬 효과적</li>
<li>메모리 크기가 균일하지 않기때문에 외부 단편화가 발생(first fit, best fit 사용)</li>
</ul>
</li>
<li><strong>Paged Segmentation</strong>
  <img src="https://images.velog.io/images/alwayslee_12/post/0242d4bd-1262-45fd-8575-2dc4cf1ab68b/image.png" alt=""><ul>
<li>세그먼트 하나가 여러개의 페이지로 구성됨</li>
<li>메모리에 로드될 때는 페이지 단위로 쪼개져서 로드됨(외부 단편화 문제 발생하지 않음)</li>
<li>의미 단위로 해야하는 공유나 보안같은 업무는 segment table level에서 수행</li>
<li>주소변환 두 단계<ul>
<li>segment 주소변환(페이지 테이블의 시작위치 도출. 세그먼트 하나당 여러개의 페이지로 구성되기에 세그먼트당 페이지 테이블 존재)<ul>
<li>page 주소변환을 통해 물리적인 주소를 도출</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h1 id="참고">참고</h1>
<p><a href="https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f">https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Deadlock(교착 상태)]]></title>
            <link>https://velog.io/@alwayslee_12/Deadlock%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C</link>
            <guid>https://velog.io/@alwayslee_12/Deadlock%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C</guid>
            <pubDate>Thu, 11 Nov 2021 07:09:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/alwayslee_12/post/a9b60312-3e2f-4d66-9054-f659ee78be6f/1.PNG" alt="">
위 그림대로 차들이 무조건 진행방향으로만 나아가려고 한다면 진전이 없이 계속 막히게 될 것이다 이러한 상황을 Deadlock이라 한다.</p>
</br>

<p><strong>Deadlock</strong></p>
<p>일련의 프로세스들이 서로가 가진 자원(하드웨어, 소프트웨어 등을 포함하는 개념)을 기다리면 block된 상태</p>
<p>ex) </p>
<ol>
<li>시스템에 2개의 tape drive가 있고, 프로세스1,2가 각각 하나의 tape drive를 보유한 채 다른 하나를 기다리고 있음(하드웨어 자원)</li>
<li>프로세스 1이 세마포어 A를 획득하고, 프로세스 2가 세마포어 B를 획득한 상태에서 서로의 세마포어를 요구하는 상태(소프트웨어 자원)</li>
</ol>
</br>

<h3 id="deadlock-발생-4가지-조건">Deadlock 발생 4가지 조건</h3>
<hr>
<ul>
<li><strong>Mutual Exclusion(상호 배제):</strong> 매 순간 하나의 프로세스만이 자원을 사용할 수 있음</li>
<li><strong>No Preemption(비선점):</strong> 프로세스는 자원을 스스로 내어놓긴 해도 강제로 뺏기지는 않음</li>
<li><strong>Hold And Wait(보유대기):</strong> 자원을 가진 프로세스가 다른 자원을 기다릴 때 보유 자원을 놓지 않고 계속 가지고 있음</li>
<li><strong>Circular Wait(순환대기):</strong> 자원을 기다리는 프로세스간에 사이클이 형성<ul>
<li>프로세스 1이 프로세스 2가 가진 자원을 기다림</li>
<li>프로세스 2가 프로세스 3이 가진 자원을 기다림</li>
<li>프로세스 3이 프로세스 1이 가진 자원을 기다림</li>
</ul>
</li>
</ul>
<p>=&gt; 위 4가지 조건을 모두 만족해야 Deadlock이 발생</p>
</br>

<h3 id="자원할당-그래프">자원할당 그래프</h3>
<hr>
<p>Deadlock이 발생했는지를 자원할당그래프를 통해서 알 수 있음</p>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/b494576b-b800-4711-97c5-c58f926a8218/2.PNG" alt=""></p>
<ul>
<li><p>동그라미: 프로세스</p>
</li>
<li><p>사각형: 자원</p>
</li>
<li><p>동그라미로 들어오는 화살표: 프로세스가 해당 자원을 소유하고 있음</p>
</li>
<li><p>사각형으로 들어오는 화살표: 프로세스가 해당 자원을 요청(기다림)</p>
</li>
<li><p>사각형 안에 점들: 자원의 개수</p>
</li>
<li><p>위 그림을 Deadlock일까?</p>
<ul>
<li>그래프에 cycle이 없으면 Deadlock이 아님</li>
<li>cycle이 있으면<ul>
<li>자원당 점이 하나씩밖에 없으면 Deadlock</li>
<li>자원당 점이 여러개 있으면 Deadlock일수도 아닐수도 있음(여러개 점을 모든 프로세스가 소유하고 있고, 그 프로세스들끼리 cycle이 형성되어 있으면 Deadlock)</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="deadlock-처리-방법">Deadlock 처리 방법</h3>
<hr>
<ul>
<li><strong>Deadlock Prevention(예방)</strong><ul>
<li>자원 할당 시 Deadlock의 4가지 필요 조건 중 어느 하나가 만족되지 않도록 하는것</li>
</ul>
</li>
<li><strong>Deadlock Avoidance(예방)</strong><ul>
<li>자원 요청에 대한 부가적인 정보를 이용해 deadlock의 가능성이 없는 경우에만 자원 할당</li>
<li>시스템 state가 원래 state로 돌아올 수 있는 경우에만 자원 할당</li>
</ul>
</li>
<li><strong>Deadlock Detection and recovery(데드락 발생하게 하고, 탐지 후 회복)</strong><ul>
<li>Deadlock 발생은 허용, 그에 대한 탐지 루틴을 두고 발견 시 회복</li>
</ul>
</li>
<li><strong>Deadlock Ignorance(데드락 발생하게 하고, 무시)</strong><ul>
<li>Deadlock을 시스템이 책임지지 않음</li>
<li>UNIX를 포함한 대부분의 OS가 채택</li>
<li>사용자가 프로세스를 kill(만약 Deadlock이 발생하게 되면)</li>
</ul>
</li>
</ul>
</br>

<h3 id="deadlock-prevention">Deadlock Prevention</h3>
<hr>
<ul>
<li><strong>Mutual Exclusion:</strong> 사실상 배제할 수 있는 조건이 아님</li>
<li><strong>Hold and Wait</strong><ul>
<li>프로세스 시작 시 모든 필요한 자원을 할당받게 하는 방법(wait 할 일이 없음. 자원의 비효율성 초래)</li>
<li>자원이 필요할 경우 보유 자원을 모두 놓고 다시 요청(hold를 못하게)</li>
</ul>
</li>
<li><strong>No Preemption</strong><ul>
<li>자원을 선점할 수 있게함</li>
<li>state를 쉽게 save하고 restore 할 수 있는 CPU나 Memory 자원에서 주로 사용</li>
</ul>
</li>
<li><strong>Circular Wait</strong><ul>
<li>모든 자원 유형에 할당 순서를 정해 정해진 순서대로만 자원 할당</li>
</ul>
</li>
</ul>
<p>=&gt; 자원에 대한 이용율이 낮아지고, 시스템 성능 저하, starvation 문제 발생</p>
<p>=&gt; 잘 생기지도 않을 데드락을 고려해 제약조건을 많이 달아놓기에 굉장히 비효율적인 방법</p>
</br>

<h3 id="deadlock-avoidance">Deadlock Avoidance</h3>
<hr>
<ul>
<li><p>프로세스의 시작 단계에서 프로세스가 쓸 자원의 최대량을 알고 있다고 가정하고, 프로세스에게 자원을 할당할 때 Deadlock이 발생할거 같으면 할당 안함</p>
</li>
<li><p><strong>자원의 인스턴스가 하나밖에 없는 상황</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/4a733022-5048-4311-9df8-36adf8bf0d1e/3.PNG" alt=""></p>
<p>점선: 프로세스가 적어도 한번 해당 자원을 요청할 수 있는 가능성</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/67e12c2f-6eef-4d77-b3b0-921bb44b9d82/4.PNG" alt=""></p>
<p>프로세스 2가 자원을 실제로 요청(점선 -&gt; 실선)</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/ea38f1e7-5011-479e-8a08-71aab051f0e7/5.PNG" alt=""></p>
<p>점선을 포함하면, 사이클이 형성됨(이런 경우에는 프로세스 2에게 자원을 할당하지 않음)</p>
<p>만약 1번 프로세스가 자원을 요청해서 얻었다면, 사이클은 형성되지 않음(이런 경우에는 할당)</p>
</li>
<li><p><strong>자원의 인스턴스가 여러개 있는 경우(Banker&#39;s Algorithm을 이용)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/81ee802e-a52d-4874-bb6f-e6ce346e09ea/image.png" alt=""></p>
<ul>
<li>Allocation: 각 프로세스가 가지고 있는 자원 및 개수</li>
<li>Max: 각 프로세스마다 각 자원을 평생의 생명주기동안 사용할 수 있는 최대 수</li>
<li>Available: 가용자원</li>
<li>Need: Max-Allocation</li>
<li>Available로 충족할 수 있는 Need들만 받아들임(나머지는 자원을 할당해주지 않음)</li>
</ul>
</li>
</ul>
<p>=&gt; 비효율적임(자원이 남아돌게 됨). unsafe로 판단됐다고 해서 무조건 Deadlock은 아님</p>
</br>

<h3 id="deadlock-detection-and-recovery">Deadlock Detection and Recovery</h3>
<hr>
<ul>
<li><p><strong>Deadlock 탐지</strong></p>
<ul>
<li><p>자원당 인스턴스가 1개인 경우</p>
<ul>
<li>자원할당 그래프에서의 cycle이 deadlock</li>
</ul>
</li>
<li><p>자원당 인스턴스가 여러개인 경우</p>
<ul>
<li>Banker&#39;s algorithm과 유사한 방법</li>
</ul>
<p><img src="https://images.velog.io/images/alwayslee_12/post/c4fa00ba-a29e-48f7-be6d-a1f1eb16331b/image.png" alt=""></p>
<p>​        <strong>Allocation:</strong> 프로세스 당 소유한 자원들</p>
<p>​        <strong>Request:</strong> 프로세스가 각 자원들 요청 한 수(요청한 자원이 없으면, 반납한다고 가정)</p>
<p>​        <strong>Available:</strong> 가용자원</p>
<p>​        위 그림은 Deadlock이 없음</p>
</li>
</ul>
</li>
<li><p><strong>Dealock Recovery</strong></p>
<ul>
<li><p>Deadlock에 연루된 프로세스들 Kill</p>
<ul>
<li><p>모든 프로세스들 한꺼번에 kill</p>
</li>
<li><p>Deadlock에 연루된 프로세스를 하나씩 kill(Deadlock이 없어질때까지)</p>
</li>
</ul>
</li>
<li><p>Deadlock에 연루된 프로세스들의 자원을 뺏는 것(자원을 뺏을 victim 프로세스 선정하고, 자원을 뺏어 Deadlock을 없앰 -&gt; safe state로 rollback 후 프로세스 restart)</p>
<p>=&gt; victime 프로세스 선정 방법을 매번 달리해야 하고, rollback 횟수도 고려</p>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="deadlock-ignorance">Deadlock Ignorance</h3>
<hr>
<ul>
<li>Deadlock이 일어나지 않는다고 생각하고 아무런 조치도 취하지 않음</li>
<li>Deadlock은 매우 드물게 발생하므로 deadlock에 대한 조치자체가 큰 overhead일 수 있음</li>
<li>deadlock이 발생한 경우 시스템이 비정상적으로 작동하는 것을 느낀 사람이 직접 프로세스 kill</li>
<li>UNIX, WIndows 등 대부분의 범용 OS가 채택</li>
</ul>
<h1 id="참고">참고</h1>
<p><a href="https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f">https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[IP 주소]]></title>
            <link>https://velog.io/@alwayslee_12/IP-%EC%A3%BC%EC%86%8C</link>
            <guid>https://velog.io/@alwayslee_12/IP-%EC%A3%BC%EC%86%8C</guid>
            <pubDate>Wed, 10 Nov 2021 14:08:33 GMT</pubDate>
            <description><![CDATA[<p>TCP/IP 프로토콜을 만들 때 이 프로토콜을 사용하는 모든 장비들을 구분하기 위해 만들어진 것</p>
<blockquote>
<p>허브나 스위치에도 관리르 위해 IP 주소가 부여되지만, 배정하지 않아도 통신에는 지장이 없음 </p>
</blockquote>
<p>IP 주소는 이진수 32자리로 되어있음.(8자리마다 점을 찍음. 8개를 묶어 옥텟이라 부름) 2^32개의 IP 주소를 만들 수 있음</p>
<p>사람이 보기 편하게 2진수 8자리마다 10진수를 만들어서 표현</p>
</br>

<p><strong>네트워크 부분과 호스트 부분(노드 부분)</strong></p>
<p>네트워크: 하나의 브로드캐스트 영역. 라우터를 거치지 않고도 통신이 가능한 영역</p>
<p>호스트: 각각의 PC 또는 장비</p>
<p>만약 내부 네트워크가 203.240.100.1~240.100.255까지의 IP 주소를 배정 받았다면, <strong>203.240.100까지가 네트워크 부분</strong>이고 <strong>그 다음이 호스트 부분</strong>이다.</p>
<p>같은 네트워크에 속한다면 IP 주소의 네트워크 부분이 일치해야하고, 호스트 부분이 달라야 한다.</p>
</br>

<h3 id="ip-주소의-class">IP 주소의 Class</h3>
<hr>
<p>IP 주소의 Class는 네트워크의 크기에 따라 A부터 E까지 구분된다.(하나의 네트워크가 호스트 수를 몇 개까지 가질 수 있는가에 따라)</p>
<ul>
<li><p>Class A: IP 주소 중 앞에 8비트가 네트워크 부분이고, 나머지 24비트가(3개의 옥텟) 호스트 부분. </p>
<p>32개의 이진수 중 맨 앞 하나는 0이 무조건 나오고 나머지는 아무거나(0xxx xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx -&gt; 1.0.0.0~126.0.0.0(0.0.0.0과 127.0.0.0은 뺌)까지가 네트워크 부분)</p>
<p>1~126으로 시작하는 네트워크는 클래스 A</p>
<p>호스트 개수는 2^24-2(네트워크 자신과 브로드캐스트 주소 제외)</p>
</li>
<li><p>Class B: IP 주소 중 앞에 16비트가 네트워크 부분이고, 나머지 16비트가(2옥텟) 호스트 부분.</p>
<p>32개의 이진수 중 맨 앞이 반드시 10으로 시작하고 나머지는 아무거나(10xx xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx -&gt; 128.0.0.0~191.255.0.0까지가 네트워크 부분)</p>
<p>128~191로 시작하는 네트워크는 클래스 B</p>
<p>호스트 개수는 2^16-2</p>
</li>
<li><p>Class C: IP 주소 중 맨 앞에 24가 네트워크 부분이고, 나머지 8비트가 호스트 부분.</p>
<p>32개의 이진수 중 맨 앞이 반드시 110으로 시작하고 나머지는 아무거나(110x xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx -&gt; 192.0.0.0~223.255.255.0까지가 네트워크 부분)</p>
<p>192~223로 시작하는 네트워크는 클래스 C</p>
<p>호스트 개수는 2^8-2</p>
</li>
<li><p>Class D: 멀티캐스트 용으로 사용되는 주소. 224~239</p>
</li>
<li><p>Class E: 연구용으로 사용되는 주소. 240~255</p>
</li>
</ul>
</br>

<h3 id="라우터에서-ip-주소-이해">라우터에서 IP 주소 이해</h3>
<hr>
<p>많이 사용하는 라우터인 시스코 2501을 예로 들어보자</p>
<p>시스코 2501은 이더넷 인터페이스와 인터넷에 접속하기 위한 시리얼 인터페이스 2개로 구성되어있다.</p>
<p>IP 주소는 이더넷 인터페이스(기본 게이트워이: 내부 네트워크에서 밖으로 나갈 수 있는 문)에 하나 시리얼 인터페이스에 하나 총 두개 부여해야 한다.</p>
<p>이더넷 인터페이스에는 내부 네트워크에서 사용하기 위해 부여받은 IP 주소 중 하나를 배정해야 한다.</p>
<p>예를 들어, 203.120.150.1~203.120.150.255까지의 IP 주소를 내부 네트워크가 배정 받았다면, 보통 맨 앞에 번호를 쓰기 때문에 203.120.150.1이 이더넷 인터페이스의 IP 주소가 된다.</p>
<blockquote>
<p>하나의 장비에 무조건 하나의 IP 주소만 배정되므로, IP 주소가 같은 장비가 있어서는 안된다!</p>
</blockquote>
<p>시리얼 인터페이스의 IP 주소는 접속하는 ISP 업체에 따라 다르므로 인터넷 제공업체에 문의해서 배정받아야 한다.</p>
</br>

<h3 id="서브넷-마스크">서브넷 마스크</h3>
<hr>
<p>서브넷 마스크는 말 그대로 메인이 아닌 어떤 가공을 통한 네트워크를 만들기 위해 씌우는 마스크</p>
<p>IP 주소를 배정받게 되면 보통은 이 주소를 그대로 사용하지 않고, 자신의 네트워크의 환경에 맞게 나눔</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/b2b8c6e0-1268-4dcd-bde3-0071ae1187a4/1.JPG" alt=""></p>
<p>만약 클래스 B의 주소를 배정 받았다면, 이것을 그대로 사용할 경우에는 65,000여 개의 호스트를 가지는데 이렇게 큰 네트워크를 구성하게 되면, 브로드캐스트의 영향이 너무 커 브로드캐스트가 너무 많이 발생 해 정상적인 통신이 어려울 것이다.</p>
<p>이 문제를 해결하기 위해 서브네팅이 필요하다.</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/daf7f391-7f71-4500-80c3-a9092f048aad/2.JPG" alt=""></p>
<p>서브넷 마스크를 하게 되면 위 그림과 같은 구성이 가능하다.(<strong>브로드캐스트 도메인을 작게 나눔</strong>)</p>
<p>디폴트 서브넷 마스크 255.255.0.0 -&gt; 255.255.255.0으로 바뀜</p>
<p>각 서브넷 간 통신은 라우터를 통해서만 가능하다.</p>
</br>

<h3 id="default-subnet-mask">Default Subnet Mask</h3>
<hr>
<p>배정받은 IP 주소를 나누지 않아도 서브넷 마스크는 존재한다.</p>
<p>예를 들어, 210.100.100.1(C 클래스)이란 주소가 있고, 254개의 호스트에 IP 주소를 부여했다고 했을 때, 이는 주어진 클래스를 나누지 않고 그대로 사용한 것이다.</p>
<p>서브넷 마스크를 가지지 않은 네트워크는 없는 것이다.(모든 네트워크에 디폴트 서브넷 마스크가 존재하기 때문에)</p>
<p>이렇게 주어진 클래스를 나누어 쓰지 않고 모두 쓰는 경우의 서브넷 마스크를 디폴트 서브넷 마스크라 한다. 이 경우는 디폴트 서브넷 마스크가 255.255.255.0이다.</p>
</br>

<p>정리하면,</p>
<p>210.100.100.1 -&gt; IP 주소</p>
<p>255.255.255.0 -&gt; 서브넷 마스크</p>
<p>210.100.100.0 -&gt; 서브넷 네트워크(IP 주소와 서브넷 마스크를 이진수로 바꾸고 AND 연산)</p>
<p>가 되는 것이다.</p>
</br>

<h3 id="서브넷-마스크의-기본-성질">서브넷 마스크의 기본 성질</h3>
<hr>
<ol>
<li>서브넷 마스크로 만들어진 네트워크 즉, 서브넷은 하나의 네트워크이기 때문에 서로 나뉜 서브넷끼리는 라우터를 통해서만 통신 가능</li>
<li>서브넷 마스크는 이진수로 썼을 때, 1이 연속적으로 나와야 함(1과 1 사이에 0이 오면 안됨)</li>
</ol>
</br>

<h3 id="서브넷-만들어보기">서브넷 만들어보기</h3>
<hr>
<p>210.100.1.0 IP 주소를 받았고, PC가 30대인 네트워크를 최소 4개 이상 만든 후 이들을 라우터를 이용해 서로 통신하게할 떄, 서브넷 마스크는?</p>
<p>답) 클래스 C에 해당하며, 디폴트 서브넷 마스크는 255.255.255.0이다. (210.100.1.0)</p>
<p>210.100.1.0이 네트워크 주소이며, 호스트가 30대라 했으니, 호스트 부분이 최소 5비트는 되어야 한다.(나머지 부분은 1)</p>
<p>이렇게 되면, <strong>서브넷 마스크는 210.100.1.224</strong>가 된다.</p>
</br>

<p>서브넷들은 다음과 같다.</p>
<p>210.100.1.1~30(원래 사용하지 않았지만 요새 사용하는 추세)</p>
<p>210.100.1.33~62</p>
<p>210.100.1.65~94</p>
<p>210.100.1.97~126</p>
<p>210.100.1.129~158</p>
<p>210.100.1.161~190</p>
<p>210.100.1.193~222</p>
<p>210.100.1.225~254(원래 사용하지 않았지만 요새 사용하는 추세)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Process Synchronization]]></title>
            <link>https://velog.io/@alwayslee_12/Process-Synchronization</link>
            <guid>https://velog.io/@alwayslee_12/Process-Synchronization</guid>
            <pubDate>Mon, 08 Nov 2021 05:42:18 GMT</pubDate>
            <description><![CDATA[<p>공유 데이터의 동시 접근은 데이터 불일치 문제를 발생시킴</p>
<p>데이터의 일관성을 유지하기 위해 협력 프로세스 간 실행 순서를 정해주는 메커니즘 필요</p>
<p><strong>Race Condition</strong></p>
<ul>
<li>여러 프로세스들이 동시에 공유 데이터를 접근하는 상황</li>
<li>데이터의 최종 연산 결과는 마지막에 그 데이터를 다룬 프로세스에 따라 달라짐</li>
<li>이를 막기 위해 동시에 실행하는 프로세스 간 동기화가 잘 되어야 함</li>
</ul>
</br>

<h3 id="데이터의-접근">데이터의 접근</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/330756ba-158b-47ce-b68c-2043fe0627b1/4.PNG" alt=""></p>
<p>데이터를 읽어가고 그 데이터에 대한 연산을 수행하고, 수행 결과 데이터를 다시 저장하는 과정을 거친다.</p>
<p>이 과정에서 같은 데이터를 읽어서 연산을 수행하는 경우가 있는데, 이러한 경우 발생하는 문제를 Synchronization 문제라 한다.</p>
</br>

<h3 id="race-condition">Race Condition</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/b12e808f-1353-4c8b-9769-bceb7987b5ab/5.PNG" alt=""></p>
<p>같은 Storage Box(Memory Address Space)를 여러 Execution Box(CPU Process)가 접근하는 경우 Race Condition(공유 메모리를 사용하는 프로세스들, 커널 내부 데이터를 접근하는 루틴들 간 발생하는 문제) 가능성이 있음</p>
</br>

<h3 id="운영체제에서-race-condition이-발생하는-경우">운영체제에서 Race Condition이 발생하는 경우</h3>
<hr>
<ol>
<li><strong>Kernel 수행 중 인터럽트 발생 시</strong></li>
</ol>
<p><img src="https://images.velog.io/images/alwayslee_12/post/e102aae5-88c5-4b91-a432-fa127aecd707/6.PNG" alt=""></p>
<p>​    커널모드에서 작업을 실행하고 있을 때, 인터럽트가 발생해 인터럽트 처리루틴 수행(커널에서 1. load까지 수행    하고 2. inc 하려하는데 인터럽트가 발생해 처리루틴을 수행하는데, 그 작업에서 <code>count</code>를 감소하는 작업을 수행    하고 다시 커널모드 작업을 재개함. 이때, 작업은 2. inc를 수행하는데 1. load에서 읽을 데이터를 기준으로 수행.     즉, <code>count</code>를 감소하는 작업은 반영이 안된채 <code>count</code>가 원래 값에서 증가만 함) -&gt; 결국, 양쪽 다 커널 코드이므로 kernel address space를 공유함으로써 이러한 문제 해결
</br>
2. <strong>Process가 System Call 하여 Kernel Mode로 수행 중인데 Context Switch가 일어나는 경우</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/0c93ebae-1970-46e8-9181-3048c3f44a2c/7.PNG" alt=""></p>
<p>​    <strong>해결:</strong> 커널 모드에서 CPU가 수행중일때, CPU가 preempt 당하지 않게 하고, 커널 모드에서 사용자 모드로 돌아    갈 때 preempt하도록 함으로써 해결
</br>
3. <strong>Multiprocessor에서 Shared memory 내 Kernel Data</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/bc4ebdb2-13f1-4429-bb96-ec29aa7baf79/8.PNG" alt="">
​    <strong>방법1:</strong> 한번에 하나의 CPU만 커널에 들어갈 수 있게 함</p>
<p>​    <strong>방법2:</strong> 커널 내부에 있는 각 공유 데이터에 접근할 때마다 그 데이터에 대한 lock/unlock을 함</p>
</br>

<h3 id="the-critical-section임계구역-problem">The Critical-Section(임계구역) Problem</h3>
<hr>
<ul>
<li>n 개의 프로세스가 공유 데이터를 동시에 사용하기를 원하는 경우</li>
<li>각 프로세스의 code segment에 공유 데이터를 접근하는 코드인 <strong>critical section</strong>이 존재</li>
<li>Problem<ul>
<li>하나의 프로세스가 <strong>critical section</strong>에 있을 때 다른 모든 프로세스는 <strong>critical section</strong>에 들어갈 수 없어야 함</li>
</ul>
</li>
</ul>
<p><img src="https://images.velog.io/images/alwayslee_12/post/35eb450f-7a2c-4aea-b137-4d08b89aaa57/9.PNG" alt=""></p>
</br>

<h3 id="initial-attempts-to-solve-problem">Initial Attempts to Solve Problem</h3>
<hr>
<p>임계구역 문제를 해결하기 위한 첫 번째 방법</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/784cf09d-5d4a-4e63-8b77-1c5076c5dfa2/1.PNG" alt=""></p>
<p>공유데이터를 접근하는 프로세스의 critical section 전에 entry section을 넣어 lock을 걸고, critical section 후에 lock을 푸는 방식</p>
</br>

<p><strong>프로그램적 해결법의 충족 조건</strong></p>
<ul>
<li><strong>Mutual Exclusion(상호 배제):</strong> 한 프로세스가 critical section 부분을 수행 중이면 다른 프로세스는 접근하지 못한다.</li>
<li><strong>Progress:</strong> critical section에 아무 프로세스도 들어가 있지 않은 상태에서 critical section에 들어가고자 하는 프로세스가 있으면, 들어갈 수 있게 해주어야 한다.</li>
<li><strong>Bounded Waiting(유한 대기):</strong> 프로세스가 critical section에 들어가려 요청한 후부터 요청이 허용될 때까지 다른 프로세스들이 critical section에 들어가는 횟수에 한계가 있어야 함</li>
</ul>
</br>

<p><strong>Algorithm 1</strong></p>
<ul>
<li><p>Synchronization variable: int turn, turn=0(처음에는 프로세스 0번 차례)</p>
</li>
<li><p>Process P0(프로세스 0 입장에서의 코드)</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/alwayslee_12/post/4c801d21-0cfc-41a0-804d-6a3e2a3dc563/2.PNG" alt=""></p>
<ul>
<li>Mutual Exclusion 만족, Progress 불만족(critical section에 반드시 교대로 들어가도록 코딩되어 있음)</li>
</ul>
</br>

<p><strong>Algorithm 2</strong></p>
<ul>
<li><p>Synchronization variable: boolean flag[2], flag[모두]= false</p>
</li>
<li><p>flag가 true이면, critical section에 들어갈 수 있음</p>
</li>
<li><p>Process Pi
  <img src="https://images.velog.io/images/alwayslee_12/post/6f08b616-6a4b-480f-918d-a7cd8ad2104a/image.png" alt=""></p>
</li>
<li><p>Mutual exclusion 만족, Progress 불만족(둘 다 flag가 true로 세팅해놓은 경우 대기만하고 critical section에 들어가지 못함. 아무도 못 들어가는 상황)</p>
</li>
</ul>
</br>

<p><strong>Algorithm 3</strong></p>
<ul>
<li><p>Peterson&#39;s Algorithm</p>
</li>
<li><p>Process Pi</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/468dd2a5-5305-4244-96e7-8eeaed6e4338/4.PNG" alt=""></p>
</li>
<li><p>Mutual Exclusion 만족, Progress 만족, Bounded Waiting 만족</p>
</li>
<li><p>Busy Waiting(=spin lock) 문제(while 문을 돌면서 체킹하기떄문에 계속 CPU와 memory를 쓰면서 wait)</p>
</li>
</ul>
</br>

<p><strong>Busy Waiting 문제 해결</strong></p>
<ul>
<li><p>하드웨어적으로 Test&amp;Modify를 atomic하게 수행할 수 있도록 지원하면 해결</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/b4a9a87f-4d35-4c47-9799-906275415757/5.PNG" alt="">
<img src="https://images.velog.io/images/alwayslee_12/post/be78b2f8-55c9-4280-a26d-e3cfe4b0c9ef/6.PNG" alt=""></p>
</li>
<li><p><strong>Test_and_Set(value):</strong> value의 현재값을 읽고, value의 값을 바꿈(lock이 걸려있는지를 확인하고, lock을 걸고 들어갈 수 있음) </p>
</li>
</ul>
</br>

<h3 id="semaphores">Semaphores</h3>
<hr>
<ul>
<li><p>프로그래머 입장에서 위 방식들은 구현이 너무 복잡. 위 방식들을 추상 자료형으로 제공해 프로그래머가 이를 이용해 코딩하게 하면 훨씬 수월할 것임</p>
</li>
<li><p>Semaphores는 위 방식들을 추상화시킴(<strong>추상 자료형:</strong> Object와 Operation으로 구성. 논리적으로 정의된 자료형)</p>
</li>
<li><p>Semaphore S</p>
<ul>
<li><p>Integer variable</p>
</li>
<li><p>두 가지 atomic 연산에 의해서만 접근 가능</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/f1fc2884-00b9-48c8-a6be-38cd80766ace/1.PNG" alt=""></p>
</li>
<li><p><strong>P(S):</strong> 공유 데이터 획득. lock</p>
</li>
<li><p><strong>V(S):</strong> 공유 데이터 반납. unlock</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/alwayslee_12/post/20b5755a-256e-4c2d-98a7-1930cd11020c/2.PNG" alt=""></p>
<ul>
<li><strong>busy-wait 문제</strong>는 아직 있음(<strong>Block &amp; Wakeup 방식</strong>을 통해 해결 가능)</li>
</ul>
</li>
<li><p>Semaphores의 종류</p>
<ul>
<li><strong>Counting semaphore:</strong> 자원의 개수가 여러 개 있는 경우. resource counting에 사용</li>
<li><strong>Binary semaphore:</strong> 자원의 개수가 1개인 경우(0 또는 1 값만 가질 수 있음). mutual exclusion(lock/unlock)에 사용</li>
</ul>
</li>
</ul>
</br>

<p><strong>Block&amp;Wakeup 방식</strong></p>
<ul>
<li><p>Semaphore를 다음과 같이 정의</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/792e54ef-6422-49f2-b3e9-25a86efe3cad/3.PNG" alt=""></p>
</li>
<li><p>block: 커널은 block을 호출한 프로세스를 suspend 시킴. 이 프로세스의 PCB를 semaphore에 대한 wait queue에 넣음</p>
</li>
<li><p>wake up: block된 프로세스를 wakeup시킴. 이 프로세스의 PCB를 ready queue로 옮김</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/alwayslee_12/post/3608236d-4d5e-435c-936c-040623d43e5c/4.PNG" alt=""></p>
<ul>
<li><p>구현</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/6b3de820-6886-4f78-8d92-2611538b4403/5.PNG" alt="">
  P(S) 연산에서 만약 사용 가능한 자원이 있다면, S.value를 감소시키고, 자원을 사용하고 사용 가능한 자원이 없다면, S.value를 감소시키고, 대기큐에 넣고 blocked 상태가 된다.
  V(S) 연산에서 자원을 반납했는데, S.value가 0 이하라는 소리는 자원을 사용하기 위해 대기큐에서 기다리는 프로세스가 있다는 소리이므로 대기큐에서 프로세스 하나를 지우고 blocked 상태에서 깨운다(wakeup). 자원을 반납하고 S.value가 0 보다 크다면, 자원을 사용하기 위해 대기하는 프로세스가 없다는 소리이므로, 위 작업없이 그냥 넘어간다.</p>
</li>
</ul>
</br>

<p><strong>Busy-wait VS block/wakeup</strong></p>
<ul>
<li>critical section의 길이가 긴 경우 block/wakeup 방식이 적당</li>
<li>critical section의 길이가 매우 짧은 경우 busy-wait 방식이 적당</li>
<li>보통은 block/wakeup 방식이 더 좋음</li>
</ul>
</br>

<h3 id="deadlock-and-starvation">Deadlock and Starvation</h3>
<hr>
<ul>
<li>S와 Q가 1로 초기화된 semaphore라 가정</li>
</ul>
<p><img src="https://images.velog.io/images/alwayslee_12/post/087ed7a8-b5e1-46f2-83ee-6be60ebe0d16/6.PNG" alt=""></p>
<ul>
<li><p><strong>Deadlock:</strong> 자원이 2개가 있는 상황에서 하나의 프로세스가 자원을 하나 획득하고, 또 다른 프로세스가 다른 자원을 획득한 상태에서 각 프로세스가 상대방의 자원을 요구할 때, 내놓을때까지 무한히 기다리는 현상</p>
<p>-&gt; 자원을 획득하는 순서를 똑같이 맞춰주면 됨(자원은 반드시 S먼저, 다음 Q 획득 이런식으로)</p>
</li>
<li><p><strong>Starvation:</strong> 특정 프로세스들끼리만 자원을 공유하고, 다른 프로세스는 자원을 얻을 수 없는 현상</p>
</br>

</li>
</ul>
<h3 id="classical-problem-of-synchronization">Classical Problem of Synchronization</h3>
<hr>
<ul>
<li>Bounded-Buffer Problem(Producer-Consumer Problem)</li>
<li>Readers and Writers Problem</li>
<li>Dining-Philosophers Problem</li>
</ul>
</br>

<h3 id="bounded-buffer-problemproducer-consumer-problem">Bounded-Buffer Problem(Producer-Consumer Problem)</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/aa7913de-4212-4e92-9b96-e9193f730190/1.PNG" alt=""></p>
<p>왼쪽이 Producer 프로세스, 오른쪽이 Consumer 프로세스(Producer와 Consumer는 여러 개 있음)</p>
<p>생산자는 버퍼에 데이터를 만들어 넣는 역할, 소비자는 데이터를 꺼내는 역할</p>
</br>

<p><strong>Synchronization 문제</strong></p>
<ul>
<li><p>생산자 둘이 동시에 빈 버퍼에 데이터를 넣는 경우(<strong>버퍼에 lock/unlock 검으로써 해결</strong>)</p>
</li>
<li><p>소비자 둘이 동시에 버퍼에서 데이터를 꺼내는 경우(<strong>버퍼에 lock/unlock 검으로써 해결</strong>)</p>
</li>
<li><p>버퍼의 개수가 유한하기 때문에, <strong>모든 버퍼가 차 있는 경우(소비자가 데이터를 소비하지 않고)</strong>, 더이상 버퍼에 데이터를 넣을 수 없게됨 -&gt; 버퍼가 비워질때까지 기다려야 함(어떻게 버퍼가 비워졌는지 알까?)</p>
<p>버퍼의 개수가 유한하기 때문에, <strong>모든 버퍼가 비워져있는 경우(생산자가 데이터를 넣지않고)</strong>, 더이상 버퍼에서 꺼낼게 없게됨 -&gt; 버퍼가 채워질때까지 기다려야 함(어떻게 버퍼가 채워졌는지 알까?)</p>
<p>=&gt; <strong>가용 자원의 개수를 세는 것이 필요</strong>(생산자: <strong>Full Buffer</strong>, 소비자: <strong>Empty Buffer</strong>)</p>
</li>
</ul>
</br>

<p><strong>Producer(with Semaphore)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/14988d64-9300-455b-9057-bb583ecc2ed8/2.PNG" alt=""></p>
<ul>
<li><strong>P(empty):</strong> 빈 버퍼 획득(빈 버퍼가 없으면, 기다림)</li>
<li><strong>P(mutex):</strong> 버퍼에 lock을 검</li>
<li><strong>V(mutex):</strong> 버퍼에 lock을 품</li>
<li><strong>V(full):</strong> 내용이 들어있는 버퍼 개수 증가(++)</li>
</ul>
</br>

<p><strong>Consumer(with Semaphore)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/30a70d42-e18f-458b-b19d-7ecff5c9a334/3.PNG" alt=""></p>
<ul>
<li><strong>P(full):</strong> 내용이 들어있는 버퍼 획득(내용이 들어있는 버퍼가 없으면, 기다림)</li>
<li><strong>P(mutex):</strong> 버퍼에 lock을 검</li>
<li><strong>V(mutex):</strong> 버퍼에 lock을 품</li>
<li><strong>V(empty):</strong> 비어있는 버퍼 개수 증가(++)</li>
</ul>
</br>

<h3 id="readers-writers-problem">Readers-Writers Problem</h3>
<hr>
<ul>
<li><p>한 Process(데이터를 읽거나 쓰는 주체: Reader, Writer)가 DB(공유데이터)에 write 중일 때 다른 process가 접근하면 안됨</p>
</li>
<li><p>read는 동시에 가능, write는 불가능</p>
</li>
<li><p>공유데이터</p>
<ul>
<li>DB 자체</li>
<li>readcount: 현재 DB에 접근 중인 Rader의 수</li>
</ul>
</li>
<li><p>synchronization variables</p>
<ul>
<li><strong>mutex:</strong> readcount에 lock을 위한 binary semaphore </li>
<li><strong>db:</strong> 공유DB에 lock을 위한 binary semaphore</br>

</li>
</ul>
</li>
</ul>
<p><strong>Writer(with Semaphore)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/ffc431cc-e214-4442-969f-fadd4e33e2ca/4.PNG" alt=""></p>
<ul>
<li><strong>P(db):</strong> db에 대한 lock을 검</li>
<li><strong>V(db):</strong> db에 대한 lock을 품</li>
</ul>
</br>

<p><strong>Reader(with Semaphore)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/394bdf82-a1db-430a-9292-eea0adf49ac9/5.PNG" alt=""></p>
<ul>
<li><strong>P(mutex):</strong> readcount라는 공유변수에 lock을 검(for ++)</li>
<li><strong>readcount:</strong> 공유데이터를 read하는 reader의 수</li>
<li><strong>if(readcount==1) P(db):</strong> 최초 reader만 공유데이터(db)에 lock을 검</li>
<li><strong>V(mutex):</strong> readcount라는 공유변수에 lock을 품</li>
<li><strong>P(mutex):</strong> DB를 다 읽고 readcount라는 공유변수에 lock을 검(for --)</li>
<li><strong>if(readcount==0) V(db):</strong> 마지막 reader라면, db에 대한 lock을 품</li>
<li><strong>V(mutex):</strong> readcount라는 공유변수에 lock을 품</li>
</ul>
<p>=&gt; Reader가 먼저 도착하고 Writer가 그 다음 도착했으면, Reader가 DB에 lock을 걸어놨기때문에 Writer는 기다린다. 그 다음, 또 다른 Reader가 들어왔다면, Reader끼리는 같이 read 할 수 있기때문에 DB에 접근이 가능해진다. 이후에도 Reader가 계속 들어온다면, Writer가 계속 기다린다.(Starvation 발생)</p>
</br>

<h3 id="dining-philosophers-problem">Dining-Philosophers Problem</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/9992a488-edd3-4ac1-ba5c-d94e1d42f5c6/6.PNG" alt=""></p>
<p>5명의 철학자는 각각 <strong>생각하는 일</strong>과 <strong>밥먹는 일</strong>을 한다.</p>
<p>배고프면 자신의 오른쪽과 왼쪽에 있는 젓가락을 들고 밥을 먹는다.(둘 중 하나라도 없으면 밥을 못먹음)</p>
</br>

<p><strong>Philosopher(with Semaphore)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/16908a16-c085-43c2-ba28-2634c879bfd0/image.png" alt=""></p>
<ul>
<li><p><strong>위 코드의 문제점</strong></p>
<ul>
<li><strong>Deadlock 가능성</strong>이 있음(모든 철학자가 동시에 배가고파 왼쪽 젓가락을 잡으면(오른쪽 젓가락을 얻을때까지 놓지 않음), 오른쪽 젓가락을 잡을 수 없음)</li>
</ul>
</li>
<li><p><strong>해결방안</strong></p>
<ul>
<li>4명의 철학자만 테이블에 동시에 앉을 수 있게 함</li>
<li>젓가락을 모두 잡을 수 있을때에만 젓가락을 잡을 수 있게 함</li>
<li>짝수(홀수) 철학자는 왼쪽(오른쪽) 젓가락부터 잡도록 함</li>
</ul>
</li>
<li><p><strong>개선 코드</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/53c82964-9ba3-45a7-b7cf-d16b6363da5a/image.png" alt=""></p>
</li>
</ul>
<p>​        <strong>state:</strong> 철학자들의 상태, </p>
<p>​        <strong>self:</strong> 젓가락을 잡을 수 있는지 여부를 나타내는 Semaphore, </p>
<p>​        <strong>mutex:</strong> state 공용변수 lock을 위한 Semaphore</p>
<p>​        <strong>젓가락 잡는 코드:</strong> state 변수 접근을 위해 P(mutex) lock을 검-&gt; 자신의 state hungry로 변경 -&gt; test(i) -&gt; V(mutex) 공유데이터에 건 lock을 품 -&gt; 젓가락 잡을 수 있는 권한을 얻었으면, 종료(P(self[i])(1 -&gt; 0). 젓가락 잡을 수 있은 권한이 없으면, P(self[i])에서 기다림</p>
<p>​        <strong>test(i)</strong>:  왼쪽 철학자와 오른쪽 철학자 모두 밥을 먹지 않고, 내가 hungry인 경우 나의 상태를 eating으로 바꿈 -&gt; 젓가락 잡을 수 있는 권한 부여 V(self[i])(0 -&gt; 1)</p>
<p>​        <strong>젓가락 내려놓는 코드:</strong> P(mutex) 공유변수에 lock을 걸고, 자신의 상태를 thinking으로 바꿈 -&gt; 왼쪽과 오른쪽 철학자가 자신으로 인해 밥을 못먹었다면, 밥을 먹을 수 있게 해줌 test() -&gt; 공유변수에 대한 lock을 품 V(mutex)</p>
<p>​        세마포어가 자원의 개수가 아닌 상태체크용으로 사용되기에 세마포어의 철학과 벗어난 코드이다.</p>
</br>

<h3 id="monitor">Monitor</h3>
<hr>
<p><strong>Semaphore의 문제점</strong></p>
<ul>
<li>코딩하기 힘듦(프로그래머가 직접 코딩)</li>
<li>정확성의 입증이 어려움</li>
<li>자발적 협력이 필요</li>
<li>한번의 실수가 모든 시스템에 치명적 영향(프로그래머에게 부담이 큼.)<ul>
<li>V 연산을 먼저하게되면 Mutual exclusion 깨짐, P 연산만 하게되면 Deadlock 문제</li>
</ul>
</li>
</ul>
</br>

<p><strong>모니터</strong>는 이러한 문제를 보완하기 위해 동시 수행중인 프로세스 사이에서 추상 데이터 타입의 안전한 공유를 보장하기 위한 high-level synchronization construct임</p>
<p>프로그래밍 언어차원에서 공유데이터 접근에 대한 문제를 자동으로 해결해줌으로써 프로그래머의 부담 줄여줌</p>
<p><strong>목적:</strong> 공유데이터에 대한 동시접근을 모니터 차원에서 지원</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/6b9cc2e8-c8c3-4e95-b04f-b9577b61449c/image.png" alt=""></p>
<ul>
<li>모니터 내부 공유변수는 모니터 내부 프로시저만 접근할 수 있음</li>
<li>모니터 내에서는 한번에 하나의 프로세스만 활동 가능(프로그래머가 따로 lock을 걸어줄 필요가 없음)</li>
<li>프로그래머가 동기화 제약 조건을 명시적으로 코딩할 필요없음</li>
<li>프로세스가 모니터 안에서 기다릴 수 있도록 하기 위해 <strong>condition variable</strong> 사용<ul>
<li><strong>wait():</strong> 프로세스가 suspend 됨(sleep)</li>
<li><strong>signal():</strong> 프로세스를 invoke 함(wakeup)</li>
</ul>
</li>
</ul>
</br>

<h3 id="classical-problem-of-synchronization을-모니터로">Classical Problem of Synchronization을 모니터로</h3>
<hr>
<p><strong>Bounded-Buffer Problem</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/861938dd-4438-45f5-8d31-1e22b4a89eeb/10.PNG" alt=""></p>
<p>​    <strong>empty:</strong> 내용이 빈 버퍼를 기다리는 프로세스를 줄세워 놓은 condition variable(큐)</p>
<p>​    <strong>full:</strong> 내용이 차있는 버퍼를 기다리는 프로세스를 줄세워 놓은 condition variable(큐)</p>
</br>

<p><strong>Dining Philosophers Problem</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/895b59b3-de71-4bb5-9709-a39d33ba31cc/11.PNG" alt=""></p>
<h1 id="참고">참고</h1>
<p><a href="https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f">https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[네트워크 장비]]></title>
            <link>https://velog.io/@alwayslee_12/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9E%A5%EB%B9%84</link>
            <guid>https://velog.io/@alwayslee_12/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9E%A5%EB%B9%84</guid>
            <pubDate>Thu, 04 Nov 2021 12:48:10 GMT</pubDate>
            <description><![CDATA[<h3 id="nicnetwork-interface-card">NIC(Network Interface Card)</h3>
<hr>
<p>보통 랜카드라고 함(LAN에 접속하기 위해 필요한 카드처럼 생긴 것. 카드형으로 되어있기도 하고, 메인보드에 붙어있기도 함)</p>
<p>유저의 데이터를 케이블에 실어 허브나 스위치, 라우터 등에 전달하고, 자신에게 온 데이터를 CPU에 전달</p>
</br>

<p><strong>랜가드의 구분</strong></p>
<p>랜카드를 어디에 설치하느냐에 따라 데스크톱용 랜카드와 PCMCIA 방식이라고 하는 노트북용 랜카드로 나뉨</p>
<p>특히, 데스크톱용 랜카드를 선택할때, 추가적으로 고려해야 할 사항이 있는데 , 바로 PC의 버스 방식이다.</p>
<p>PC의 버스 방식(랜카드의 구분)은 크게 PCI(현재 가장 많이 사용하는 방식), ISA(이전에 많이 사용했던 방식), EISA 방식으로 구분된다.</p>
<p>위 3가지 버스 방식 중 자신의 PC가 어떤 방식을 사용하는 PC인지 확인 후 랜카드를 선택해야 한다.</p>
<p>또한, 이더넷 랜카드는 속도에 따라 10메가, 100메가(100Mbps. 데이터 전송 속도: 1초에 100,000,000bit=12,500,000byte=1초에 10MB 정도의 파일 전송. 실제로는 layer 별로 데이터에 header와 같은 overhead가 붙기에 이렇게까지는 속도가 나오지 않음), 10,100메가, 1기가 등으로 나눌 수 있다.</p>
<p>케이블의 종류에 따라 랜카드를 TP(일반적으로 사용) 포트를 가진 랜카드, BNC나 AUI(예전에 많이 사용) 포트를 가진 랜카드, 광케이블과(경우에 따라 사용) 접속하는 랜카드 등으로 나눌 수 있음</p>
<blockquote>
<p>BNC용 커넥터와 AUI용 커넥터, UTP용 커넥터를 모두 골라 연결할 수 있는 combo 방식을 사용하기도 했음</p>
</blockquote>
</br>

<p><strong>IRQ와 Base Memory</strong></p>
<p>랜카드로 데이터가 도착하고, 데이터의 목적지가 랜카드의 MAC Address 주소이면, PC의 CPU에 IRQ(인터럽트 요청)를 이용해 인터럽트를 걸게 된다. </p>
<p>CPU는 Interrupt line에서 랜카드가 요청한 IRQ를 보고, Base Memory(데이터에 어떤 서비스를 할 것인지 미리 정해놓는 장소)로 이동해 작업을 시작</p>
</br>

<h3 id="허브">허브</h3>
<hr>
<p>허브는 직사각형 상자에 구멍이 뚫려있는 모습으로 되어있고, 이 구명이 몇 개(장비를 연결할 수 있는 개수) 뚫려있느냐에 따라 몇 포트 허브인지 구분한다.</p>
<p>허브는 멀티포트 리피터 역할을 수행(많은 PC를 연결하고 들어온 데이터를 그대로 재전송)</p>
<p>같은 허브에 연결되어있는 PC끼리는 서로 통신이 가능</p>
</br>

<p><strong>허브 용도에 따른 구분</strong></p>
<p>허브도 랜카드와 마찬가지로 토큰링용과 이더넷용이 있음</p>
<p>이더넷용 허브는 속도에 따라 그냥 허브(10Mbps)와 패스트 허브(100Mbps가 있음)</p>
</br>

<p><strong>허브에서의 통신</strong></p>
<p>PC 1~4까지 있다고 하고, PC1이 PC2에 데이터를 허브를 통해 전송한다고 해보자</p>
<p>PC1이 PC2가 목적지인 데이터를 허브에 보내면, 허브는 그저 데이터를 그대로 재전송하는 역할을 수행하기에 모든 PC에 해당 데이터를 보낸다.</p>
<p>해당이 되지 않는 PC3,4는 랜카드딴에서 목적지의 주소가 자신의 MAC Address와 다르기에 데이터를 버리고, PC2의 랜카드는 목적지의 주소가 자신의 MAC Address이므로, 이를 CPU에 인터럽트를 걸어 해당 데이터에 대한 처리를 요구한다.</p>
<p>이 허브는 CSMA/CD 방식을 적용한 이더넷 허브이므로, 충돌이 발생할 수 있고, 해당 허브에 연결되어있는 PC1~4는 같은 Collision Domain에 있음</p>
</br>

<p><strong>허브의 한계</strong></p>
<ol>
<li>속도의 한계</li>
</ol>
<p>같은 허브에 연결되어 있는 PC들은 모두 하나의 Collision Domain에 있기 때문에 허브의 속도를 PC들이 공유하게 된다(Shared 허브)</p>
<p>만약, 화상 회의나 멀티미디어 등과 같은 데이터 양이 많은 상황이라면, 10Mbps Shared Hub로는 무리가 있을 것이다.</p>
<p>속도를 좀 더 높이기 위해 랜카드의 속도도 100Mbps인 것으로 바꾸고, 케이블로 100Mbps용으로 바꾸고, 허브도 100Mbps로 바꿨다고 해보자.</p>
<p>이 경우에도 어차피, 모든 PC들이 허브를 공유하고, 한 순간에 독점하는 PC가 있을 수도 있기때문에 그닥 효과가 있는 방법은 아닐 것이다.</p>
</br>

<ol start="2">
<li>Collision의 영향</li>
</ol>
<p>허브에 허브를 연결하고 또 연결하다 보면, 많은 PC들 간 통신이 가능해지겠지만, 충돌이 더 자주 발생할 뿐 아니라, Collision Domain이 더 커지게 된다.</p>
<p>Collision Domain이 커지게 되면, 충돌이 발생했을 때, 영향을 받는 PC들이 더욱 늘어난다는 소리이다.</p>
<p>이러한 문제때문에, 먼 거리의 PC들을 허브로만 연결하는 데는 한계가 있다.</p>
</br>

<p><strong>허브의 종류</strong></p>
<p>허브의 종류로는 보통 인텔리전트 허브와 더미 허브, 세미 더미 허브(+스태커블 허브도 있음 But 다음에)가 있다.</p>
<p>인텔리전트 허브는 NMS(네트워크 관리 시스템. 허브의 동작을 감시하고 제어)를 통해 관리가 되고, 더미 허브는 그렇지 않다.</p>
<p>인털리전트 허브는 또한, 문제가 발생한 포트에 대해 Isolation시켜버려, 한 포트에서 문제가 발생해도, 나머지 PC들이 영향을 받지 않게 한다.(분리된 포트가 어떤건지 램프로 표시도 해줌(Auto Partition))</p>
<p>세미 더미 허브는 디폴트는 더미 허브인데 인텔리전트 허브와 연결되면 인텔리전트 허브가 되는 허브이다.</p>
</br>

<p><strong>Stackable 형과 Standalone 형?</strong></p>
<p><strong>스태커블 형</strong>은 스태커블끼리 연결하면 백플레인(장비 간 데이터 전송을 위해 연결된 일종의 고속도로)이 훨씬 빨라지고, 연결된 장비 중 하나가 고장나도 다른 장비에 영향 안끼침. 또한, NMS를 이용한 관리 시에도 전체 스택 장비들을 마치 한대의 장비처럼 관리할 수 있음(여러 대의 허브나 스위치를 쓰는 경우)</p>
<p><strong>스탠드얼론 형</strong>은 서로 연결은 되지만,  이러한 특징을 가지고 있진 않음 (작은 규모의 경우)</p>
</br>

<h3 id="스위치">스위치</h3>
<hr>
<p>허브의 Collision Domain이 커져 통신 속도의 영향을 받게되는 문제를 해결하기 위해 Collision Domain을 나눠주는 장비</p>
<p>스위치가 브리지보다 빠른 장비</p>
</br>

<p><strong>장점</strong></p>
<p>스위치는 포트별로 Collision Domain을 나눠준다.(1,2번 포트의 PC들이 통신할 때, 3,4번 PC도 통신할 수 있음)</p>
<p>그렇기에 각각 포트별로 독자적으로 10Mbps or 100Mbps or etc..의 속도를 갖음</p>
<p>허브보다 속도가 빠름</p>
<p>데이터를 처리하는 방법이 우수, 데이터의 전송 에러 등을 복구하는 기능 등 여러가지 기능이 있음</p>
</br>

<p><strong>허브냐 스위치냐</strong></p>
<p>답은 상황에 따른 사용이다.(네트워크에 돌아다니는 데이터에 따른)</p>
<p>만약 채팅이나 메일 정보만 쓰는 네트워크라면, 트래픽 자체가 적기 때문에 PC들을 비싼 스위치(예전 얘기)에 붙이기보다는 허브에 붙이는 걸로 충분할 것이다.(근데 요즘에는 스위치의 가격이 많이 싸지긴 해서 괜찮을지도....)</p>
</br>

<p><strong>한계</strong></p>
<p>만약 모든 PC가 전부 하나의 서버와 통신을 하게 된다면 어떻게 될까?</p>
<p>허브의 경우 당연히 하나의 PC가 통신중이면, 다른 PC들은 통신을 할 수 없기 때문에 불가능하다.</p>
<p>스위치도 마찬가지이다. 포트끼리 Collision Domain을 나눠놨을 뿐이라, 전체 PC가 통신을 한다라고 했을때는 결국 하나의 PC밖에 서버와 통신할 수 없다.</p>
<p>즉, 모든 장비가 무조건 한 곳으로만 향하는 경우 허브나 스위치나 속도상으로 별반 다를게 없다는 소리이다.(통신의 효율성은 좋으나 속도 향상은 그게 변화 없음)</p>
</br>

<h3 id="브리지">브리지</h3>
<hr>
<p>스위치를 이해하기 위해서는 먼저 원조인 브리지를 알고가야 한다.</p>
<p>허브는 모든 PC들이 하나에 붙어있기에 이 허브로 연결된 PC들 간 통신에 문제가 생길 수도 있다. 이때, 브리지나 스위치를 사용해 Collision Domain을 나눠준다고 했다.</p>
<p>스위치는 위해서 말했듯이 그러한 역할을 수행하는데 과연 브리지도 그럴까?</p>
<p>물론이다. 브리지는 허브로 만들어진 Collision Domain 중간에 다리를 놓아 반으로 나눈다.(마찬가지로 Collision Domain을 나눠준다는 것)</p>
<h3 id="브리지스위치의-기능">브리지/스위치의 기능</h3>
<hr>
<p>브리지/스위치는 다음 5가지의 일을 함</p>
<ul>
<li><strong>Learning(학습):</strong> 호스트가 브리지/스위치에 프레임을 보내면 브리지/스위치는 호스트의 MAC Address를 읽어 자신의 <code>브리지 테이블</code>에 저장(이는 호스트에게 통신을 요청할 때 참고해 다리를 건너게 할 지 못 건너게 할 지 판단하는데 쓰임)</li>
<li><strong>Flooding:</strong> 목적지 호스트가 <code>브리지 테이블</code>에 기록되어있지 않다면, 보낸 호스트의 포트를 제외한 나머지 포트에 뿌림(이뿐만아니라 브로드캐스트나 멀티캐스트의 경우에도 발생)</li>
<li><strong>Forwarding:</strong> 목적지 호스트가 <code>브리지 테이블</code>에 기록되어 있고, 출발지 포트와 목적지 포트의 세그먼트가 다르면(다른 Collision Domain), 다른 세그먼로 넘어가게 해줌</li>
<li><strong>Filtering:</strong> 다른 포트로 못 건너가게 막음. 목적지 호스트가 <code>브리지 테이블</code>에 기록되어 있고, 출발지 포트와 목적지 포트의 세그먼트가 같으면, 프레임이 다른 세그먼트로 넘어가지 못하게 막음(<strong>Collision Domain을 나누는 기능</strong>)</li>
<li><strong>Aging:</strong> <code>브리지 테이블</code>은 영원히 호스트들의 MAC Address를 저장하는 것은 불가능하다. 만약 영원히 저장하게 한다면, 용량이 한정되어 있기 때문에, 더이상의 학습을 할 수 없을 것이다. Aging이란 인간의 뇌처럼 프레임이 들어오면, <code>브리지 테이블</code>에 저장하고 그와 동시에 시간을 정해놓고 타이머를 작동시키는 기능이다. 만약 해당 MAC Address를 가진 프레임이 더이상 들어오지 않은 채, 정해놓은 시간이 다 지나면, 그 MAC Address는 테이블에서 삭제된다.(정해진 시간이 다 지나기 전 해당 MAC Address를 가진 프레임이 들어오면, 타이머를 리셋(리플래시))</li>
</ul>
</br>

<h3 id="브리지와-스위치의-차이점">브리지와 스위치의 차이점</h3>
<hr>
<p>둘은 같은 데이터 링크 레이어에 속하고 하는 일도 비슷하다.</p>
<p>하지만, 이 둘 간에도 차이는 존재한다.</p>
<ul>
<li><p>이름</p>
</li>
<li><p>가격: 스위치가 더 비쌈</p>
</li>
<li><p>선호도: 스위치가 선호도가 더 높음</p>
</li>
<li><p>스위치는 프레임을 ASIC 하드웨어 방식으로 처리하기에 소프트웨어적 프로그램에 의해 프레임을 처리하는 브리지보다 프레임 처리속도가 빠름 </p>
</li>
<li><p>브리지는 포트들이 같은 속도를 지원하지만, 스위치는 포트들마다 서로 다른 속도를 지원하도록 할 수 있음</p>
</li>
<li><p>스위치가 포트 수가 더 많음</p>
</li>
<li><p>스위치의 경우 Cut-through or Store-and-forward 방식을 사용하지만, 브리지는 Store-and-forward 방법만을 사용</p>
<ul>
<li><p><strong>Cut-through:</strong> 프레임의 목적지 주소만 확인한 후 바로 목적지로 전송.(처음 48bit만 봄) 처리 속도는 빠르지만, 에러 복구 능력이 떨어짐</p>
</li>
<li><p><strong>Store-and-forward:</strong> 프레임을 모두 받아들이고 나서 프레임이 잘 들어왔는지, 에러는 없는지, 출발지와 목적지는 어디인지를 파악해서 처리를 해주는 방식. 만약 에러가 발견되면, 프레임을 버리고 재전송을 요구함. </p>
<p>회선에 에러가 자주 발생하거나 출발지와 목적지의 전송 매체가 다른 경우 자주 사용하는 방식</p>
</li>
<li><p><strong>Fragment-free:</strong> Store-and-forward 방식과 Cut-through 방식의 장점을 결합한 방식. 프레임을 모두 받지는 않고, 처음 512bit만 봄.</p>
<p>에러 감지 능력이 컷스루보다는 우수</p>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="looping이-생기는-이유">Looping이 생기는 이유</h3>
<hr>
<p>Looping은 브리지나 스위치에서 발생하는 현상이다.</p>
<p>Looping은 프레임이 네트워크상에서 계속 뱅뱅돌기때문에 이더넷 특성상 다른 프레임을 전송할 수 없는 상태를 말한다.</p>
<p>예를 들어, 두 호스트 사이에 스위치/브리지가 두 개 있다고 하면, 하나의 호스트에서 다른 호스트로 가는 경로가 두 개 이상 만들어지기때문에, 루핑이 발생한다.(한 호스트가 브로드캐스트를 보내면, 두 스위치/브리지가 이를 수신하고 Flooding 함. 이를 계속 반복)</p>
<p>루핑은 네트워크를 치명적인 상태에 빠뜨리게 된다.</p>
<p>이러한 루핑을 막기 위해서는 어떻게 해야할까? Spanning Tree Algorithm을 이용해 막으면 된다.</p>
</br>

<p><strong>Spanning Tree Algorithm</strong></p>
<ul>
<li>자동으로 루핑을 검색해서 루핑이 발생할 수 있는 상황을 미리 막아줌(스위치 간 두 개의 링크 중 하나를 끊음으로써)</li>
<li>결과적으로 데이터는 하나의 링크로만 전송됨</li>
<li>만약 데이터가 흐르는 링크에 문제가 생기면, 끊었던 링크를 다시 살려 데이터가 그쪽으로 전송되게 함</li>
<li>모든 스위치는 스패닝 트리 알고리즘을 지원</li>
<li>끊어진 링크를 다시 살리는 데 소요되는 시간은 1분 이상(이더 채널은 여러 개의 링크가 마치 하나의 링크처럼 인식되게 하는 기술로 이 알고리즘의 약점을 보완, 업링크 패스트라는 기술도 있음)</li>
</ul>
</br>

<h3 id="라우팅-스위칭">라우팅, 스위칭</h3>
<hr>
<p>스위치가 가격, 속도, 구성의 편리함 면에서 라우트보다 낫다는 장점이 있지만, 근본적으로 스위치만으로는 풀 수가 없는 문제가 있다.</p>
<ol>
<li><p><strong>브로드캐스트:</strong> 브로드캐스트의 도메인을 나눠주기 위해 라우터가 꼭 필요(브로드캐스트 자체가 네트워크의 성능을 저하시키는데, 이 영향의 범위를 줄이기 위해 브로드캐스트 도메인을 나눠야 함.)</p>
<p>보통 브로드캐스트 영역을 나눌 때 IP일때는 약 500노드, IPX일 때는 300노드, AppleTalk일 때는 200노드 정도(각각 반 노드 정도는 사용해야 제대로 네트워크를 사용할 수 있고, 노드란 네트워크에 접속되는 장비 주로 PC를 말함)</p>
</li>
<li><p><strong>패킷 필터링:</strong> 라우터는 네트워크 주소에 따라 전송을 막았다 풀었다 하는 필터 기능을 제공해 불필요한 트래픽이 전송되는 것을 막음</p>
</li>
<li><p><strong>로드 분배:</strong> 데이터가 여러 개의 경로를 타고 갈 수 있게 함.(한쪽 경로에서 문제가 생겨도 다른 경로로 통신가능)</p>
</li>
<li><p>라우터는 프로토콜이나 데이터의 크기, 중요도 등 여러 상황에 따라 트래픽의 전송 순서를 조정해주는 기능을 제공(<strong>QoS: Quality of Service</strong>)</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[CPU Scheduling]]></title>
            <link>https://velog.io/@alwayslee_12/CPU-Scheduling</link>
            <guid>https://velog.io/@alwayslee_12/CPU-Scheduling</guid>
            <pubDate>Thu, 04 Nov 2021 06:20:39 GMT</pubDate>
            <description><![CDATA[<h3 id="cpu-burst-time-분포">CPU-burst TIme 분포</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/4b5ed347-7411-4944-a734-48c424672429/2.PNG" alt=""></p>
<p><strong>I/O bound job(Interactive Job):</strong> CPU burst 시간이 짧은 프로그램의 종류(I/O 작업이 자주 끼어드는 경우. CPU를 짧게 자주 씀. 주로 사람과 Interaction을 많이 함)</p>
<p><strong>CPU bound job:</strong> CPU burst 시간이 긴 프로그램의 종류(CPU 사용 시간이 긴 경우. 계산 위주의 job)</p>
<p>=&gt; 위처럼 여러 종류의 job이 섞여있기에 CPU 스케쥴링이 필요(Interactive Job(사용자와 상호작용이 잦은 작업)에 CPU를 우선적으로 주자 for 효율성(not 공정성)(CPU bound job 위주면 사용자 입장에서 너무 오래 기다려야 함))</p>
</br>

<h3 id="cpu-scheduler--dispatcher">CPU Scheduler &amp; Dispatcher</h3>
<hr>
<ul>
<li>CPU Scheduler: Ready 상태의 프로세스 중 CPU를 넘겨줄 프로세스를 고르는 것(운영체제 내부에 CPU 스케쥴링 관련 코드)</li>
<li>Dispatcher: CPU의 제어권을 CPU Scheduler에 의해 선택된 프로세스에 넘김(문맥 교환)</li>
<li>CPU 스케쥴링이 필요한 경우<ul>
<li>I/O 작업을 위해 시스템 콜을 요청한 프로세스(Nonpreemtive)</li>
<li>타이머 인터럽트가 발생한 프로세스(Preemtive)</li>
<li>I/O 작업을 완료해 인터럽트가 발생한 경우(보통은 기존에 수행하던 프로세스에 다시 CPU 제어권을 넘겨주지만, 우선순위에 기반한 스케쥴링에 경우, I/O 작업을 요청했던 프로세스가 우선순위가 높은 경우라면 해당 프로세스가 CPU 제어권을 받게 됨)</li>
<li>프로세스가 종료된 경우</li>
<li>etc....</li>
</ul>
</li>
</ul>
</br>

<h3 id="scheduling-algorithm">Scheduling Algorithm</h3>
<hr>
<p><strong>Non-preemtive(비선점형. CPU 뺏기지 않음)</strong></p>
<ul>
<li><p><strong>FCFS(First-come First-served):</strong> 먼저 들어온 순서대로 처리(프로세스들의 수행 시간에 따라 응답 시간, 대기 시간이 길어질 수 있음(convoy effect))</p>
</li>
<li><p><strong>SJF(Shortest-Job-First):</strong> 도착한 프로세스 중 수행시간이 짧은 프로세스부터 처리</p>
<p>평균 대기 시간이 짧음.</p>
<p>Starvation(기아 현상. CPU 수행시간이 긴 프로세스는 CPU 사용이 계속 밀림)문제. </p>
<p>매번 CPU 사용 시간을 미리 알기가 어려움(보통 과거의 CPU 사용 이력을 보고 예측))</p>
<p>(n+1)번째 CPU 사용 예측 시간= a x n번째 CPU 사용시간 + (1-a) x n번째 CPU 사용 예측시간 ---(exponential averaging. 현재에서 과거로 갈수록 반영비율 적게)</p>
</li>
<li><p><strong>Priority Scheduling:</strong> 높은 우선순위를 가진 프로세스에 CPU 할당(SJF는 일종의 Priority Scheduling). </p>
<p>우선순위가 낮은 프로세스에 대해 기아 현상 발생(Aging 기법(우선순위를 조금씩 올려줌)을 사용해 해결)</p>
</li>
</ul>
</br>

<p><strong>Preemtive(선점형. CPU를 뺏을 수 있음. 현대적 CPU Scheduling 방법)</strong></p>
<ul>
<li><p><strong>SJF || SRTF(Shortest-Job-First, Shortest-Remaining-Time-First):</strong> 대기 프로세스 중 수행시간이 더 짧은 프로세스가 있으면, CPU를 뺏어 그 프로세스에 줌(평균 대기 시간 짧음)</p>
</li>
<li><p><strong>Priority Scheduling:</strong> 높은 우선순위를 가진 프로세스에 CPU 할당(SJF는 일종의 Priority Scheduling)</p>
</li>
<li><p><strong>RR(Round Robinn):</strong> 각 프로세스는 동일한 크기의 할당 시간을 가짐. 각 프로세스는 할당 시간만큼 CPU 사용. 현대적인 CPU 스케쥴링 방법(응답 시간 빠름)</p>
<p>할당 시간을 길게 해놓으면, FCFS랑 다를게 없을 것이고, 짧게 해놓으면, 문맥 교환이 잦게된다(오버헤드가 큼)</p>
<p>일반적으로 SJF보다 평균 반환시간이 길지만, 응답 시간은 빠름</p>
</li>
</ul>
</br>

<h3 id="scheduling-criteria성능-척도">Scheduling Criteria(성능 척도)</h3>
<hr>
<p><strong>시스템 입장에서의 성능 척도</strong></p>
<ul>
<li><strong>CPU Utilization(이용률):</strong> 전체 시간 중 CPU가 일한 시간의 비율</li>
<li><strong>Throughput(처리량):</strong> 주어진 시간동안 몇 개의 작업을 처리했는지</li>
</ul>
</br>

<p><strong>프로그램  입장에서의 성능 척도</strong></p>
<ul>
<li><strong>Turnaroud Time(소요시간, 반환시간):</strong> CPU를 사용하러 들어와서 다 쓰고 나갈때까지의 시간</li>
<li><strong>Waiting Time(대기 시간):</strong> CPU를 사용하기위해 기다린 시간(CPU 사용을 위해 기다린 총 시간)</li>
<li><strong>Response Time(응답 시간):</strong> 최초에 CPU를 얻기까지 기다린 시간</li>
</ul>
</br>

<h3 id="multilevel-queue">Multilevel Queue</h3>
<hr>
<p>큐의 우선순위에 따라 CPU를 할당(위에 큐가 제일 높은 큐. 해당큐가 비어있으면, 그 다음 우선순위...)</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/36222b2f-f2e6-40b2-9a1d-8e0f84efd73b/1.PNG" alt=""></p>
<ul>
<li>Ready Queue를 여러 개로 분할<ul>
<li>foreground: interactive한 job을 넣음</li>
<li>background: batch- no human interaction job을 넣음</li>
</ul>
</li>
<li>각 큐는 독립적인 스케쥴링 알고리즘을 가짐<ul>
<li>foreground: RR</li>
<li>background: FCFS</li>
</ul>
</li>
<li>큐에 따른 스케쥴링 필요<ul>
<li>Fixed Priority Scheduling<ul>
<li>모든 foreground가 수행되고, background를 수행</li>
<li>starvation문제</li>
</ul>
</li>
<li>Time Slice<ul>
<li>각 큐에 CPU Time을 적절한 비율로 할당</li>
<li>ex) foreground 80%(RR), background 20%(FCFS)</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="multilevel-feedback-queue">Multilevel Feedback Queue</h3>
<hr>
<p>프로세스가 경우에 따라 큐를 이동할 수 있음</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/a2e7620c-542d-42bb-9c24-0527e0a8410f/2.PNG" alt=""></p>
<ul>
<li>보통 3개의 큐가 있음<ul>
<li>첫 번째 큐는 quantum time이 8ms(RR)</li>
<li>두 번째 큐는 quantum time이 16ms(RR)</li>
<li>세 번째 큐는 FCFS</li>
</ul>
</li>
<li>스케쥴링 메커니즘<ul>
<li>새로운 프로세스가 첫 번째 큐로 들어감</li>
<li>CPU를 점유하며 8ms 동안 수행</li>
<li>그 안에 다 끝내지 못했으면, 두 번째 큐로 강등</li>
<li>두 번째 큐에서 기다리다가 차례가 되면 CPU를 점유해서 16ms 동안 수행</li>
<li>그 안에 다 끝내지 못했으면, 세 번째 큐로 강등</li>
</ul>
</li>
</ul>
</br>

<h3 id="multiple-processor-scheduling">Multiple-Processor Scheduling</h3>
<hr>
<p>CPU가 여러 개인 경우 스케쥴링</p>
<ul>
<li>CPU가 여러 개인 경우 스케쥴링은 더욱 복잡</li>
<li><strong>Homogeneous Processor인 경우</strong><ul>
<li>큐에 한줄로 세워 각 프로세서가 알아서 꺼내가게 함</li>
<li>특정 프로세서에서 수행되어야 하는 프로세스가 있는 경우 문제가 있음</li>
</ul>
</li>
<li><strong>Load Sharing</strong><ul>
<li>일부 프로세서에 프로세스가 몰리지 않게 부하를 적절히 공유하는 매커니즘 필요(노는 CPU가 있으면 안됨)</li>
<li>프로세서 별 별도의 큐를 두는 방법 vs 공동 큐를 사용하는 방법</li>
</ul>
</li>
<li><strong>Symmetric Multiprocessing(SMP)</strong><ul>
<li>각 프로세서가 각자 알아서 스케쥴링 결정</li>
</ul>
</li>
<li><strong>Asymmetric Multiprocessing</strong><ul>
<li>하나의 프로세서가 시스템 데이터의 접근과 공유를 책임지고 나머지 프로세서가 따르는 구조</li>
</ul>
</li>
</ul>
</br>

<h3 id="real-time-scheduling">Real-Time Scheduling</h3>
<hr>
<ul>
<li><strong>Hard real-time systems</strong><ul>
<li>Hard real-time task는 반드시 deadline 안에 끝내도록 스케쥴링 해야 함</li>
</ul>
</li>
<li><strong>Soft real-rime computing</strong><ul>
<li>Soft real-time task는 일반 프로세스보다 높은 우선순위를 갖도록 함(반드시 deadline 안에 끝내지는 않아도 됨)</li>
</ul>
</li>
</ul>
</br>

<h3 id="thread-scheduling">Thread Scheduling</h3>
<hr>
<ul>
<li><strong>Local Scheduling</strong><ul>
<li>User level thread의 경우 사용자 수준의 thread library에 의해 어떤 thread를 스케쥴할지 결정</li>
</ul>
</li>
<li><strong>Global Scheduling</strong><ul>
<li>Kernel level thread의 경우 일반 프로세스와 마찬가지로 커넣의 단기 스케쥴러가 어떤 thread를 스케쥴할지 결정</li>
</ul>
</li>
</ul>
</br>

<h3 id="algorithm-evaluation">Algorithm Evaluation</h3>
<hr>
<p>CPU Scheduling Algorithm을 평가하는 방법</p>
<ul>
<li><p><strong>Queueing Models(이론적인 방법)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/c353de66-8ea1-4bac-90d8-a43e37782087/3.PNG" alt=""></p>
<ul>
<li>확률 분포로 주어지는 arrival rate와 service rate 등을 통해 각종 performance index 값 계산</li>
</ul>
</li>
<li><p><strong>Implementation &amp; Measurement(실제 구현, 측정)</strong></p>
<ul>
<li>실제 시스템에 알고리즘을 구현해 실제 작업에 대해 성능 측정, 비교</li>
</ul>
</li>
<li><p><strong>Simulation</strong></p>
<ul>
<li>알고리즘을 모의 프로그램으로 작성 후 trace(input data)를 입력으로 해 결과 비교(ex) SJF와 내가 만든 알고리즘을 비교)</li>
</ul>
</li>
</ul>
<h1 id="참고">참고</h1>
<p><a href="https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f">https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Process Management]]></title>
            <link>https://velog.io/@alwayslee_12/Process-Management</link>
            <guid>https://velog.io/@alwayslee_12/Process-Management</guid>
            <pubDate>Thu, 04 Nov 2021 06:19:17 GMT</pubDate>
            <description><![CDATA[<h3 id="프로세스-생성">프로세스 생성</h3>
<hr>
<ul>
<li><p><strong>Copy-on-write(COW) 기법:</strong> 자식 프로세스가 부모 프로세스를 공유만 하고 있다고, 수정 사항이 생기면 해당 부분만 copy하는 기법(<strong>복제 생성이 아닌 방식</strong>)</p>
</li>
<li><p>부모 프로세스가 자식 프로세스 생성(<strong>복제 생성</strong>)</p>
</li>
<li><p>프로세스의 트리(계층 구조) 형성</p>
</li>
<li><p>프로세스가 실행되기 위해서는 자원을 필요로 함</p>
<ul>
<li>운영체제로부터 받음</li>
<li>부모와 자원을 공유하는 경우도 있음</li>
</ul>
</li>
<li><p>자원의 공유</p>
<ul>
<li>부모 자식 간 모든 자원을 공유하는 모델</li>
<li>일부 공유하는 모델</li>
<li>공유하지 않는 모델(일반적)</li>
</ul>
</li>
<li><p>수행</p>
<ul>
<li>부모와 자식이 공존하며 수행되는 모델</li>
<li>자식이 종료될 때까지 부모가 기다리는 모델</li>
</ul>
</li>
<li><p>주소 공간</p>
<ul>
<li>자식은 부모의 공간을 복사(복제 생성되기 때문. 부모의 <strong>프로세스 문맥을 복사</strong>)</li>
<li>자식은 해당 공간에 새로운 프로그램 로드</li>
</ul>
</li>
<li><p>유닉스 예</p>
<ul>
<li><strong>fork()</strong> 시스템 콜이 새로운 프로세스 생성(복제 생성)</li>
<li><strong>exec()</strong> 시스템 콜을 통해 새로운 프로그램 메모리에 로드</li>
</ul>
</li>
</ul>
</br>

<h3 id="프로세스-종료">프로세스 종료</h3>
<hr>
<ul>
<li>프로세스가 마지막 명령을 수행한 후 운영체제에 이를 알림(<strong>exit</strong>. 자발적 프로세스 종료 시스템 콜)<ul>
<li>자식이 부모 프로세스에 output data를 보냄(<strong>wait</strong> 시스템 콜을 통해)</li>
<li>프로세스의 각종 자원들이 운영체제에 반납</li>
</ul>
</li>
<li>부모 프로세스가 자식 프로세스의 수행을 종료시킴(<strong>abort</strong>. 강제 종료 시스템 콜)<ul>
<li>자식이 할당해준 자원의 한계치를 넘어서는 경우</li>
<li>자식에게 할당된 태스크가 더 이상 필요하지 않은 경우</li>
<li>부모가 종료(<strong>exit</strong>)하는 경우<ul>
<li>운영체제는 부모 프로세스가 종료하는 경우 자식 프로세스를 종료시킴</li>
<li>종료는 단계적으로 이루어짐(손자 프로세스 종료 -&gt; 자식 프로세스 -&gt; 부모 프로세스 종료 순으로)</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="fork-시스템-콜">fork() 시스템 콜</h3>
<hr>
<ul>
<li><p>프로세스는 fork() 시스템 콜을 통해 만들어짐</p>
<pre><code class="language-c">int main(){
    int pid;
    printf(&quot;\n 부모 프로세스만 출력할 수 있는 부분&quot;);
    pid= fork(); //fork 시점 이후부터 자식 프로세스가 실행됨(부모 프로세스의 PC를 자식이 알고 있기                      때문에(문맥을 복사했기 때문))
                 //fork()의 리턴으로 pid가 오는데, 부모 프로세스의 pid는 양수이고, 자식 프로세스                    는 0(구분가능)
    if(pid==0)
        printf(&quot;\n Hello, I&#39;m Child Process&quot;);
    else if(pid&gt;0)
        printf(&quot;\n Hello I&#39;m Parent Process&quot;);
    ...
}</code></pre>
</li>
</ul>
</br>

<h3 id="exec-시스템-콜">exec() 시스템 콜</h3>
<hr>
<ul>
<li><p>프로세스는 exec() 시스템 콜을 통해 다른 프로그램을 실행할 수 있음</p>
<pre><code class="language-c">int main(){
    int pid;
    pid= fork();
    if(pid==0){
        printf(&quot;Hello I&#39;m Child&quot;);
        execlp(&quot;/bin/date&quot;, &quot;/bin/date&quot;,(char*)0);//이 함수가 exec() 시스템 콜을 함
                                                  //자식 프로세스는 date라는 프로그램을 덮                                                     어씌우게 됨(새로운 프로그램 실행).                                                         자식 프로세스는 해당 프로그램이 종료되면                                                  수행을 다함. 다시 이곳으로 돌아올 수는 없음
    }
    else if(pid&gt;0) printf(&quot;Hello I&#39;m parent&quot;);
    ...
}</code></pre>
</li>
</ul>
</br>

<h3 id="wait-시스템-콜">wait() 시스템 콜</h3>
<hr>
<ul>
<li><p>자식 프로세스가 종료될 때까지 부모 프로세스는 sleep(block) 상태로 만듦</p>
</li>
<li><p>자식 프로세스가 종료되면 부모 프로세스를 깨움(ready 상태)</p>
<pre><code class="language-c">int main(){
    int childPID;

    childPID= fork();

    if(childPID==0){
        ...
    }else{
        wait()
    }
    ...
}</code></pre>
</li>
<li><p>ex) 리눅스의 명령 프롬프트에서 특정 프로그램의 이름을 입력하면, 명령 프롬프트라는 부모 프로세스가 특정 프로그램이라는 자식 프로세스를 생성하고 해당 프로그램이 종료될때까지 wait 했다가 다시 명령줄을 입력할 수 있게 함(자식 프로세스 종료전까지는 명령줄 입력 x)</p>
</li>
</ul>
</br>

<h3 id="exit-시스템-콜">exit() 시스템 콜</h3>
<hr>
<ul>
<li>프로세스 종료 시 사용하는 시스템 콜</li>
<li><strong>자발적 종료</strong><ul>
<li>마지막 명령 수행 후 exit() 시스템 콜 명시적으로 입력</li>
<li>또는, 함수의 리턴 위치에 컴파일러가 넣어줌</li>
</ul>
</li>
<li><strong>비자발적 종료</strong><ul>
<li>부모 프로세스가 자식 프로세스 강제 종료시킴<ul>
<li>자식 프로세스가 할당된 자원 한계치 초과</li>
<li>자식에게 할당된 태스크가 불필요해진 경우</li>
</ul>
</li>
<li>키보드로 kill, break 등 명령을 입력한 경우</li>
<li>부모가 종료되는 경우<ul>
<li>자식 프로세스들을 먼저 종료 후 부모 프로세스 종료(순차적으로. 트리의 밑에서 위로)</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h3 id="프로세스-간-협력">프로세스 간 협력</h3>
<hr>
<ul>
<li><p><strong>독립적 프로세스</strong></p>
<ul>
<li>프로세스는 각자의 주소 공간을 가지고 수행되므로, 원칙적으로는 하나의 프로세스가 다른 프로세스의 수행에 영향을 끼치지 않음</li>
</ul>
</li>
<li><p><strong>협력 프로세스</strong></p>
<ul>
<li>프로세스 협력 메커니즘을 통해 하나의 프로세스가 다른 프로세스의 수행에 영향을 미칠 수 있음</li>
</ul>
</li>
<li><p><strong>프로세스 간 협력 메커니즘(IPC: Interprocess Communication)</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/3c2833d6-c104-4a8c-befa-2885c835333f/1.PNG" alt=""></p>
<ul>
<li><strong>메세지 전달 방법</strong><ul>
<li><strong>Message Passing:</strong> <strong>커널을 통해</strong> 메세지 전달<ul>
<li><strong>Direct Communication:</strong> 통신하려는 프로세스의 이름을 명시적으로 표시</li>
<li><strong>Indirect Communication:</strong> mailbox(or port)를(커널에 mailbox가 있음) 통해 메세지 간접 전달</li>
</ul>
</li>
</ul>
</li>
<li><strong>주소 공간 공유 방법(커널에 공유하는 영역에 대해 알리는 시스템 콜을 먼저 해야함)</strong><ul>
<li><strong>Shared Memory:</strong> 서로 다른 프로세스 간 일부 주소 공간을 공유</li>
</ul>
</li>
</ul>
</li>
</ul>
</br>

<h1 id="참고">참고</h1>
<p><a href="https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f">https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TCP/IP]]></title>
            <link>https://velog.io/@alwayslee_12/TCPIP</link>
            <guid>https://velog.io/@alwayslee_12/TCPIP</guid>
            <pubDate>Tue, 02 Nov 2021 13:40:50 GMT</pubDate>
            <description><![CDATA[<p>TCP/IP는 인터넷을 사용하기 위해 필요한 프로토콜이다.</p>
<h3 id="특징">특징</h3>
<hr>
<ul>
<li>각각 네트워크에 접속되는 호스트들은 고유의 주소를 가져, 자신이 속한 네트워크뿐 아니라 다른 네트워크에 연결되어있는 호스트와도 데이터를 주고받을 수 있음</li>
<li>호스트들의 소유 주소는 Internet Network Information Center(InterNIC)라는 단체에서 관리 분배</li>
<li>기본적으로 TCP/IP는 랜카드에 세팅되어 있음</li>
</ul>
</br>

<p><strong>TCP/IP 계층 구조</strong></p>
<ul>
<li>총 4계층</li>
<li>어플리케이션 계층(HTTP, FTP 등), 트랜스포트 계층(TCP, UDP), 인터넷 계층(IP), 네트워크 엑세스 계층(Network Driver, Hardware 등)</li>
</ul>
</br>

<h3 id="ip-주소">IP 주소</h3>
<hr>
<ul>
<li>인터넷을 사용하는 호스트에게 고유하게 주어지는 주소</li>
<li>만약, 동일한 IP 주소를 가진 사용자 둘이 있다면, 둘중 한명은 인터넷 접속 불가</li>
<li>NIC(Network Information Center)라는 기관이 IP 주소를 관리 분배</li>
</ul>
</br>

<p><strong>10.139.4.36?</strong></p>
<p>위는 IP 주소의 예이다.</p>
<p>IP 주소는 원래 32자리의 2진수로 만들어져있으나, 사람이 보기 쉽게 위와같이 십진수로 표현한다.</p>
<p><code>.</code>으로 구분된 각 십진수 자리는 2진수 8자리로 되어있다.(8자리마다 점을 찍어 표현하고, 한 자리당 0~255까지 표현 가능)</p>
<p>최대 할당받을 수 있는 IP의 수는 2^32(42억 9496만 7296)인데, 인터넷 사용 인구수가 늘어나 바닥이 났고, 더 많은 IP 주소를 부여하기 위해 IPv6가 나옴</p>
<p>IPv6는 128개의 이진수로 이루어져있어 2^128의 IP 주소를 할당할 수 있음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Process]]></title>
            <link>https://velog.io/@alwayslee_12/Process</link>
            <guid>https://velog.io/@alwayslee_12/Process</guid>
            <pubDate>Tue, 02 Nov 2021 13:00:57 GMT</pubDate>
            <description><![CDATA[<p>프로세스는 실행중인 프로그램이다.</p>
<h3 id="프로세스의-문맥context">프로세스의 문맥(Context)</h3>
<hr>
<p>프로세스의 현재 상태를 나타내는 아래와 같은 것들을 프로세스의 문맥이라 한다. </p>
<p>프로세스들이 번갈아가며 실행되기때문에 프로세스의 문맥에 대한 백업을 필수이다.(시분할, 멀티태스킹 환경 등에서)</p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/188fb470-4557-4972-83ae-3be62aee79b7/os1.JPG" alt=""></p>
<ul>
<li>CPU 수행 상태를 나타내는 하드웨어 문맥<ul>
<li>Program Counter</li>
<li>각종 Register</li>
</ul>
</li>
<li>프로세스의 주소 공간<ul>
<li>code, data, stack(어떤 코드가 실행되고 있고, 어떤 데이터가 저장되어있고, 어떤 함수가 스택에 있는지)</li>
</ul>
</li>
<li>프로세스 관련 커널 자료 구조<ul>
<li>PCB(운영체제가 프로세스 각각을 관리하기 위해 자신의 data 영역에 생성한 자료구조)</li>
<li>Kernel Stack(시스템 콜을 한 프로세스 별로 커널 함수를 구분지어 스택에 저장)</li>
</ul>
</li>
</ul>
</br>

<h3 id="pcbprocess-control-block">PCB(Process Control Block)</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/8c19f24d-dfe0-429d-b91e-c6bbf5201f34/os4.JPG" alt=""></p>
<ul>
<li><p>운영체제가 각 프로세스를 관리하기 위해 프로세스별로 정보를 자료구조로 만들어 자신의 data 영역에 저장</p>
</li>
<li><p>구성요소</p>
<p>운영체제가 관리상 사용하는 정보</p>
<ul>
<li>Process State, Process ID</li>
<li>Scheduling Information, Priority</li>
</ul>
<p>CPU 수행 관련 하드웨어 값</p>
<ul>
<li>Program Counter, Registers</li>
</ul>
<p>메모리 관련</p>
<ul>
<li>Code, Data, Stack의 위치 정보(메모리의 어디에 위치해 있나)</li>
</ul>
<p>파일 관련</p>
<ul>
<li>프로세스가 사용하고 있는 파일 정보</li>
</ul>
</li>
</ul>
</br>

<h3 id="프로세스의-상태">프로세스의 상태</h3>
<hr>
<p>프로세스는 상태가 변경이 되며 수행된다.</p>
<ul>
<li><strong>Running:</strong> CPU를 점유하고 Instruction을 수행하는 상태</li>
<li><strong>Ready:</strong> CPU를 점유하기 위해 대기하는 상태(프로세스가 실행되기 위한 모든 조건을 충족한)</li>
<li><strong>Blocked(Wait, Sleep):</strong> CPU를 점유하더라도 당장 Instruction을 수행할 수 없는 상태. 프로세스가 요청한 event(I/O 작업 등)가 완료되기까지 기다리는 상태<ul>
<li>ex) 디스크에서 파일을 읽어와야 하는 경우</li>
</ul>
</li>
<li><strong>Suspended(stopped):</strong> 외부적인 이유로 프로세스의 수행이 정지된 상태 프로세스가 통째로 <code>swap out</code> 됨<ul>
<li>ex) 사용자가 프로그램을 일시 정지시킨 경우(break key. 사람이 다시 재개시키면 위 상태로 돌아갈 수 있음)</li>
<li>중기 스케쥴러에 의해(메모리에 너무 많은 프로세스가 로드되어있을 때, 프로세스 하나를 통째로 메모리에서 디스크로 내보냄)</li>
</ul>
</li>
<li><strong>New:</strong> 프로세스 생성중인 상태(Optional)</li>
<li><strong>Terminated:</strong> 실행이 끝난 상태(Optional)</li>
</ul>
</br>

<p><strong>프로세스 상태도</strong></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/d13bb8a2-1577-40f7-bb81-cec2034b5a61/os2.JPG" alt=""></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/f527a546-de98-4f61-b7ef-e8d6fafd12d2/os5.JPG" alt=""></p>
<p><img src="https://images.velog.io/images/alwayslee_12/post/a32fd5ca-78f0-447f-a4b3-963116db970a/os3.JPG" alt=""></p>
<p>하드웨어 자원(I/O Device)뿐만아니라 소프트웨어 자원인 공유데이터를 사용할때도 Resource Queue(운영체제가 자신의 주소공간 중 data 영역에 큐 자료구조를 만들어 놓고, 프로세스의 상태를 바꿔가면서 CPU 줬다뺏는다)에서 대기하고 프로세스는 <code>blocked</code> 상태가 된다.</p>
</br>

<h3 id="문맥-교환context-switch">문맥 교환(Context Switch)</h3>
<hr>
<ul>
<li><strong>CPU</strong>를 <strong>한 프로세스에서 다른 프로세스로 넘기는 과정</strong></li>
<li>CPU가 다른 프로세스에 넘어갈 때 운영체제는 다음과 같은 작업을 수행<ul>
<li>CPU를 넘기는 프로세스의 상태를 해당 프로세스의 PCB에 저장</li>
<li>CPU를 받는 프로세스의 상태를 해당 프로세스의 PCB에서 읽어옴</li>
</ul>
</li>
<li>문맥 교환은 오버헤드가 큰 작업(CPU를 넘기는 프로세스의 Cache Memory를 모두 비워야 하기때문(<strong>Cache Memory Flush</strong>))</li>
</ul>
</br>

<h3 id="프로세스를-스케쥴링-하기-위한-큐">프로세스를 스케쥴링 하기 위한 큐</h3>
<hr>
<p>프로세스는 각 큐들을 오가며 수행됨</p>
<ul>
<li><strong>Job Queue:</strong> 현재 시스템 내에 있는 모든 프로세스의 집합</li>
<li><strong>Ready Queue:</strong> 현재 메모리 내에 있으면서 CPU를 점유하기 위해 대기하는 프로세스의 집합</li>
<li><strong>Device Queue:</strong> I/O Device의 처리를 기다리는 프로세스의 집합</li>
</ul>
</br>

<h3 id="스케쥴러">스케쥴러</h3>
<hr>
<ul>
<li><strong>장기 스케쥴러(Job Scheduler)</strong><ul>
<li>시작 프로세스 중 어떤 것들을  ready queue로 보낼지 결정</li>
<li>프로세스에(프로세스는 메모리에 로드되어야 CPU 점유 권한을 얻을 수 있음) 메모리(나 각종 자원)을 <strong>주는 문제</strong></li>
<li>메모리에 로드되는 프로세스의 수를 제어(메모리에 많은 프로세스(프로세스별로 차지하는 공간이 적어지기에 필요한 데이터가 없으면, I/O를 하러가야함)가 로드되어도, 적은 프로세스(CPU 유휴시간 김)가 로드되어도 컴퓨터 성능에 문제가 생김)</li>
<li>시분할 시스템(대부분의 시스템)에는 장기 스케쥴러없이 모든 프로세스를 메모리어 로드시킴(무조건 ready)</li>
</ul>
</li>
<li><strong>단기 스케쥴러(CPU Scheduler)</strong><ul>
<li>어떤 프로세스를 다음번에 실행시킬지 결정</li>
<li>프로세스에 CPU를 주는 문제</li>
<li>빠름(milisecond 단위)</li>
</ul>
</li>
<li><strong>중기 스케쥴러(Swapper)</strong><ul>
<li>(일단 모든 프로세스를 올려놓고 메모리에 로드된 프로세스 수가 많다싶으면)일부 프로세스를 통째로 메모리에서 디스크로 내보냄</li>
<li>프로세스를 메모리에서 디스크로 내보내는 문제(<strong>뺏는 문제</strong>)</li>
<li>메모리의 로드되는 프로세스 수 제어</li>
<li>대부분의 시스템(현대의 운영체제)</li>
</ul>
</li>
</ul>
</br>    

<h3 id="thread">Thread</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/7b8efa72-005e-4f48-b13b-134c025b4efb/image.png" alt="">
만약 동일한 일을 수행하는 프로세스가 여러개 있다고 하면, 각 프로세스들의 주소공간이 만들어지고 메모리에 주소공간들이 로드되고, PCB가 여러개 생성되어 커널 주소공간의 data 영역에 로드된다. 이는 메모리 낭비이며, 이러한 낭비를 막기위해 Thread가 있다. 
Thread를 이용하면, 메모리에 각각 주소공간들이 로드되는 것이 아니라, 주소공간 하나만 로드되고, 하나의 code 영역을 공유하면서 code 영역 내 다른 Instruction을 수행할 수 있다.
각각의 프로세스가 수행하는 Instruction에 대한 정보(Program Counter, Registers)를 PCB의 Thread 영역에 저장한다.(또한, Stack 영역에 Thread 별로 함수 호출 정보를 쌓는다)
<strong>즉, Thread는 프로세스 하나에 CPU 수행 단위만 여러개 두는 것을 말한다.</strong>(프로세스 하나에서 공유할 수 있는 것을 최대한 공유하고, CPU 수행과 관련된 정보만 별도로 가진다)</p>
</br>

<p><strong>Thead의 구성</strong></p>
<ul>
<li>Program Counter</li>
<li>Register Set</li>
<li>Stack</li>
</ul>
</br>

<p><strong>Thread끼리 공유하는 부분(task)</strong></p>
<ul>
<li>Code Section</li>
<li>Data Section</li>
<li>OS Resources</li>
</ul>
</br>

<p><strong>Thread 사용 장점</strong></p>
<ul>
<li>다중 스레드로 구성된 태스크 구조에서 하나의 스레드가 blocked된 상태여도 동일한 태스크 내 다른 스레드가 실행되어 처리를 빠르게 할 수 있음(응답시간 빨라짐. 웹 포털에 접속할 때 페이지를 읽어오는 동안 프로세스가 blocked되지 않게, 다른 스레드가 HTML 문서 정도를 화면에 띄워준다)</li>
<li>동일한 일을 수행하는 다중 스레드가 협력해 높은 처리율(스레드를 생성하거나 다른 스레드에게 CPU를 전달하는 것은 크게 오버헤드가 없기때문)과 성능 향상, 자원 절약(메모리)</li>
<li>병렬성을 높일 수 있음(CPU가 여러개 있는 경우. 처리가 빠름)</li>
</ul>
</br>

<p><strong>스레드 구현 방식</strong></p>
<ul>
<li>커널 스레드: 스레드가 운영체제의 지원을 받음. 운영체제가 하나의 스레드에서 다른 스레드로 CPU가 넘어가는 것을 관리</li>
<li>유저 스레드: 라이브러리를 통해 지원. 유저 프로그램자체가 여러 스레드를 관리(라이브러리의 지원을 받아). 커널 스레드에 비해 구현 상 제약이 있을 수 있음</li>
</ul>
</br>

<h1 id="참고">참고</h1>
<p><a href="https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f">https://core.ewha.ac.kr/publicview/C0101020140307151724641842?vmode=f</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Subnet]]></title>
            <link>https://velog.io/@alwayslee_12/Subnet</link>
            <guid>https://velog.io/@alwayslee_12/Subnet</guid>
            <pubDate>Mon, 01 Nov 2021 07:11:04 GMT</pubDate>
            <description><![CDATA[<h3 id="16진수의-이해">16진수의 이해</h3>
<hr>
<p>0= 0, 1= 1, 2= 2, 3= 3, 4= 4, </p>
<p>5= 5, 6= 6, 7= 7, 8= 8, 9= 9, </p>
<p>10= a, 11= b, 12= c, 13= d</p>
<p>14= e, 15= f</p>
<p>십진수 245= 2 x 10^2+ 4 x 10^1 + 5 x 10^0= 245</p>
<p>16진수 245= 2 x 16^2 x 4 x 16^1 + 5 x 16^0= 579
</br></p>
<p><strong>2진수와 16진수 변환</strong>
01011110 -&gt; 이진수 4자리씩 끊어서 변환 -&gt; 0101 1110 -&gt; 5 e</p>
<p>ff -&gt; 16진수 한 자리 당 2진수 4자리로 변환 -&gt; 1111 1111 </p>
<h3 id="ip-주소에서의-이진수와-16진수">IP 주소에서의 이진수와 16진수</h3>
<hr>
<p>150.100.10.255 -&gt; 1001 0110. 0110 0100. 0000 1010. 1111 1111 -&gt; 96. 64. 0a. ff(10진수 -&gt; 이진수 -&gt; 16진수. 다 같은 숫자이다. 표현 방식이 다를 뿐)</p>
<h3 id="서브넷팅이-없다면">서브넷팅이 없다면?</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/78c60483-920f-4182-a59b-ce64246cbd71/1.JPG" alt=""></p>
<p>Network 150.150.0.0 -&gt; Class B. 2^16개만큼의(뒤에 두 0.0이 -&gt; 0000 0000.0000 0000 16자리 이진수이기때문) 호스트를 가짐 -&gt; 관리가 어렵고, 브로드캐스트 문제 발생</p>
</br>

<p><strong>서브넷팅 하는 이유</strong></p>
<ul>
<li>네트워크를 체계적으로 관리하기 위함(나누기때문에)</li>
<li>네트워크를 나누기에 보안성이 좋아짐</li>
<li>브로드캐스트를 줄일 수 있음(브로드캐스트 도메인이 작아져 영향을 줄일 수 있음)</li>
<li>밖에서 볼 때는 서브넷팅 한 부분이 아닌 네트워크 주소만 보이기 때문에 트래픽을 줄일 수 있음(네트워크 주소에만 트래픽을 보내기때문에)</li>
<li>밖에서 볼 때 네트워크 주소만 보임으로써 라우팅 정보를 줄일 수 있음(보안성 향상)</li>
</ul>
</br>

<h3 id="서브넷-마스크를-한-네트워크">서브넷 마스크를 한 네트워크</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/acabafde-e675-48ce-9964-ad9aa4ef1274/2.JPG" alt=""></p>
<ul>
<li>클래스 B 네트워크 150.150.0.0을 서브네팅해서 사용</li>
<li>서브넷 마스크는 255.255.255.0(3번째 자리까지가 네트워크 주소)</li>
<li>나누어진 서브넷 간 통신은 라우터를 거쳐야만 함</li>
</ul>
</br>

<h3 id="서브넷-마스크-후-라우터-구성">서브넷 마스크 후 라우터 구성</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/b90783e2-21b1-4af7-ab73-22b8443863cd/3.JPG" alt=""></p>
<p>Network 172.16.0.0을 서브네팅 한 것(Class B)</p>
<p>172.16 (Network)</p>
<p>2 (Subnet)</p>
<p>160 (Host)</p>
</br>

<p>Routing Table을 보면, 두 개의 네트워크로 나눠진 것을 볼 수 있다.</p>
</br>

<h3 id="디폴트-서브넷-마스크">디폴트 서브넷 마스크</h3>
<hr>
<p>서브넷 마스킹을 안해도 가지고 있는 서브넷 마스크</p>
<p>210.100.100.1의 디폴트 서브넷 마스크는?</p>
<p>-&gt; 255.255.255.0(Class C)</p>
<p>150.100.10.20의 디폴트 서브넷 마스크는?</p>
<p>-&gt; 255.255.0.0(Class B)</p>
<p>10.1.1.100의 디폴트 서브넷 마스크는?</p>
<p>-&gt; 255.0.0.0(Class A)</p>
</br>

<h3 id="ip-주소에서-네트워크-주소-찾기">IP 주소에서 네트워크 주소 찾기</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/30846669-e381-44e8-a78a-71fd828e6fda/4.JPG" alt=""></p>
<p>IP Address와 Subnet Mask를 AND하면 네트워크 주소를 구할 수 있음
</br></p>
<h3 id="서브넷-마스크-만들기">서브넷 마스크 만들기</h3>
<hr>
<p><img src="https://images.velog.io/images/alwayslee_12/post/c4f483d8-c0c1-44e0-9000-ab72bbf8d695/5.JPG" alt=""></p>
<p>8 bit Subnet Masking을 한다는 말은 추가 8 bit를 더 서브넷 하겠다는 소리(Network 부분과 Host 부분 중 호스트 부분의 왼쪽 비트부터 사용)</p>
<h3 id="서브넷-마스크-특징">서브넷 마스크 특징</h3>
<hr>
<ul>
<li><p>디폴트 서브넷 마스크 중 호스트 비트를 사용하고 호스트 비트의 맨 왼쪽부터 씀</p>
</li>
<li><p>서브넷 마스크는 1이 연속으로 나와야 함(중간에 0이 끼면 안됨)</p>
<p>ex) 1111 1111.1111 1111.1100 1100(서브넷 마스크가 될 수 없음)</p>
<p>ex) 255.255.10.0 (불가능)</p>
<p>​      255.255.199.0 (불가능)</p>
<p>​      255.255.240.0(가능)</p>
</li>
</ul>
</br>

<h3 id="test">Test</h3>
<hr>
<p>172.16.2.10 -&gt; 255.255.255.0(서브넷) -&gt; Class B -&gt; 172.16.2.0(네트워크 주소)</p>
<p>10.6.24.20 -&gt; 255.255.0.0 -&gt; Class A -&gt; 10.6.0.0</p>
<p>172.30.36.12 -&gt; 255.255.255.0 -&gt; Class B -&gt; 172.30.36.0</p>
<p>201.222.10.60 -&gt; 255.255.255.248 -&gt; Class C -&gt; 201.222.10.56</p>
<p>15.18.192.6 -&gt; 255.255.0.0 -&gt; Class A -&gt; 15.18.0.0</p>
<p>130.15.121.13 -&gt; 255.255.255.0 -&gt; Class B -&gt; 130.15.121.0</p>
<p>153.70.100.2 -&gt; 255.255.255.192 -&gt; Class B -&gt; 153.70.100.0</p>
</br>

<p><strong>서브넷 만들기</strong>
<img src="https://images.velog.io/images/alwayslee_12/post/65af7007-270c-4b52-8b25-e7031f8b25dd/7.JPG" alt=""></p>
<p>20개 정도의 서브넷, 각 네트워크에는 5개까지의 호스트</p>
<p>Class C 201.222.5.0</p>
<p>디폴트 서브넷 마스크= 255.255.255.0</p>
<p>20개 정도의 서브넷이 필요하다 했으므로, 호스트 비트에서 5비트를 사용(2^5= 32)</p>
<p>각 네트워크는 5개까지의 호스트가 필요하다 했으므로, 호스트 비트에서 남은 3비트를 사용(2^3=8)</p>
<p>서브넷 마스크= 255.255.255.248
<img src="https://images.velog.io/images/alwayslee_12/post/15e2cc5e-80c3-4293-8fae-ab458e165c7a/8.JPG" alt=""></p>
<p>호스트 주소가 모두 0이면, 네트워크 주소. 호스트 주소가 모두 1이면, 브로드캐스트 주소</p>
<p>호스트 주소 범위= 네트워크 주소+1 ~ 브로드캐스트 주소-1</p>
<p>201.222.5.0(서브네팅 한 네트워크 주소): 201.222.5.1~201.222.5.6(호스트 주소 범위)</p>
<p>201.222.5.8: 201.222.5.9~201.222.5.14</p>
<p>201.222.5.16: 201.222.5.17~201.222.5.22</p>
<p>​                 .</p>
<p>​                 .</p>
<p>​                 .</p>
<p>201.222.5.224: 201.222.5.225~201.222.5.230</p>
<p>201.222.5.231: 201.222.5.232~201.222.5.238</p>
<p>201.222.5.240: 201.222.5.241~201.222.5.246</p>
<p>201.222.5.248: 201.222.5.249~201.222.5.254</p>
<h1 id="참고">참고</h1>
<p><a href="https://bm.cyber.co.kr/mypage.php?action=view&amp;no=626&amp;uidc=80546">https://bm.cyber.co.kr/mypage.php?action=view&amp;no=626&amp;uidc=80546</a></p>
]]></description>
        </item>
    </channel>
</rss>