{"componentChunkName":"component---src-templates-blog-post-js","path":"/Operating-Systems/2020-05-20-운영체제-교착상태와기아상태/","result":{"data":{"site":{"siteMetadata":{"title":"Hun's Footsteps 🥷","author":"전여훈","siteUrl":"https://jeonyeohun.netlify.app","comment":{"disqusShortName":"","utterances":"jeonyeohun/jeonyeohun.github.io"},"sponsor":{"buyMeACoffeeId":"jeonyeohun"}}},"markdownRemark":{"id":"5584038a-1a5c-51c3-ac35-0030cb18e5fc","excerpt":"참고도서: Operating System Concepts (10/E) Abraham Silberschatz, Peter B. Galvin, Greg Gagne 마치 세마포어가 임계구역 문제를 해결하는 만능열쇠처럼 보였지만 실상은 그렇지 않다. 다음 예시를 한번 보자. 교착상태(Deadlock) P0 P1 프로세스 P1 과 P2가 임계구역 진입을 시도하려고 하는 것을 생각해보자. 그리고 세마포어는 1로 초기화 되어 있다고 가정하자. 위와 같은 상황에서 아래와 같은 상황이 발생한다. 편의상 P1과 P…","html":"<p>참고도서: <em>Operating System Concepts (10/E) Abraham Silberschatz, Peter B. Galvin, Greg Gagne</em></p>\n<p>마치 세마포어가 임계구역 문제를 해결하는 만능열쇠처럼 보였지만 실상은 그렇지 않다. 다음 예시를 한번 보자.</p>\n<h2 id=\"교착상태deadlock\" style=\"position:relative;\"><a href=\"#%EA%B5%90%EC%B0%A9%EC%83%81%ED%83%9Cdeadlock\" aria-label=\"교착상태deadlock permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>교착상태(Deadlock)</h2>\n<p><strong>P0</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token function\">wait</span><span class=\"token punctuation\">(</span>S<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">wait</span><span class=\"token punctuation\">(</span>Q<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">.</span>\n<span class=\"token punctuation\">.</span>\n<span class=\"token punctuation\">.</span>\n<span class=\"token function\">signal</span><span class=\"token punctuation\">(</span>S<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">signal</span><span class=\"token punctuation\">(</span>Q<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><strong>P1</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token function\">wait</span><span class=\"token punctuation\">(</span>Q<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">wait</span><span class=\"token punctuation\">(</span>S<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">.</span>\n<span class=\"token punctuation\">.</span>\n<span class=\"token punctuation\">.</span>\n<span class=\"token function\">signal</span><span class=\"token punctuation\">(</span>Q<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">signal</span><span class=\"token punctuation\">(</span>S<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>프로세스 P1 과 P2가 임계구역 진입을 시도하려고 하는 것을 생각해보자. 그리고 세마포어는 1로 초기화 되어 있다고 가정하자. 위와 같은 상황에서 아래와 같은 상황이 발생한다. 편의상 P1과 P2 번갈아가며 실행한다고 생각해보자.</p>\n<ol>\n<li>P0가 wait(S) 실행, <strong>S 세마포어의 값은 0</strong>이 된다. 아직 음수가 되지 않았기 때문에 임계구역 진입을 위해 계속 진행한다. 현재 S는 P0가 점유한 상황이다.</li>\n<li>P1이 wait(Q) 실행, <strong>Q 세마포어의 값이 0</strong>이 된다. 아직 음수가 되지 않았기 때문에 임계구역 진입을 위해 계속 진행한다. 현재 Q는 P1이 점유한 상황이다.</li>\n<li>P0가 wait(Q) 실행, <strong>Q 세마포어의 값이 -1</strong>이 된다. 세마포어 값이 음수가 되었으므로 P0는 Q의 대기 큐에 들어간다.</li>\n<li>P1이 wait(S) 실행, <strong>S 세마포어의 값이 -1</strong>이 된다. 세마포어 값이 음수가 되었으므로 P1는 S의 대기 큐에 들어간다.</li>\n<li>P0가 임계구역에 진입하기 위해서는 P1의 signal(Q)를 받아야한다.</li>\n<li>P1이 임계구역에 진입하기 위해서는 P0의 signal(S)를 받아야한다.</li>\n<li>두 프로세스 모두 대기 큐에 들어가 있으므로 signal() 연산은 절대 일어나지 않는다. 따라서 두 프로세스가 무한히 대기하는 상태가 된다.</li>\n</ol>\n<p>위 예시처럼 두 프로세스가 서로의 자원을 필요로 하게 되면, 서로 대기큐에 들어가 무한정하게 기다리는 상태가 되고 이런 문제를 우리는 <code class=\"language-text\">deadlock</code> 이라고 부른다.</p>\n<h3 id=\"solution\" style=\"position:relative;\"><a href=\"#solution\" aria-label=\"solution permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Solution</h3>\n<p>교착 상태에 대한 더 자세한 이야기는 책을 더 정리하면서 추가하도록 하자.</p>\n<h2 id=\"기아상태starvation\" style=\"position:relative;\"><a href=\"#%EA%B8%B0%EC%95%84%EC%83%81%ED%83%9Cstarvation\" aria-label=\"기아상태starvation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>기아상태(Starvation)</h2>\n<p>교착상태와 비슷한 문제가 하나 더 있다. 세마포어의 대기 큐에서 대기하던 프로세스는 signal() 연산을 통해 대기 큐에서 제거되면 상태가 <code class=\"language-text\">ready</code> 상태로 바뀌고, 준비 큐로 들어가 디스패쳐의 스케줄링을 기다리게 된다. 이때 선입선출로 스케줄링 되는 것이 아니라 우선순위에 의해 스케줄링 되는 방식이라면(Priority Scheduling), 해당 프로세스가 우선순위가 낮을 경우 준비 큐에서 디스패처의 선택을 받지 못하고 계속 대기중인 상태가 될 여지가 있다. 이렇게 우선순위에서 계속 밀려서 스케줄링되지 못하고 계속 준비 큐에 남아있는 프로세스를 <code class=\"language-text\">기아상태</code>에 있다고 한다.</p>\n<h3 id=\"solution-1\" style=\"position:relative;\"><a href=\"#solution-1\" aria-label=\"solution 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Solution</h3>\n<p>일반적으로 스케줄링 알고리즘을 수정해서 Round Robin 알고리즘을 Priority Scheduling 과 함께 사용하거나, aging 을 적용해서 대기시간에 따라 프로세스의 우선순위를 단계적으로 높이는 기법이 사용된다.</p>\n<h2 id=\"우선순위역전priority-inversion\" style=\"position:relative;\"><a href=\"#%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%EC%97%AD%EC%A0%84priority-inversion\" aria-label=\"우선순위역전priority inversion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>우선순위역전(Priority Inversion)</h2>\n<p>우선순위역전 문제는 기아상태 문제와 비슷한 맥락이다. 이 문제는 스케줄링이 가능한 프로세스가 3개 이상 존재할 때 발생한다. 다음과 같은 상황을 상상해보자.</p>\n<ol>\n<li>우선순위가 가장 낮은 프로세스 Plow 가 세마포어 S를 점유하고 실행중이다.</li>\n<li>우선순위가 가장 높은 프로세스 Phigh 가 시스템의 준비 큐에 들어왔고, 스케줄러에 의해 곧바로 CPU를 선점한다. 이때 Plow 는 다시 준비큐로 돌아간다.</li>\n<li>그런데 Phigh 가 작업하는 중에 세마포어 S를 사용해야하는 작업이 있다. 하지만 현재 세마포어는 Plow가 가지고 있기 때문에 wait에 의해 Phigh 는 세마포어의 대기 큐에 들어가서 대기한다.</li>\n<li>CPU가 비었기 때문에 중간 우선순위를 가지고 있는 프로세스 Pmiddle 이 등장하고 스케줄링된다.</li>\n<li>이제 Phigh는 Pmiddle이 모두 종료되고, Plow가 다시 실행되어서 signal()을 실행할 때까지 기다려야 하는 상황이 되었다. 우선순위가 역전된 것이다.</li>\n</ol>\n<p>우선순위는 존재하지만 세마포어 때문에 우선순위가 의미가 없어지는 역설적인 상황이다. 여기서 만약 기아상태 문제까지 발생해서 Plow 의 실행이 점점 더 늦춰진다면, Phigh의 우선순위는 정말로 의미가 없진다.</p>\n<h3 id=\"soulution\" style=\"position:relative;\"><a href=\"#soulution\" aria-label=\"soulution permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Soulution</h3>\n<p>우선순위 역전 문제의 해결을 위해서 <code class=\"language-text\">우선순위 상속 프로토콜(Priority-Inheritance Protocol)</code> 을 사용할 수 있다. 우선순위 상속은 만약 어떤 프로세스가 자기자신보다 높은 우선순위를 가진 프로세스로 부터 자원을 요청받는다면, 해당 자원을 넘겨줄 때까지 프로세스의 우선순위를 상속받아 높이는 것이다. 이 방법을 사용하면 위 예시에서도 Plow가 Phigh의 요청을 받는 순간 우선순위를 최고순위로 높이면서 중간 우선순위 프로세스를 제치고 먼저 실행될 수 있도록 할 수 있다.</p>","frontmatter":{"title":"[운영체제] 교착상태, 기아상태 그리고 우선순위역전(Deadlocks, Starvation and Priority Inversion)","date":"May 20, 2020"}}},"pageContext":{"slug":"/Operating-Systems/2020-05-20-운영체제-교착상태와기아상태/","previous":{"fields":{"slug":"/Operating-Systems/2020-05-20-운영체제-뮤텍스/"},"frontmatter":{"title":"[운영체제] 뮤텍스(Mutex Lock)","category":"Operating-Systems","draft":false}},"next":{"fields":{"slug":"/Operating-Systems/2020-05-21-운영체제-식사하는-철학자-문제/"},"frontmatter":{"title":"[운영체제] 고전적 동기화 문제-3 : 식사하는 철학자 문제(The Dining-Philosophers Problem)","category":"Operating-Systems","draft":false}}}},"staticQueryHashes":["2486386679","3128451518"]}