<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Yoo 스터디</title>
    <link>https://doubleyoo.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 21 Aug 2026 15:28:16 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>yooja_tea</managingEditor>
    <image>
      <title>Yoo 스터디</title>
      <url>https://tistory1.daumcdn.net/tistory/4637527/attach/b304fb4dc7dc4fa09ba2b63d7bd251cb</url>
      <link>https://doubleyoo.tistory.com</link>
    </image>
    <item>
      <title>[CS 스터디] 스택 오버플로우 (Stack Overflow), 힙 오버플로우 (Head Overflow)</title>
      <link>https://doubleyoo.tistory.com/63</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.tcpschool.com/c/c_memory_stackframe&quot;&gt;참고: TCP 스쿨 - 스택&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://je0n-je.tistory.com/12&quot;&gt;참고: 버퍼 오버플로우&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 주소 공간에 대해 공부하며 스택 오버플로우, 힙 오버플로우에 대한 궁금증이 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리에서 스택 영역은 큰 주소값에서 작은 주소값으로 할당되고, 힙 영역은 작은 주소값에서 큰 주소값으로 할당된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(이는 버퍼 오버플로우를 막기 위해서 이다. 스택 영역 뒤에는 커널 영역이 있는데, 만약 스택 영역을 초과하는 크기의 데이터를 저장하면 커널 영역을 침범해 데이터를 조작하는 등 해킹이 일어날 수 있다. 때문에 스택 영역은 큰 주소에서 작은 주소로 메모리를 할당한다.)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;버퍼 오버플로우&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연속된 메모리 공간을 사용하는 프로그램이 할당된 메모리 영역을 벗어난 위치에서 데이터를 읽거나 쓰려고 할 때 발생하는 것&lt;/li&gt;
&lt;li&gt;버퍼 오버플로우가 발생하면 프로그램이 오작동하거나, 공격자가 임의의 코드를 삽입시켜 해킹할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스택 오버플로우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 영역은 함수의 호출과 함께 할당되고, 함수가 종료하면 해제되는 공간이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 프로그램에서 함수의 재귀 호출이 무한히 반복되면 스택 오버플로우가 발생할 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;함수의 재귀 호출이 무한히 발생한다.&lt;/li&gt;
&lt;li&gt;스택 프레임이 스택 영역에 계속 쌓이게 된다.&lt;/li&gt;
&lt;li&gt;스택 영역의 모든 공간이 찼을 때, 다시 함수를 호출하게 되면 그때 생기는 스택 프레임은 스택 영역을 넘어가서 저장하게 된다.&lt;/li&gt;
&lt;li&gt;이렇게 되면 해당 프로그램은 오작동을 하거나 보안상 큰 취약점을 가지게 된다. 따라서 프로그래밍 언어에서는 스택 오버플로우가 발생하면 에러를 발생시키고 프로그램을 강제 종료 시킨다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HfaPZ/btsopCCqfyM/XXvBswbDuSrkkA8pQtrWK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HfaPZ/btsopCCqfyM/XXvBswbDuSrkkA8pQtrWK1/img.png&quot; data-alt=&quot;http://www.tcpschool.com/c/c_memory_stackframe&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HfaPZ/btsopCCqfyM/XXvBswbDuSrkkA8pQtrWK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHfaPZ%2FbtsopCCqfyM%2FXXvBswbDuSrkkA8pQtrWK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;659&quot; height=&quot;435&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;698&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;http://www.tcpschool.com/c/c_memory_stackframe&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;힙 오버플로우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙 영역은 런타임 시에 애플리케이션에 의해 동적으로 할당, 해제되는 메모리 영역이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙에 문자열, 객체 등이 저장될 때 미리 지정한 크기의 힙 메모리 사이즈를 초과하여 저장될 경우 버퍼 오버플로우가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ex) 악의적으로 힙 영역을 벗어나 데이터를 변경하거나 함수 주소를 변경&lt;/p&gt;</description>
      <category>CS</category>
      <category>스택 오버플로우</category>
      <category>힙 오버플로우</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/63</guid>
      <comments>https://doubleyoo.tistory.com/63#entry63comment</comments>
      <pubDate>Fri, 21 Jul 2023 13:57:36 +0900</pubDate>
    </item>
    <item>
      <title>[CS 스터디] PCB (Process Control Block)</title>
      <link>https://doubleyoo.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/gyoogle/tech-interview-for-developer&quot;&gt;참고: tech-interview-for-developer&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Process Management&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제는 여러 개의 프로세스의 실행 순서를 관리하고, CPU 등 자원을 배분하고 관리해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 각 프로세스를 구분할 수 있어야 관리가 가능하다. 각 프로세스의 정보를 &lt;b&gt;Process metadata라고&lt;/b&gt; 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Process Metadata&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Process ID (PID) : 프로세스를 식별하기 위한 고유 번호&lt;/li&gt;
&lt;li&gt;Process State&lt;/li&gt;
&lt;li&gt;Process Priority&lt;/li&gt;
&lt;li&gt;CPU Register&lt;/li&gt;
&lt;li&gt;Owner&lt;/li&gt;
&lt;li&gt;CPU Usage&lt;/li&gt;
&lt;li&gt;Memory Usage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Process Metadata는 프로세스가 생성되면 PCB에 저장된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PCB (Process Control Block)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Process metadata를 저장하는 블록&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 PCB 안에는 한 프로세스의 정보가 담긴다.&lt;/li&gt;
&lt;li&gt;프로세스 생성 시 커널 영역에 생성되어 프로세스를 식별하는 정보로 사용한다. 프로세스가 종료되면 폐기된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로그램 실행 &amp;rarr; 프로세스 생성 &amp;rarr; 프로세스 주소 공간 생성 (코드, 데이터, 스택) &amp;rarr; 해당 프로세스의 메타데이터가 PCB에 저장&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdU1QN/btsopBPVsDT/3HaG9LSypiVU08iYRHMUo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdU1QN/btsopBPVsDT/3HaG9LSypiVU08iYRHMUo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdU1QN/btsopBPVsDT/3HaG9LSypiVU08iYRHMUo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdU1QN%2FbtsopBPVsDT%2F3HaG9LSypiVU08iYRHMUo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;487&quot; height=&quot;362&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PCB가 필요한 이유?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU는 프로세스의 상태에 따라 교체 작업이 이뤄진다. (인터럽트가 발생해 할당받은 프로세스가 waiting 상태가 되고 다른 프로세스를 running으로 바꿔 실행할 때)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이때 현재 waiting 상태로 변한 프로세스에 관한 저장 값을 PCB에 저장해둔다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PCB 관리 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Linked List 방식으로 관리&lt;/li&gt;
&lt;li&gt;PCB List Head에 PCB들이 생성될 때마다 붙게 된다. = &lt;b&gt;프로세스가 생성되면 해당 PCB가 생성되어 리스트에 붙게 되고, 프로세스 완료 시 리스트에서 제거한다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;주소값으로 연결되어 있는 연결 리스트로 삽입, 삭제가 용이하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Context Switching&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CPU가 수행 중인 프로세스를 변경할 때 이전 프로세스 상태(context)를 PCB에 보관하고, 새로운 프로세스의 정보를 PCB에서 읽어 레지스터에 적재하는 과정&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보통 인터럽트 발생, 실행 중인 CPU 사용 허가 시간을 모두 소모, 입출력을 위해 대기해야 하는 경우 발생한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;즉,&lt;span style=&quot;background-color: #f6e199;&quot;&gt; 프로세스가 Ready &amp;rarr; Running, Running &amp;rarr; Ready, Running &amp;rarr; Waiting 상태 변경 시 발생&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Multi Processing을 위해 필수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Context Switching OverHead&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context Switching 동안에는 CPU가 작업을 할 수 없다. 때문에 잦은 context switching은 성능에 좋지 않다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스의 레지스터 개수, 데이터의 종류 등에 영향을 받는다.&lt;/li&gt;
&lt;li&gt;성능 개선을 위해 Conext의 데이터 양을 줄여야 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;thread 간에는 공유하는 메모리 영역이 있기 때문에 프로세스에 비해 context switching 비용이 적다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS</category>
      <category>pcb</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/62</guid>
      <comments>https://doubleyoo.tistory.com/62#entry62comment</comments>
      <pubDate>Fri, 21 Jul 2023 01:22:47 +0900</pubDate>
    </item>
    <item>
      <title>[CS 스터디] 시스템 콜, fork() wait() exec()</title>
      <link>https://doubleyoo.tistory.com/61</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dar0m.tistory.com/264&quot;&gt;참고: OS - 시스템 호출&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://didu-story.tistory.com/311&quot;&gt;참고: 시스템콜, 시스템 호출이란&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제는 사용자가 컴퓨터를 효과적으로 사용하도록 컴퓨팅 자원을 직접적으로 관리한다. 따라서 응용 프로그램은 운영체제가 제공하는 인터페이스를 통해서 컴퓨팅 자원을 이용하는데, 이러한 인터페이스를 &lt;b&gt;시스템 콜&lt;/b&gt;이라고 부른다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;커널 모드 vs 사용자 모드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제는 &lt;b&gt;커널 모드(Kernel Mode)&lt;/b&gt;와 &lt;b&gt;사용자 모드(User Mode)&lt;/b&gt;로 나뉘어 구동된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Kernel Mode&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운영체제가 CPU를 사용하는 모드, 하드웨어를 제어하는 명령어 (Privileged Instructions)를 실행&lt;/li&gt;
