{"componentChunkName":"component---src-templates-blog-post-js","path":"/Operating-Systems/2020-05-07-운영체제-실시간스케줄링/","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":"36076921-fae0-5e3f-b139-0dd67c8d20ab","excerpt":"참고도서: Operating System Concepts (10/E) Abraham Silberschatz, Peter B. Galvin, Greg Gagne Real-Time CPU Scheduling 운영체제가 실시간으로 동작하면서 스케줄링을 수행하는 것을 우리는 두 종류로 구분한다.  : 우선순위가 높은 프로세스가 먼저 실행되도록 보장하는 시스템  : 각 태스크가 반드시 정해진 deadline 안으로 작업이 끝나는 것을 보장하는 시스템 Latency…","html":"<p>참고도서: <em>Operating System Concepts (10/E) Abraham Silberschatz, Peter B. Galvin, Greg Gagne</em></p>\n<h2 id=\"real-time-cpu-scheduling\" style=\"position:relative;\"><a href=\"#real-time-cpu-scheduling\" aria-label=\"real time cpu scheduling 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>Real-Time CPU Scheduling</h2>\n<p>운영체제가 실시간으로 동작하면서 스케줄링을 수행하는 것을 우리는 두 종류로 구분한다.</p>\n<ol>\n<li><code class=\"language-text\">Soft Real-Time System</code> : 우선순위가 높은 프로세스가 먼저 실행되도록 보장하는 시스템</li>\n<li><code class=\"language-text\">Hard Real-Time System</code> : 각 태스크가 반드시 정해진 deadline 안으로 작업이 끝나는 것을 보장하는 시스템</li>\n</ol>\n<h2 id=\"latency\" style=\"position:relative;\"><a href=\"#latency\" aria-label=\"latency 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>Latency</h2>\n<p>결국 스케줄링이 필요한 이유는 각 프로세스의 <code class=\"language-text\">latency</code> 를 줄이기 위함인데, <code class=\"language-text\">latency</code>는 어떤 이벤트가 발생하고 그에 맞는 서비스가 수행되기 까지의 시간을 의미한다. 그리고 이 latency는 다시 두 유형으로 나뉘어진다.</p>\n<ol>\n<li><code class=\"language-text\">Interupt Latency</code> : 인터럽트가 발생하고 <code class=\"language-text\">Interupt Service Routine(ISR)</code>이 시작되기 까지의 지연시간을 말한다. 이미 이전 수업에서 배웠던 것 처럼 인터럽트가 발생하면 어떤 유형의 인터럽트인지 검사하고 Context Switching 을 수행한 이후에 이미 정해진 ISR을 수헹하게 된다.</li>\n<li><code class=\"language-text\">Dispatch Latency</code> : <code class=\"language-text\">Dispatcher</code>가 하나의 프로세스를 block 하고 다른 프로세스를 시작하기 까지의 지연시간을 말한다. 이때 새로운 프로세스가 시작되기전, 커널에서 동작하는 프로세스에 대한 <code class=\"language-text\">preemtion</code>과 높은 우선순위를 가진 프로세스가 요구하는 리소스를 낮은 우선순위 프로세스로부터 방출시키는 작업이 발생하고 이때 걸리는 시간들이 Dispatch Latency가 된다.</li>\n</ol>\n<h2 id=\"scheduling-strategy\" style=\"position:relative;\"><a href=\"#scheduling-strategy\" aria-label=\"scheduling strategy 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>Scheduling Strategy</h2>\n<p>어떤 프로세스가 스케줄되는 과정을 이해하기 위해서 몇가지 용어들을 알아야한다.</p>\n<ol>\n<li><code class=\"language-text\">수행시간(t)</code> : 어떤 프로세스가 CPU에 스케줄링 되었을 때 작업을 수행하는 고정된 시간</li>\n<li><code class=\"language-text\">마감시간(d)</code> : 어떤 CPU로부터 서비스를 반드시 받아야하는 마감시간</li>\n<li><code class=\"language-text\">주기(p)</code> : CPU를 필요로하는 주기적인 시간</li>\n<li><code class=\"language-text\">승인제어(Admission Control)</code> : 스케줄러가 어떤 프로세스가 마감시간 이내에 작업을 마칠 수 없다면 프로세스를 거부하는 알고리즘</li>\n</ol>\n<h3 id=\"priority-based-scheduling\" style=\"position:relative;\"><a href=\"#priority-based-scheduling\" aria-label=\"priority based scheduling 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-Based Scheduling</h3>\n<p>실시간 운영체제는 프로세스를 중요성에 따라 우선순위를 부여하고, Preemtion을 지원함으로 실시간으로 중요한 프로세스가 CPU에 할당될 수 있도록 해야한다. 이런 방법으로 스케줄링을 하는 경우에는 <code class=\"language-text\">Soft Real-Time System</code>의 요구사항을 충족시킬 수 있다. 하지만 각 태스크의 마감시간을 보장하지는 않는다.</p>\n<h5 id=\"번외-토막-상식\" style=\"position:relative;\"><a href=\"#%EB%B2%88%EC%99%B8-%ED%86%A0%EB%A7%89-%EC%83%81%EC%8B%9D\" aria-label=\"번외 토막 상식 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>번외 토막 상식</h5>\n<p>책에서 나오는 <code class=\"language-text\">태스크</code> 의 의미가 모호한 것 같아서 구글링을 조금 해봤다. 태스크는 어떤 작업의 단위를 지칭하는 말이다. 어떤 시스템에서는 프로세스가 작업의 단위가 되기도하고, 또 어떤 시스템에서는 스레드가 작업의 단위가 되기도 한다. 따라서 작업을 표현하고자할 때 일반적인 지칭으로 사용하는 것이 태스크이다.</p>\n<h3 id=\"rate-monotonic-scheduling\" style=\"position:relative;\"><a href=\"#rate-monotonic-scheduling\" aria-label=\"rate monotonic scheduling 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>Rate-Monotonic Scheduling</h3>\n<p><code class=\"language-text\">Rate-Monotonic</code> 알고리즘은 프로세스들의 우선순위에 따라 프로세스를 CPU에 스케줄링한다. 이때 우선순위는 각 프로세스가 가지는 주기에 따라서 결정된다. 주기가 짧으면 우선순위가 높아지고, 주기가 길면 우선순위가 낮게 평가된다.</p>\n<p>다음과 같은 두 프로세스가 Rate-Monotonic 방법으로 스케줄링된다고 해보자</p>\n<center>\n<ol>\n<li>P1 = 수행시간 : 20, 주기 : 50, 마감 : 50<br/></li>\n<li>P2 = 수행시간 : 35, 주기 : 100, 마감 : 100</li>\n</ol>\n</center>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 936px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 35%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAyUlEQVQoz4WR2QqEMAxF+/+/qC/FB3dc664ZTqBSZZgJ3JLe3CxNzXVdEuI8T/nF4Xt8ixsJbN93WZZF3uacu/11XWXbNpnn+ebIOY5DfYOABNB1ndR1reJxHJWbpknKstQ7ftM0qqmqSuNoucMTNwgBgmEYFHTLskwb0LDve2nbVpMoYq3VIkxKHF1RFBo3HBShE4lRFN3T+Qng0JGc57kkSfIomqapxHGsWsNCwx1S/G1MwMIxkvxKPMdTge6Q4/1bIefxj/P+B97RIae70Dl+AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"ratemonotonic\"\n        title=\"ratemonotonic\"\n        src=\"/static/779caf4581115edef4ffb464844a9331/6d2da/ratemonotonic.png\"\n        srcset=\"/static/779caf4581115edef4ffb464844a9331/5a46d/ratemonotonic.png 300w,\n/static/779caf4581115edef4ffb464844a9331/0a47e/ratemonotonic.png 600w,\n/static/779caf4581115edef4ffb464844a9331/6d2da/ratemonotonic.png 936w\"\n        sizes=\"(max-width: 936px) 100vw, 936px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<ol>\n<li>일단 주기가 더 짧은 P1이 스케줄링 되고 고정된 수행시간만큼 작업이 수행된다. P1 의 마감시간은 50이기 때문에 P1은 마감시간을 지켰다.</li>\n<li>P1의 작업이 끝난 직후에 P2가 스케줄링 된다. P2의 마감시간은 100이기 때문에 그 전에만 작업이 완료되면 된다.</li>\n<li>P2가 작업을 수행하던 중 P1의 주기인 50에 도달하게 된다. 이 시점에서 P2는 아직 5의 시간이 남았지만 P1에 의해 CPU가 선점된다.</li>\n<li>다시 P1이 할당되었고 20동안 작업을 수행하고 돌아간다.</li>\n<li>P2가 다시 할당되고 P2의 남은 작업 시간인 5를 마저 실행한다.</li>\n</ol>\n<p>여기까지 오면 두 프로세스의 1차 주기 내에 모든 작업이 끝나게 되고 두 주기가 완전히 끝나는 100까지 기다리게 된다. 그리고 100에 도달했을 때, 주기가 짧은 P1부터 다시 할당이 시작된다.</p>\n<h4 id=\"cpu-usage\" style=\"position:relative;\"><a href=\"#cpu-usage\" aria-label=\"cpu usage 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>CPU Usage</h4>\n<p>Rate-monotonic 알고리즘을 사용한 스케줄링이 매우 효과적으로 보이겠지만, CPU의 자원적 한계 때문에 스케줄링 하고자하는 프로세스의 CPU 이용률에 따라 마감시간을 지키지 못할 수도 있다.</p>\n<p>다음은 N개의 프로세스에 대해서 CPU 이용률의 최악의 경우를 구하는 수식이다:</p>\n<span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi><mo stretchy=\"false\">(</mo><msup><mn>2</mn><mrow><mn>1</mn><mi mathvariant=\"normal\">/</mi><mi>N</mi></mrow></msup><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">N(2^{1/N} - 1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.188em;vertical-align:-0.25em;\"></span><span class=\"mord mathdefault\" style=\"margin-right:0.10903em;\">N</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.938em;\"><span style=\"top:-3.113em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span><span class=\"mord mtight\">/</span><span class=\"mord mathdefault mtight\" style=\"margin-right:0.10903em;\">N</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></span>\n<p>단일한 프로세스는 언제나 100%의 이용률을 보여줄 것이기 때문에 크게 의미가 없다. 다수의 프로세스를 사용할 때는 각 프로세스의 CPU 이용률을 구한 뒤, 위 수식에 프로세스의 개수를 대입해 CPU 이용률의 합과 최악의 경우의 이용률을 비교해볼 수 있다.</p>\n<p>예를 들어, 위에서 사용한 예시에서 P1의 주기는 50, 수행시간은 20 이었기 때문에 CPU 이용률은 20/50 = 40% 가 된다. 그리고 P2의 주기는 100, 수행시간은 35이기 때문에 CPU 이용률은 35%가 된다. 따라서 두 이용률을 합치면 75%가 되고, 위 수식에 프로세스 2개에 대한 최악의 이용률을 계산해보면 2(2^(1/2)-1)이므로 약 83% 이기 때문에 두 프로세스가 마감시간을 맞추는 것이 보장된다는 것을 확인할 수 있다.</p>\n<h3 id=\"earlist-deadline-first-scheduling\" style=\"position:relative;\"><a href=\"#earlist-deadline-first-scheduling\" aria-label=\"earlist deadline first scheduling 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>Earlist-Deadline-First Scheduling</h3>\n<p><code class=\"language-text\">Earlist-Deadline-First(EDF)</code> 스케줄링은 마감시간을 기준으로 우선순위를 구분하는 방법이다. 마감시간이 빠르면 우선순위가 높게 부여되고, 짧으면 낮게 부여된다. EDF에서는 프로세스가 실행이 가능한 상태가 되면 자신의 마감시간을 시스템에 알리게되고, 이 마감시간에 맞춰서 시스템 내의 프로세스들의 우선순위가 변경된다.</p>\n<p>이 방법은 이론적으로 완벽한 방법이다. 프로세스의 주기를 확인할 필요도 없고 모든 프로세스가 항상 마감시간을 맞출 수 있으며 CPU 이용률을 100%로 활용할 수 있다. 하지만 두 프로세스가 교체되는 과정에서 발생하는 context switching은 항상 pure overhead를 가지고 있기 때문에 실제로 구현이 불가능하다.</p>\n<h3 id=\"proportionate-share-scheduling\" style=\"position:relative;\"><a href=\"#proportionate-share-scheduling\" aria-label=\"proportionate share scheduling 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>Proportionate Share Scheduling</h3>\n<p><code class=\"language-text\">Proportional Share</code> 스케줄링은 모든 응용프로그램들에게 비율을 나누어서 배분해주고 각 응용프로그램은 해당 비율에 맞춰서 프로세스를 할당하게 되는 방법이다. 만약 비율이 100%로 가득 채워져서 사용되고 있을 때는 새로운 프로세스의 할당을 거부하고, 80%가 채워져 있는 상황에서 100%를 넘어서는 30% 이상을 요구했을 때도 할당을 거부하게 된다.</p>","frontmatter":{"title":"[운영체제] 실시간 CPU 스케줄링(Real-Time CPU Scheduling)","date":"May 07, 2020"}}},"pageContext":{"slug":"/Operating-Systems/2020-05-07-운영체제-실시간스케줄링/","previous":{"fields":{"slug":"/Problem-Solving/2019-12-27-2783번-삼각김밥/"},"frontmatter":{"title":"[백준 알고리즘] 2783번: 삼각김밥","category":"Problem-Solving","draft":false}},"next":{"fields":{"slug":"/Operating-Systems/2020-05-07-운영체제-멀티프로세서스케줄링/"},"frontmatter":{"title":"[운영체제] 멀티 프로세서 스케줄링(Multiple Processor Scdeduling)","category":"Operating-Systems","draft":false}}}},"staticQueryHashes":["2486386679","3128451518"]}