&lt;li&gt;&lt;s&gt;PC 레지스터가 운영체제가 존재하는 부분을 가리킴&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;시스템 콜을 통해 커널 모드로 전환된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;User Mode&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 애플리케이션 코드가 실행되는 모드&lt;/li&gt;
&lt;li&gt;&lt;s&gt;PC 레지스터가 사용자 프로그램이 올라가 있는 메모리 위치를 가리킴&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;해당 모드에서는 하드웨어 (디스크, I/O 등)에 접근할 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt; &amp;nbsp;&lt;b&gt;시스템 콜이 필요한 이유?&lt;/b&gt;&lt;br /&gt;응용 프로그램으로 대표되는 유저 프로세스는 유저 모드에서 실행되기 때문에 커널의 기능을 직접 사용할 수 없다. 커널 모드로 전환 후에 해당 작업을 수행할 수 있다. 만약 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;해커가 악의적으로 하드웨어를 조작하거나, 사용자가 실수로 하드웨어를 조작하는 경우 시스템 전체에 큰 장애가 발생할 수 있다&lt;/span&gt;. 이를 막기 위해 이러한 명령들은 커널 모드에서만 실행할 수 있도록 설계되었다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;System Call&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 콜은 이러한 커널 모드의 기능을 사용자 모드가 사용 가능 하게 해 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, 응용 프로그램이 하드웨어에 접근해 필요한 기능을 사용할 수 있도록 해주는 인터페이스&lt;/b&gt;이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그래밍 언어는 시스템 콜을 편리하게 사용하기 위한 수단으로 API를 제공한다.&lt;/li&gt;
&lt;li&gt;각 시스템 콜에는 번호가 할당되고, 시스템 콜 인터페이스는 시스템 콜 번호와 시스템 콜 핸들러 함수 주소로 구성되는 시스템 콜 테이블을 유지한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dD1bhs/btsoqPmLLo0/sAjzAsuUk1YHnnmI2MOK51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dD1bhs/btsoqPmLLo0/sAjzAsuUk1YHnnmI2MOK51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dD1bhs/btsoqPmLLo0/sAjzAsuUk1YHnnmI2MOK51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdD1bhs%2FbtsoqPmLLo0%2FsAjzAsuUk1YHnnmI2MOK51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;574&quot; height=&quot;363&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;363&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양한 기능의 시스템 콜을 제공한다. 이중 프로세스 제어 시스템 콜 중 fork, exec, wait에 대해 정리했다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;프로세스 제어&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;파일 조작&lt;/li&gt;
&lt;li&gt;장치 조작 (Device Manipulation)&lt;/li&gt;
&lt;li&gt;정보 유지&lt;/li&gt;
&lt;li&gt;통신&lt;/li&gt;
&lt;li&gt;보호&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;347&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtSPaJ/btsopuXIktL/UInsPZyMuxyzkuTWqdYp31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtSPaJ/btsopuXIktL/UInsPZyMuxyzkuTWqdYp31/img.png&quot; data-alt=&quot;https://codybuilder.com/41&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtSPaJ/btsopuXIktL/UInsPZyMuxyzkuTWqdYp31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdtSPaJ%2FbtsopuXIktL%2FUInsPZyMuxyzkuTWqdYp31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;629&quot; height=&quot;320&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;347&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://codybuilder.com/41&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로세스 제어 시스템 콜&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jeongzero.oopy.io/086f4daa-084f-471c-8c68-8014661d4de4&quot;&gt;참고: fork, exec, wait&lt;/a&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fork(), exec() : 프로세스 생성과 관련 있는 명령&lt;/li&gt;
&lt;li&gt;wait() : 프로세스(parent)가 만든 다른 프로세스(child)가 끝날 때까지 기다리는 명령&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;fork()&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 프로세스를 생성&lt;/li&gt;
&lt;li&gt;fork가 실행되는 순간 프로세스가 하나 더 생긴다. 이때 생긴 child 프로세스는 fork를 만든 프로세스와 동일한 복사본을 가지게 된다.&lt;/li&gt;
&lt;li&gt;이러면 OS는 똑같은 2 개의 프로그램이 동작한다고 생각하고 fork()가 return 될 차례라고 생각한다. 그 때문에 새로 생성된 Child 프로세스는 main에서 시작하지 않고 if 문부터 시작하게 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스케쥴러가 어떤 프로세스를 먼저 수행할지는 확신할 수 없다. (보장하지 못함)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;wait()&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Child 프로세스가 종료될 때까지 기다리는 작업&lt;/li&gt;
&lt;li&gt;wait을 통해서 Parent 프로세스를 Child 프로세스가 실행이 끝날 때까지 기다리게 할 수 있다.&lt;/li&gt;
&lt;li&gt;Parent가 먼저 실행되더라도 wait()는 Child가 끝나기 전에는 return 하지 않으므로 반드시 Child가 먼저 실행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;exec()&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순 fork()는 동일한 프로세스의 내용을 여러 번 반복 동작할 때 사용한다.&lt;/li&gt;
&lt;li&gt;만약 Child 프로세스에서 Parent 프로세스와 다른 동작이 하고 싶을 때는 exec를 사용한다.&lt;/li&gt;
&lt;li&gt;exec가 실행되면, execvp(실행 파일, 전달 인자) 함수는 Code Segment(프로세스의 주소 공간 중)에 실행 파일의 코드를 읽어와서 덮어 씌운다.&lt;/li&gt;
&lt;li&gt;이후 heap, stack, 다른 메모리 영역이 초기화되고 OS는 덮어 씌워진 메모리 영역을 그냥 실행한다. 즉, 새로운 프로세스를 생성하지 않고 현재 프로그램에 wc라는 파일을 실행한다. 그로 인해 execvp() 이후 부분은 실행되지 않는다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS</category>
      <category>system call</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/61</guid>
      <comments>https://doubleyoo.tistory.com/61#entry61comment</comments>
      <pubDate>Fri, 21 Jul 2023 01:20:00 +0900</pubDate>
    </item>
    <item>
      <title>[Java] HashMap</title>
      <link>https://doubleyoo.tistory.com/60</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://coding-factory.tistory.com/556&quot;&gt;참고: 자바 HashMap 사용법&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HashMap&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Map 인터페이스를 구현한 대표적인 Map 컬렉션&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Hashing + Map&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Map은 &lt;b&gt;&amp;lt;키, 값&amp;gt;&lt;/b&gt; 구성된 객체를 저장하는 자료구조&lt;/li&gt;
&lt;li&gt;키는 중복될 수 없다. &amp;rarr; 동일한 키로 값을 저장하면 기존 값은 사라지고 새로운 값으로 대치&lt;/li&gt;
&lt;li&gt;Hash을 사용 &amp;rarr; 데이터를 검색하는데 뛰어난 성능을 보인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashMap 생성&lt;/h3&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;import java.util.Map
import java.util.HashMap

Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;String, Integer&amp;gt;();
Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;(); // 타입 생략 가능
Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;(10); // 초기 용량 지정
Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;() {{ // 초기값 지정
	put(&quot;key1&quot;, 1);
}}; 
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashMap 사용&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;map.put(&quot;key1&quot;, 1); // &amp;lt;키, 값&amp;gt; 추가
map.put(&quot;key1&quot;, 2); // 동일한 키 &amp;gt; 새로운 값으로 덮어씌워진다. 

map.get(&quot;key1&quot;); // 키에 해당하는 데이터 출력

map.remove(&quot;key1&quot;); // 키에 해당하는 데이터 제거
map.clear(); // map의 모든 데이터 제거

map.containsKey(&quot;key1&quot;); // map에 특정 키가 존자해는지 여부
map.containsValue(10); // map에 특정 값이 존자해는지 여부
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashMap 순회&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;entrySet() 사용 : map의 모든 데이터 &amp;lt;키, 값&amp;gt; 출력&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;keySet() 사용 : map의 모든 키 출력&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Key 값을 사용해 Value를 확인하는 과정에서 많은 시간이 소모된다. 많은 양의 데이터를 확인해야 한다면 entrySet() 을 사용하는 것이 좋다.&lt;/p&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;// entrySet() 사용
for (Entry&amp;lt;String, Integer&amp;gt; entry: map.entrySet()) {
		System.out.println(entry.getKey() + &quot; : &quot; + entry.getValue());
}

// keySet**() 사용**
for (String key: map.keySet()) {
		System.out.println(key + &quot; : &quot; + map.get(key));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;iterator 사용: 보다 빠르게 원소에 접근할 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Iterator&amp;lt;Entry&amp;lt;String, Integer&amp;gt;&amp;gt; iter = map.entrySet().iterator();
while (iter.hasNext()) {
		Entry&amp;lt;String, Integer&amp;gt; entry = iter.next()
		System.out.println(entry.getKey() + &quot; : &quot; + entry.getVaue());
}

Iterator&amp;lt;String&amp;gt; iter = map.keySet().iterator();
while (iter.hasNext()) {
		String key = iter.next()
		System.out.println(key + &quot; : &quot; + map.get(key));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashMap의 값을 변경하는 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 키에 해당하는 값만 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;map.put(&quot;key1&quot;, 10);
map.put(&quot;key1&quot;, map.get(&quot;key1&quot;)*10);
map.replace(&quot;key1&quot;, 10);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 조건에 해당하는 모든 값 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;map.replaceAll((key, value) -&amp;gt; {
	if (key.contains(&quot;x2&quot;)) {
		return value * 2;
	} else {
		return value;
	}
});
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS</category>
      <category>HashMap</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/60</guid>
      <comments>https://doubleyoo.tistory.com/60#entry60comment</comments>
      <pubDate>Thu, 20 Jul 2023 11:13:35 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] JPA - 양방향 연관 관계 mappedBy, @JoinColumn</title>
      <link>https://doubleyoo.tistory.com/59</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;참고: ORM 이란&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ttl-blog.tistory.com/126#%40JoinColumn-1&quot;&gt;참조: @JoinColumn과 연관관계 주인&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. ORM&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Object Relational Mapping, 객체-관계 매핑&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관계형 데이터베이스의 데이터를 객체지향적 언어로 자동으로 매핑(연결)해주는 것을 말한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 지향 프로그래밍은 &lt;b&gt;클래스&lt;/b&gt;를 사용하고, 관계형 데이터베이스는 &lt;b&gt;테이블&lt;/b&gt;을 사용하기 때문에 객체 모델과 관계형 모델 간에 불일치가 존재한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;데이터베이스 데이터 &amp;lt;&amp;mdash;매핑&amp;mdash;&amp;gt; Object 필드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;이를 통해 Spring에서 객체를 사용해 간접적으로 데이터베이스 데이터를 다룰 수 있다.&lt;/li&gt;
&lt;li&gt;Persistent API라고도 할 수 있다. Ex) JPA, Hibernate 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스의 관계의 종류는 크게 세 가지가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;1 : 1 - One to One&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 테이블 레코드 하나와 다른 테이블의 레코드 한 개가 연관되는 관계&lt;/li&gt;
&lt;li&gt;보통 1:1의 관계는 테이블을 하나로 합쳐서 표현하기 때문에 흔하지 않다.&lt;/li&gt;
&lt;li&gt;특정 데이터를 성능이나 보안적 측면에서 나눠야 하는 경우 사용된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보통 Foreign key &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;컬럼에&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;칼럼에&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;spell&amp;quot;}&quot; data-grammar-id=&quot;grammar4&quot; data-grammar-focus=&quot;false&quot;&gt;컬럼에&lt;/span&gt; Unique 제약 사항을 적용함으로써 구현한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;1 : N - Many to One&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 테이블의 레코드가 다른 테이블의 레코드 0 개 이상과 연관된 관계&lt;/li&gt;
&lt;li&gt;가장 흔한 관계 (ex) 게시글 &amp;rarr; 댓글, 가게 &amp;rarr; 상품 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;N : N - Many to Many&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 테이블의 레코드 0 개 이상과 다른 테이블의 레코드 0 개 이상이 연관된 관계&lt;/li&gt;
&lt;li&gt;&lt;b&gt;양쪽 테이블의 PK를 Foreign &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;key 로&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;key로&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;space&amp;quot;}&quot; data-grammar-id=&quot;grammar1&quot; data-grammar-focus=&quot;false&quot;&gt;key 로&lt;/span&gt; 가지는 &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;제 3의&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;제3의&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;space&amp;quot;}&quot; data-grammar-id=&quot;grammar2&quot; data-grammar-focus=&quot;false&quot;&gt;제 3의&lt;/span&gt; 테이블&lt;/b&gt;을 만들어 표현한다. 이를 &lt;b&gt;Associative Table&lt;/b&gt; 또는 &lt;b&gt;Join &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;Table 이라고&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;Table이라고&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;space&amp;quot;}&quot; data-grammar-id=&quot;grammar3&quot; data-grammar-focus=&quot;false&quot;&gt;Table&lt;/span&gt;&lt;/b&gt;&lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;Table 이라고&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;Table이라고&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;space&amp;quot;}&quot; data-grammar-id=&quot;grammar3&quot; data-grammar-focus=&quot;false&quot;&gt; 이라고&lt;/span&gt; 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA에서 1:N, N:N을 나타내는 어노테이션을 제공한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@ManyToOne, @OneToMany&lt;/li&gt;
&lt;li&gt;@ManyToMany&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 양방향 관계 mappedBy&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서 객체 참조는 방향성이 있다. 따라서 양방향 관계가 필요한 경우 연관을 두 번 정의해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 RDBMS에서는 방향이 없기 때문에 &lt;b&gt;외래키 하나&lt;/b&gt;로 두 테이블의 연관관계를 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;자바에서 @OneToMany의 &lt;b&gt;mappedBy 속성&lt;/b&gt;을 사용해 양방향 연관 관계를 가지는 두 엔터티 중 외래키를 관리할 객체를 지정해줘야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mappedBy에 owner 엔터티의 필드명을 지정한다.&lt;/li&gt;
&lt;li&gt;연관관계의&amp;nbsp;주인은 mappedBy 속성을&amp;nbsp;사용하지 않는다.&lt;/li&gt;
&lt;li&gt;mappedBy를 사용하지 않으면, N:1 관계의 경우 Join table이 생성되며 1:1 관계의 경우 각 테이블에 서로를 참조하는 FK가 설정된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;양뱡향 연관 관계 두 엔터티 중 어떤 엔터티가 Owner?&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;N:1 양방향 관계&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;N:1 관계를 가진 쪽이 외래키 owner가 된다. &amp;rarr;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; @OneToMany 쪽의 컬렉션 컬럼에 mappedBy 속성을 작성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;1:1 양방향 관계&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반대 엔터티에 대한 FK를 가지는 쪽이 owner가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;N:N 양방향 관계&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;양쪽 아무나 owner가 될 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Entity
public class Lecture {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
	private Instructor instructor; // Lecture -&amp;gt; Instructor

    // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Data
@Entity
public class Instructor {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;
    private String lastName;

    @OneToMany(mappedBy = &quot;instructor&quot;)
    private List&amp;lt;Lecture&amp;gt; lectures;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;cf) 양방향 관계에서 주의할 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://skysoo1111.tistory.com/44&quot;&gt;참고:&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시 코드를 보면 &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;Lecture 와&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;Lecture와&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;space&amp;quot;}&quot; data-grammar-id=&quot;grammar5&quot; data-grammar-focus=&quot;false&quot;&gt;Lecture 와&lt;/span&gt; Insructor 각각 @Data 어노테이션이 설정되어 있어 각각 toString을 호출할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 lecture.toString()을 호출하면 내부의 필드의 toString을 호출하고, Instructor.toString을 호출하게 된다. Instructor 클래스에도 Lecture가 있기 때문에, Lecture.toString을 호출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 두 엔터티가 반복적으로 서로의 toString을 호출하면서 stackOverFlow 에러가 발생하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다양한 해결 방법이 존재하는데 두 가지만 정리해 보겠다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;두 객체 중 한 객체에서 JSON 직렬화를 막는다&lt;/b&gt;.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@JsonManagedReference : 해당 필드는 직렬화를 허용한다.&lt;/li&gt;
&lt;li&gt;@JsonBackRefrence : 해당 필드는 직렬화하지 않도록 막는다. (역직렬화 중에 해당 필드 값은 Managed 링크가 있는 인스턴스로 설정된다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;@JsonIgnoreProperties 사용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 어노테이션이 붙은 필드는 JSON 데이터에 null로 들어가게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. &lt;b&gt;@JoinColumn&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외래키를 매핑할 때 사용하는 어노테이션&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;name 속성&lt;/b&gt; : 매핑할 외래키 &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;컬럼명,&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;칼럼명,&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;spell&amp;quot;}&quot; data-grammar-id=&quot;grammar6&quot; data-grammar-focus=&quot;false&quot;&gt;컬럼명,&lt;/span&gt; &lt;span style=&quot;background-color: #f6e199;&quot;&gt;단순히 &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;컬럼명을&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;칼럼명을&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;spell&amp;quot;}&quot; data-grammar-id=&quot;grammar7&quot; data-grammar-focus=&quot;false&quot;&gt;컬럼명을&lt;/span&gt; 만들어 주는 역할&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;referencedColumnName 속성&lt;/b&gt; : 외래키가 참조하는 대상 테이블의 &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;컬럼명,&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;칼럼명,&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;spell&amp;quot;}&quot; data-grammar-id=&quot;grammar8&quot; data-grammar-focus=&quot;false&quot;&gt;컬럼명,&lt;/span&gt; &lt;span style=&quot;background-color: #f6e199;&quot;&gt;대상 테이블의 어떤 &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;컬럼을&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;칼럼을&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;spell&amp;quot;}&quot; data-grammar-id=&quot;grammar9&quot; data-grammar-focus=&quot;false&quot;&gt;컬럼을&lt;/span&gt; 참조하는지 지정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;foreignKey 속성&lt;/b&gt; : 외래키 제약조건을 직접 지정할 때 사용, 테이블을 생성할 때만 사용한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;그 외 @Column 속성과 동일 (unique, nullable, insertable, updatable, columnDefinition, table)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;@JoinColumn을 생략하면 외래키를 찾는 전략으로 참조하는 테이블의 기본 키 &lt;span data-grammar=&quot;{&amp;quot;input&amp;quot;:&amp;quot;컬럼명을&amp;quot;,&amp;quot;output&amp;quot;:&amp;quot;칼럼명을&amp;quot;,&amp;quot;etype&amp;quot;:&amp;quot;spell&amp;quot;}&quot; data-grammar-id=&quot;grammar10&quot; data-grammar-focus=&quot;false&quot;&gt;컬럼명을&lt;/span&gt; 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 Lecture와 Instructor가 N:1 관계를 가지고 있다. @JoinColumn을 생략했기 때문에 Instructor의 기본키인 id (실제 테이블에서는 instructor_id)를 참조한다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Data
@Entity
public class Lecture {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    // @JoinColumn(name = &quot;instructor&quot;) // 외래키 매핑 할때 사용, name 속성에 매핑할 외래 키 이름을 지정
    private Instructor instructor;

    // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Data
@Entity
public class Instructor {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;267&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhzwry/btsn7tkZWiX/0vD3BSpsP7xGaMPJr5vCy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhzwry/btsn7tkZWiX/0vD3BSpsP7xGaMPJr5vCy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhzwry/btsn7tkZWiX/0vD3BSpsP7xGaMPJr5vCy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhzwry%2Fbtsn7tkZWiX%2F0vD3BSpsP7xGaMPJr5vCy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;267&quot; height=&quot;196&quot; data-origin-width=&quot;267&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/Backend</category>
      <category>JoinColumn</category>
      <category>JPA</category>
      <category>ManyToMany</category>
      <category>ManyToOne</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/59</guid>
      <comments>https://doubleyoo.tistory.com/59#entry59comment</comments>
      <pubDate>Tue, 18 Jul 2023 23:12:20 +0900</pubDate>
    </item>
    <item>
      <title>[알고리즘] 최대 공약수 구하기 - 유클리드 호제법</title>
      <link>https://doubleyoo.tistory.com/58</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://m.blog.naver.com/eandimath/221704180761&quot;&gt;참고: [최대공약수 쉽게 구하는 법] - 유클리드 호제법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대 공약수를 구하는 방법은 여러 가지가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;보통 방법 (연제법) - 동시에 나눌 수 있는 수로 계속 나누는 방법&lt;/li&gt;
&lt;li&gt;소인수분해 - 소수의 곱으로 표현하는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유클리드 호제법\&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;유클리드 호제법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 수 A, B 가 있을 때 A, B의 최대 공약수 G에 대하여 다음이 성립한다. (a, b는 서로소)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;A = G*a&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;B = G*b&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 다음도 성립한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;A - B = Ga - Gb = G * (a -b)&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 수의 차 A-B는 최대공약수 G의 배수이다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이를 통해 A-B의 약수 중 A와 B를 나누어 떨어지게 하는 수 중 가장 큰 수를 구하면 된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;더 나아가 B와 A-B의 최대 공약수를 구하는 식으로 계속 반복해 적용할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;119 - 91 = 28&lt;br /&gt;91 - 28 - 28 - 28 =&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&amp;nbsp;7 (큰 수 119는 버리고 91에서 28을 3번 뺄 수 있다. 나머지는 7 이다.)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;18 - 7 -7 -7-7 =&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&amp;nbsp;0 (큰 수 91은 버리고 28에서 7을 4번 뺄 수 있다. 나머지는 0이다.&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론적으로 차가 0 일 때 빼는 수가 바로 최대 공약수이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;연습 문제 - BOJ 9613 GCD의 합&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;nbsp;가능한 조합 구하기&lt;/li&gt;
&lt;li&gt;최대 공약수 구하기&lt;/li&gt;
&lt;li&gt;결과에 합하기&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조합을 구하기 위해 Combination 함수를 작성했고, 조합을 구한 후 findGDC로 최대 공약수를 구했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;findGDC에서 유클리드 호제법을 사용해서 b - a를 수행하기 때문에 배열(arr)을 입력받은 후 정렬해 줬다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;솔루션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1689671644442&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;

/*
가능한 모든 쌍의 최대공약수의 합
1. 조합 구하기
2. 최대 공약수 구하기 -&amp;gt; 더하기
- 유클리드 호제법 b - a 사용
*/
public class Main {
    static int t;
    static int[] arr;
    static boolean[] visited;
    static int[] output;
    static long result; // 총 합이 int 범위를 벗어난다. 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        t = Integer.parseInt(br.readLine());
        
        for (int i=0; i &amp;lt; t; i++) {
            arr = Arrays.stream(br.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
            Arrays.sort(arr, 1, arr[0]+1); // 1 ~ n 요소 정렬
            
            output = new int[2];
            visited = new boolean[arr[0]+1];
            result = 0L; // GCD 총합
            
            combination(0, 1);
            System.out.println(result);
        } 
    }
    
    public static void combination(int depth, int s) {
        if (depth == 2) {
            result += (long) findGCD(output[0], output[1]);
            return;
        }
        
        for (int i=s; i &amp;lt;= arr[0]; i++) {
            if (visited[i]) continue;
            
            visited[i] = true;
            output[depth] = arr[i];
            combination(depth + 1, i);
            visited[i] = false;
        }
    }
    
    // 항상 a &amp;lt; b
    public static int findGCD(int a, int b) {
        while (a &amp;gt; 0 &amp;amp;&amp;amp; b &amp;gt; 0) {
            if (b % a == 0) return a;
            if (b - a &amp;gt; 0) {
                int tmp = a;

                a = b % a;
                b = tmp;
            } 
        }
        
        return 1;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS</category>
      <category>유클리드 호제법</category>
      <category>최대공약수</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/58</guid>
      <comments>https://doubleyoo.tistory.com/58#entry58comment</comments>
      <pubDate>Tue, 18 Jul 2023 18:16:14 +0900</pubDate>
    </item>
    <item>
      <title>[CS 스터디] 프로세스 주소 공간</title>
      <link>https://doubleyoo.tistory.com/57</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Process%20Address%20Space.md&quot;&gt;참고: 프로세스의 주소 공간&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램이 CPU에 의해 실행되면 프로세스가 생성되고 메모리에 &lt;b&gt;프로세스 주소 공간&lt;/b&gt;이 할당된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;프로세스 주소 공간&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 주소 공간은 &lt;b&gt;코드, 데이터, 스택, 힙 영역&lt;/b&gt;으로 이루어져 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Code(Text) Segment&lt;/b&gt; : 프로그램 소스 코드 저장, &lt;b&gt;read only&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Data Segment&lt;/b&gt; : 전역 변수, static 등 저장, &lt;b&gt;read &amp;amp; write&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초기화된 데이터는 Data 영역에 저장, 초기화되지 않는 데이터는 BSS 영역에 저장된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Stack Segment&lt;/b&gt; : 함수(복귀할 주소, 리턴 값 &amp;hellip;), 지역 변수 저장, &lt;b&gt;read &amp;amp; write&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴파일 시 Stack 영역의 크기가 결정되기 때문에 무한정 할당할 수 없다. &amp;gt; stack overflow 발생 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Heap Segment&lt;/b&gt; : 런타임 시정에 결정되는 메모리 영역&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7tnIn/btsnZhq6rp1/9cj5v7rC37KWRh0JvpYFLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7tnIn/btsnZhq6rp1/9cj5v7rC37KWRh0JvpYFLK/img.png&quot; data-alt=&quot;https://github.com/Songwonseok/CS-Study/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7tnIn/btsnZhq6rp1/9cj5v7rC37KWRh0JvpYFLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7tnIn%2FbtsnZhq6rp1%2F9cj5v7rC37KWRh0JvpYFLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;622&quot; height=&quot;496&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/Songwonseok/CS-Study/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Code 구역을 나눈 이유?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 프로그램이 만들어진 후에는(컴파일된 후) 바뀔 일이 없기 때문에 읽기만 가능한 별개의 segment로 나누어 관리한다. 같은 프로그램을 실행시켜 여러 개의 프로세스가 실행되어도 코드 부분은 같은 내용을 가지고 있게 된다. 따라서 &lt;b&gt;같은 프로그램의 프로세스일 경우 Code segment를 공유해서 메모리 사용량을 줄인다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Stack과 Data 구역을 나눈 이유?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stack과 Data segment로 나눈 이유는 &lt;b&gt;스택 구조의 특성과 전역 변수의 활용성&lt;/b&gt;을 위해서 이다. 프로그램의 &lt;b&gt;함수와 지역변수&lt;/b&gt;는 LIFO 특성을 가진 스택에서 실행된다. 전역변수는 어떤 함수에서도 접근 가능하기 때문에 Data Segment로 관리한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uCTR8/btsn0EMAv6M/vbckOGp06cQJaKY35XCP41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uCTR8/btsn0EMAv6M/vbckOGp06cQJaKY35XCP41/img.png&quot; data-alt=&quot;func1 &amp;amp;gt; func 2 &amp;amp;gt; func3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uCTR8/btsn0EMAv6M/vbckOGp06cQJaKY35XCP41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuCTR8%2Fbtsn0EMAv6M%2FvbckOGp06cQJaKY35XCP41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;541&quot; height=&quot;234&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;265&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;func1 &amp;gt; func 2 &amp;gt; func3&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt; &amp;nbsp;Data 영역과 BSS 영역&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;http://shinluckyarchive.tistory.com/159&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참고: DATA, BSS&lt;/a&gt;&lt;br /&gt;&lt;b&gt;- Data 영역&lt;/b&gt; : 프로그램 실행 도중 자유롭게 접근하여 수정 및 변경이 가능하다.&lt;br /&gt;- &lt;b&gt;BSS 영역 : &lt;/b&gt;메모리 상에 공간만 잡아두고 실제로 변수를 초기화시키지 않는다.&lt;br /&gt;데이터 영역은 초기에 사용할 메모리를 확보하는 반면 BSS 영역에서는 런타임 후에야 메모리 영역이 확보된다. 즉, 메모리 사용면에서는 BSS 영역을 사용하는 것이 효율적이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <category>주소 공간</category>
      <category>프로세스</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/57</guid>
      <comments>https://doubleyoo.tistory.com/57#entry57comment</comments>
      <pubDate>Mon, 17 Jul 2023 16:32:45 +0900</pubDate>
    </item>
    <item>
      <title>[CS 스터디] 인터럽트 (Interrupt)</title>
      <link>https://doubleyoo.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Interrupt.md&quot;&gt;참고: tech-interview-for-developer&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@ckstn0777/%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8&quot;&gt;참고: 인터럽트&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인터럽트 (Interrupt)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 실행하는 도중 예기치 않은 상황이 발생할 경우, 현재 실행 중인 작업을 즉시 중단하고 발생된 상황에 대한 우선 처리가 필요함을 CPU에게 알리는 것&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지금 수행하는 작업보다 우선순위가 더 높은 작업을 먼저 처리하고 하던 일을 이어서 수행한다.&lt;/li&gt;
&lt;li&gt;인터럽트가 발생하면 CPU는 해당 인터럽트를 무시할 수도 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Non maskable 인터럽트 (NMI): 항상 응답해야 하는 인터럽트&lt;/li&gt;
&lt;li&gt;Maskable 인터럽트: 그렇지 않은 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인터럽트 종류&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트를 발생시키기 위해 하드웨어/소프트웨어는 CPU 내에 있는&amp;nbsp;&lt;b&gt;인터럽트 라인&lt;/b&gt;을 세팅하여 인터럽트를 발생시킨다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;하드웨어 인터럽트&lt;/b&gt; : 하드웨어 신호에 의해 발생 (외부/내부)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소프트웨어 인터럽트&lt;/b&gt; : 명령어의 수행에 의해 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;외부 인터럽트 :&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입출력 장치, 타이밍 장치, 전원 등 외부적인 요인으로 발생&lt;/li&gt;
&lt;li&gt;ex) 전원 이상, 기계 착오, 외부 신호, 입출력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내부 인터럽트(Trap) :&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;잘못된 명령 또는 데이터를 사용할 때 발생&lt;/li&gt;
&lt;li&gt;ex) 0으로 나누기, 오버플로우, 명령어 잘못 사용 (Exception)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소프트웨어 인터럽트 :&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램 처리 중 명령의 요청에 의해 발생 (SVC 인터럽트)&lt;/li&gt;
&lt;li&gt;ex) 소프트웨어 이용 중에 다른 프로세스를 실행시키면, 시분할 처리를 위해 자원 할당 동작이 수행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인터럽트 처리 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(입출력 장치를 예시로)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;특정 장치가 CPU에게 인터럽트를 요구한다.&lt;/li&gt;
&lt;li&gt;CPU는 인터럽트 확인 신호(INTA)를 보낸다.&lt;/li&gt;
&lt;li&gt;INTA를 받은 입출력 장치는 인터럽트 요구 신호(INTR)를 삭제한다.&lt;/li&gt;
&lt;li&gt;CPU는 PC, PSW, 레지스터 등을 스택에 저장한다.&lt;/li&gt;
&lt;li&gt;CPU는 인터럽트 서비스 루트의 주소를 PC에 적재하고, 인터럽트 서비스 루틴(ISR)을 수행한다.&lt;/li&gt;
&lt;li&gt;CPU는 PSW, 레지스터 등을 스택으로부터 복귀한다.&lt;/li&gt;
&lt;li&gt;본래 실행 중이던 프로그램을 수행한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컨트롤러가 입력을 받아들이는 방법&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;폴링 방식&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 명령어를 사용해 입력 핀의 값을 계속 읽어 변화를 알아내는 방식&lt;/li&gt;
&lt;li&gt;인터럽트 요청 플래그를 차례로 비교하여 우선순위가 가장 높은 인터럽트 자원을 찾아 이에 맞는 인터럽트 서비스 루틴을 수행한다. &amp;lt; 하드웨어에 비해 속도가 느림&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인터럽트 방식&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MCU 자체가 하드웨어적으로 변화를 체크하여 변화 시에만 일정 동작을 수행하는 방식&lt;/li&gt;
&lt;li&gt;Daisy chain&lt;/li&gt;
&lt;li&gt;병렬 우선순위 부여&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트 기능이 없다면 컨트롤러는 어떤 일을 할 시기를 알기 위해 계속 체크해야 한다.&lt;b&gt;(= 폴링)&lt;/b&gt; 이로 인해 컨트롤러는 상당한 시간을 소비하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트 방식은 하드웨어를 사용해야 한다는 제약이 있지만, 폴링에 비해 신속하게 대응이 가능하다. 따라서 &lt;b&gt;실시간 대응이 필요할 때는 필수적인 기능이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;rarr; &lt;span style=&quot;background-color: #f6e199;&quot;&gt;인터럽트는 발생 시기를 예측하기 힘든 경우 컨트롤러가 가장 빠르게 대응할 수 있는 방법&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MCU (microcontroller unit)&lt;/b&gt; : 마이크로 프로세스와 입출력 모듈의 하나의 칩으로 만들어 정해진 기능을 수행하는 컴퓨터&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;다중 인터럽트&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 인터럽트를 처리하는 중에 또 인터럽트가 발생하는 경우 두 가지 처리 방식이 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkNtHF/btsnK8B8uRW/NLcUISLNCaSZkSSJS7a23k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkNtHF/btsnK8B8uRW/NLcUISLNCaSZkSSJS7a23k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkNtHF/btsnK8B8uRW/NLcUISLNCaSZkSSJS7a23k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkNtHF%2FbtsnK8B8uRW%2FNLcUISLNCaSZkSSJS7a23k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;601&quot; height=&quot;271&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;CPU가 인터럽트 서비스 루틴을 처리하는 중 새로운 인터럽트가 들어오더라도 &lt;b&gt;수행 중인 ISR이 끝날 때까지 새로운 인터럽트 사이클을 수행하지 않도록 하는 방식&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;인터럽트 간 우선순위를 정하고, &lt;b&gt;우선순위가 더 높은 인터럽트가 발생한다면, 현재 수행 중인 명령어를 멈춰두고 새로운 인터럽트를 먼저 처리하도록 하는 방식&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>CS</category>
      <category>인터럽트</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/56</guid>
      <comments>https://doubleyoo.tistory.com/56#entry56comment</comments>
      <pubDate>Mon, 17 Jul 2023 16:27:53 +0900</pubDate>
    </item>
    <item>
      <title>[CS 스터디] 운영체제(Operating System)</title>
      <link>https://doubleyoo.tistory.com/55</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Operation%20System.md&quot;&gt;참고: tech-interview-for-developer&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://coding-factory.tistory.com/300&quot;&gt;참고: 운영체제란 무엇인가&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영체제란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 컴퓨터를 편리하고 효과적으로 사용할 수 있도록 환경을 제공하는 시스템 소프트웨어&lt;/li&gt;
&lt;li&gt;하드웨어를 효율적으로 관리하며, 다른 응용 프로그램이 유용한 작업을 할 수 있도록 환경을 제공해 준다.&lt;/li&gt;
&lt;li&gt;Windows, Linuex, UNIX, MS-DOS 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;운영체제의 역할&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;프로세스 관리&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스, 스레드&lt;/li&gt;
&lt;li&gt;스케쥴링&lt;/li&gt;
&lt;li&gt;동기화&lt;/li&gt;
&lt;li&gt;IPC 통신&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;저장장치 관리&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리 관리&lt;/li&gt;
&lt;li&gt;가상 메모리&lt;/li&gt;
&lt;li&gt;파일 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;네트워킹&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP/IP&lt;/li&gt;
&lt;li&gt;기타 프로토콜&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;사용자 관리&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계정 관리&lt;/li&gt;
&lt;li&gt;접근 권한 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;디바이스 드라이버&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;순차 접근 장치&lt;/li&gt;
&lt;li&gt;임의 접근 장치&lt;/li&gt;
&lt;li&gt;네트워크 장치&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;각 역할에 대한 설명&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 프로세스 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제에서 작동하는 응용 프로그램을 관리하는 기능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;프로세스 스케줄링 및 동기화&lt;/b&gt; : 프로세스의 생성과 제거, 시작과 정지, CPU 할당 등&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로세스 간 공유 자원 접근과 통신 등을 관리&lt;/b&gt; (ex) 메시지 전달 기능)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 저장장치 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차 저장장치에 해당하는 &lt;b&gt;메인 메모리&lt;/b&gt;와 2차 저장장치에 해당하는 &lt;b&gt;하드디스크, NAND&lt;/b&gt; 등을 관리하는 기능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1차 저장장치 관리 : Main Memory&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스에 메모리 영역을 할당 &amp;amp; 해제&lt;/li&gt;
&lt;li&gt;각 메모리 영역 간 침범 방지&lt;/li&gt;
&lt;li&gt;메인 메모리의 효율적인 사용을 위한 가상 메모리 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2차 저장장치 관리 : HDD, NAND Flash Memroy 등&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 형식의 데이터 저장&lt;/li&gt;
&lt;li&gt;저장된 파일 데이터 관리를 위한 파일 시스템을 관리 (FAT, NTFS, EXT2, JFS, XFS&amp;nbsp;등 많은 파일 시스템들이 개발되어 사용 중이다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 네트워킹&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP/IP 기반의 인터넷에 연결하거나, 응용 프로그램이 네트워크를 사용하려면 운영체제에서 네트워크 프로토콜을 지원해야 한다. 현재 상용 OS는 다양하고 많은 네트워크 프로토콜을 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 사용자 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제는 하나의 PC를 여러 사용자가 사용하는 환경도 지원해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 계정을 관리하는 기능&lt;/li&gt;
&lt;li&gt;사용자 별로 프라이버시와 보안을 위해 개인 파일에 다른 사용자가 접근할 수 없도록 관리&lt;/li&gt;
&lt;li&gt;파일, 시스템 자원에 접근 권한을 지정할 수 있도록 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 디바이스 드라이버&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제는 시스템의 자원, 하드웨어를 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템에는 여러 하드웨어가 붙어있는데, 이들을 운영체제에서 인식하고 관리하게 만들어 응용 프로그램이 하드웨어를 사용할 수 있게 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 운영체제 안에 하드웨어를 추상화해 주는 계층**(= 디바이스 드라이버)**이 필요하다. 하드웨어의 종류가 많은 만큼, 운영체제 내부의 디바이스 드라이버도 많이 존재한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수많은 디바이스 드라이버들을 관리하는 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 운영체제는 사용자와 컴퓨터 하드웨어 사이에서, 하드웨어를 운영 관리하고 명령어를 제어하여 응용 프로그램 및 하드웨어를 소프트웨어적으로 제어 및 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  가상 메모리&lt;br /&gt;&lt;a href=&quot;http://coffeenix.net/doc/RHEL-4-Manual/rhel-isa-ko-4/s1-memory-concepts.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참고: 실제 메모리와 가상 메모리&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;초창기 물리적인 메모리의 크기보다 큰 애플리케이션을 실행하려면 메모리 부족으로 실행하지 못하는 RAM 부족 문제가 발생한다. 그래서 가상 메모리 방식이 등장했다.&lt;br /&gt;현재 애플리케이션의 실행에 필요한 데이터만 RAM에 올려놓고, 나머지는 디스크에 저장해서 디스크를 RAM의 보조 기억 장치처럼 사용하는 방식&lt;br /&gt;가상 메모리를 구현하기 위해서는 컴퓨터가 특수 메모리 관리 하드웨어를 갖추고 있어야 한다. = MMU (Memory Management Unit) &lt;br /&gt;&lt;br /&gt;&lt;b&gt;MMU (Memory Management Unit)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;가상 메모리 주소를 물리 메모리 주소로 변환하고, 메모리를 보호하는 기능을 수행 메모리를 페이지로 나누어 각 페이지를 하나의 독립적인 항목으로 처리한다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  IPC 통신 (InterProcess Communication) &lt;br /&gt;&lt;a href=&quot;https://www.fun-coding.org/post/ipc.html#gsc.tab=0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참고: 프로세스 간 커뮤니케이션&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;각 프로세스는 서로 독립적으로 실행된다. 프로세스 간에 데이터를 교환하거나 특정 기능을 사용하기 위한 방법을 제공하는 것이 IPC이다.&lt;br /&gt;&lt;br /&gt;다양한 IPC 기법이 존재한다.&lt;br /&gt;&lt;b&gt;주요 IPC 기법&lt;/b&gt; &lt;br /&gt;- &lt;b&gt;Message Queue&lt;/b&gt; : kernel space를 사용, 기본적으로 단방향 통신 &lt;br /&gt;- &lt;b&gt;Shared Memory&lt;/b&gt; : kernel space에 메모리 공간을 만들고, 해당 공간을 변수처럼 접근하는 방식 &lt;br /&gt;- &lt;b&gt;Pipe&lt;/b&gt; : kernel space를 사용, FIFO 정책으로 데이터 전송 &lt;br /&gt;&lt;b&gt;기타 IPC 기법&lt;/b&gt; &lt;br /&gt;&lt;b&gt;- Signal&lt;/b&gt; : 커널 또는 프로세스에서 다른 프로세스에 어떤 이벤트가 발생되었는지를 알려주는 기법 &lt;br /&gt;- &lt;b&gt;Socket&lt;/b&gt; : 소켓을 하나의 컴퓨터 안에서 두 개의 프로세스 간에 통신 기법으로 사용 가능 &lt;br /&gt;- file 사용, Semaphore,... 등&lt;/blockquote&gt;</description>
      <category>CS</category>
      <category>OS</category>
      <category>운영체제</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/55</guid>
      <comments>https://doubleyoo.tistory.com/55#entry55comment</comments>
      <pubDate>Thu, 13 Jul 2023 13:13:53 +0900</pubDate>
    </item>
    <item>
      <title>[CS 스터디] 프로세스 (Process), 스레드 (Thread)</title>
      <link>https://doubleyoo.tistory.com/54</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Process%20vs%20Thread.md&quot;&gt;참고: 프로세스&amp;amp;스레드&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/OS#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EC%B0%A8%EC%9D%B4&quot;&gt;참고: 프로세스와 스레드 차이&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJbcfL/btsnoJCmBYI/zVCkQraYRrpbT10PGJSA8K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJbcfL/btsnoJCmBYI/zVCkQraYRrpbT10PGJSA8K/img.jpg&quot; data-alt=&quot;https://github.com/gyoogle/tech-interview-for-developer/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJbcfL/btsnoJCmBYI/zVCkQraYRrpbT10PGJSA8K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJbcfL%2FbtsnoJCmBYI%2FzVCkQraYRrpbT10PGJSA8K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;605&quot; height=&quot;360&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/gyoogle/tech-interview-for-developer/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 60px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;프로세스&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;스레드&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;프로그램이 메모리 상에서 실행 중인 작업&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;프로세스 안에서 실행되는 여러 흐름 단위&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;차이점&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;자신만의 고유 공간과 자원을 할당받아 사용&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;프로세스 내 다른 스레드와 공간, 자원을 공유하면서 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로세스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리에 올라와 실행 중인 프로그램&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운영체제로부터 주소 공간, 파일, 메모리 등을 자원을 할당받은 작업의 단위&lt;/li&gt;
&lt;li&gt;각 프로세스는 할당된 메모리에만 접근이 가능하다 (독립적)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스는 &lt;b&gt;프로세스 스택, 데이터 섹션, 힙, 코드&lt;/b&gt;를 포함한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 스택 : 함수의 매개변수, 복귀 주소, 로컬 변수 등 임시 메모리 영역&lt;/li&gt;
&lt;li&gt;데이터 섹션 : 전역 변수, 정적 변수 등&lt;/li&gt;
&lt;li&gt;힙 : 프로세스 실행 중 동적으로 할당되는 메모리&lt;/li&gt;
&lt;li&gt;코드 : 코드 자체를 구성하는 메모리 영역&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로세스 제어 블록 (Process Control Block, PCB)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 프로세스에 대한 중요한 정보를 저장하고 있는 운영체제의 자료구조&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;운영체제는 프로세스를 관리하기 위해 &lt;b&gt;프로세스의 생성과 동시에 고유한 PCB를 생성&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;프로세스는 CPU를 할당받아 작업을 하는 중간에 프로세스 전환이 발생하면, 진행하던 작업을 저장하고 CPU를 반환해야 한다. 이때 작업의 진행 상황을 모두 PCB에 저장한다.&lt;/li&gt;
&lt;li&gt;프로세스가 다시 CPU를 할당받으면 PCB에 저장되어 있던 내용을 불러와 이전 종료 시점부터 작업을 수행한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PCB에 저장되는 정보&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 식별자(Process ID, PID) : 프로세스 식별 번호&lt;/li&gt;
&lt;li&gt;프로세스 상태 : new, ready, running, waiting, terminated 등의 상태를 저장&lt;/li&gt;
&lt;li&gt;프로그램 카운터 : 프로세스가 다음에 실행할 명령어의 주소&lt;/li&gt;
&lt;li&gt;CPU 레지스터&lt;/li&gt;
&lt;li&gt;CPU 스케줄링 정보 : 프로세스의 우선순위, 스케줄 큐에 대한 포인터 등&lt;/li&gt;
&lt;li&gt;메모리 관리 정보 : 페이지 테이블 또는 세그먼트 테이블 등과 같은 정보를 포함&lt;/li&gt;
&lt;li&gt;입출력 상태 정보 : 프로세스에 할당된 입출력 장치들과 열린 파일 목록&lt;/li&gt;
&lt;li&gt;어카운팅 정보 : 사용된 CPU 시간, 시간제한, 계정번호 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스레드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 안에서 실행되는 더 작은 작업 단위&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;스레드 ID, 프로그램 카운터(PC), 레지스터 집합, 스택&lt;/b&gt;으로 구성된다. 같은 프로세스에 속한 다른 스레드와 &lt;b&gt;코드, 데이터 섹션, 그리고 열린 파일이나 신호와 같은 운영체제 자원들을 공유&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스레드마다 Stack을 독립적으로 할당하는 이유&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스레드는 독립적인 동작을 수행하기 위해 존재한다. &amp;gt; &lt;b&gt;독립적으로 함수 호출&lt;/b&gt;이 가능해야 함&lt;/li&gt;
&lt;li&gt;때문에 &lt;b&gt;함수의 매개 변수, 지역 변수 등을 저장하는 스택 메모리 영역&lt;/b&gt;을 독립적으로 할당받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스레드마다 PC Register을 독립적으로 할당하는 이유&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PC는 스레드가 명령어를 어디까지 수행하였는지 나타낸다.&lt;/li&gt;
&lt;li&gt;스레드는 CPU를 할당받아 작업을 수행하다 스케줄러에 의해 다시 선점당한다. 그래서 각 스레드가 어느 부분까지 수행했는지 기록하기 위해 스레드 별로 독립적으로 할당받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;멀티 프로세스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 프로그램을 여러 개의 프로세스로 구성하여 각 프로세스가 병렬적으로 작업을 수행하는 것&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;장점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;안전성&lt;/b&gt; : 운영체제 차원에서 각 프로세스가 다른 프로세스의 메모리를 침범하지 못하도록 관리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;자원 소모 많음, 오버헤드&lt;/b&gt; : 프로세스 별로 독립된 메모리 영역을 할당받기 때문에, 작업량이 많을수록 오버헤드가 발생한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Context switching으로 인한 성능 저하&lt;/b&gt; : Context Switching은 프로세스의 상태 정보를 저장하고 복원하는 일련의 과정이다. 프로세스는 독립적인 메모리 영역을 할당받기 때문에 캐시 메모리 초기화와 같은 무거운 작업이 진행되었을 때 오버헤드가 발생할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;멀티 스레드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 프로세스를 다수의 스레드로 구분해 각 스레드가 하나의 작업을 처리하도록 한다. 이를 통해 다수의 작업을 동시에 처리할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;장점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;메모리 공간과 시스템 자원 소모 감소&lt;/b&gt; : 독립적인 프로세스에 비해 스레드는 자원을 공유하고, 이를 통해 자원의 생성과 관리의 중복성을 최소화할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;통신이 간단&lt;/b&gt; : heap 영역을 이용하면 스레드 간 데이터를 주고받을 수 있다. 프로세스의 통신 방법에 비해 스레드 간 통신 방법이 훨씬 간단하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빠른 context switch&lt;/b&gt; : 스레드의 context switch는 프로세스의 context switch와 달리 캐시 메모리를 비울 필요가 없어 더 빠르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&amp;rarr; 시스템의 처리율 향상, 프로그램 응답 시간 단축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;안정성 문제&lt;/b&gt; : 서로 다른 스레드가 데이터와 힙 영역을 공유하기 때문에, 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽거나 수정할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&amp;rarr; 동기화 작업 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동기화 작업을 통해 작업 처리 순서를 컨트롤, 공유 자원에 대한 접근을 컨트롤한다.&lt;/b&gt; 하지만 이로 인한 병목 현상을 고려해야 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS</category>
      <category>스레드</category>
      <category>프로세스</category>
      <author>yooja_tea</author>
      <guid isPermaLink="true">https://doubleyoo.tistory.com/54</guid>
      <comments>https://doubleyoo.tistory.com/54#entry54comment</comments>
      <pubDate>Thu, 13 Jul 2023 13:06:05 +0900</pubDate>
    </item>
  </channel>
</rss>