<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Seungil Kim</title><description>Seungil Kim의 소프트웨어 엔지니어링, 알고리즘 문제 풀이, CS, 커리어 기록을 모은 개인 블로그.</description><link>https://ks1ksi.io/</link><item><title>2024 - 2025 회고</title><link>https://ks1ksi.io/blog/2024---2025-%ED%9A%8C%EA%B3%A0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2024---2025-%ED%9A%8C%EA%B3%A0/</guid><description>2024-2025 회고. LG CNS 인턴, 교생실습, 토스 합격과 입사, 직장 생활로 바빴던 2년을 분기별로 돌아본 글.</description><pubDate>Tue, 30 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;올해 너무 바빠서 2024년꺼 미루고미루고미루다보니 2년치 한번에 작성하게 됨 😅&lt;/p&gt;
&lt;h2 id=&quot;2024-1q&quot;&gt;2024 1Q&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%B5%9C%EC%A2%85-%EC%A0%84%ED%99%98-%ED%9B%84%EA%B8%B0/&quot;&gt;2024 LG CNS 채용연계형 인턴 최종 전환 후기&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2024 ~ 2025 회고-1767027760245.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2160&quot; height=&quot;1620&quot; src=&quot;https://ks1ksi.io/_astro/2024%20~%202025%20%ED%9A%8C%EA%B3%A0-1767027760245.C3jTOPQ3_Z1V3azi.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;살면서 회사라는걸 처음 다녀봤다. 8주동안 대기업 회사원 체험을 하며 식당 밥을 맛있게 먹었던 것 같다. 아침 일찍 일어나 버스를 타고 9시까지 맞춰서 출근하는게 정말 쉽지 않다는 것을 알게 되었다. 다행히 전환되어 남은 학교생활을 편하게 했다.&lt;/p&gt;
&lt;h2 id=&quot;2024-2q&quot;&gt;2024 2Q&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/%ED%86%A0%EC%8A%A4-3%EB%85%84-%EC%9D%B4%ED%95%98-server-developer-challenge-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/&quot;&gt;토스 3년 이하 Server Developer Challenge 지원 및 합격 후기&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2024 ~ 2025 회고-1767027926138.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1440&quot; height=&quot;1080&quot; src=&quot;https://ks1ksi.io/_astro/2024%20~%202025%20%ED%9A%8C%EA%B3%A0-1767027926138.BGYoJ5L7_cM2lc.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2024 ~ 2025 회고-1767028053237.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1200&quot; height=&quot;704&quot; src=&quot;https://ks1ksi.io/_astro/2024%20~%202025%20%ED%9A%8C%EA%B3%A0-1767028053237.DWd4UJ0Q_kG8iD.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;교생실습이랑 취준이랑 병행하면서 정신없이 살다가 갑자기 직장인이 되었다. 뭔가 좋은 경험이 되지 않을까? 하고 붙으면 좋고, 아니면 말고 식으로 지원했고, 면접 보는 날 당일 교생실습 마무리 회식이라 교장 선생님 앞에서 ‘아 저 회사 면접 보러가해서 이만 일어나보겠습니다..’ 하고 집으로 뛰어와서 본게 엊그제같은데 돌아보니 감회가 참 새롭다.&lt;/p&gt;
&lt;p&gt;교생실습도 처음에는 가기 싫어서 온몸을 비틀어댔는데 막상 가니까 학생들도 선생님들도 다들 너무 잘해주셔서 행복한 시간을 보냈다. 인천남동고등학교같은 학교에서만 계속 일할 수 있으면 선생님도 참 좋은 직업이 아닐까?&lt;/p&gt;
&lt;p&gt;7월 입사하기 전에 많이 놀았어야 했는데 6월 말 종강이라 그럴 수 없었고, 그나마 남은 시간마저도 뭔가 그냥 회사 들어가기 무서워서 책을 열심히 읽어봤던 기억이 있는데 그냥 놀아도 됐을듯.&lt;/p&gt;
&lt;h2 id=&quot;2024-3q&quot;&gt;2024 3Q&lt;/h2&gt;
&lt;p&gt;(여기부터 대충 회사다니느라 바빴다는 내용)&lt;/p&gt;</content:encoded><category>life</category></item><item><title>2026 새해 목표</title><link>https://ks1ksi.io/blog/2026-%EC%83%88%ED%95%B4-%EB%AA%A9%ED%91%9C/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2026-%EC%83%88%ED%95%B4-%EB%AA%A9%ED%91%9C/</guid><description>2026년 새해 목표. PS 재시작, 운전과 자동차, 운동, CodeCrafters, 독서 계획을 정리하고 지난 목표를 돌아본 글.</description><pubDate>Sun, 21 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.acmicpc.net/&quot;&gt;ps&lt;/a&gt; 다시 시작&lt;/li&gt;
&lt;li&gt;운전 고수 + 부자가 되어 &lt;a href=&quot;https://www.tesla.com/ko_kr/model3/design#overview&quot;&gt;자동차&lt;/a&gt; 구매하기&lt;/li&gt;
&lt;li&gt;운동 하던거 계속&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codecrafters.io/&quot;&gt;codecrafters&lt;/a&gt; 사둔거 4개 이상 클리어&lt;/li&gt;
&lt;li&gt;책 사둔거 10권 이상 읽기&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/2023-%EC%83%88%ED%95%B4-%EB%AA%A9%ED%91%9C/&quot;&gt;2023 새해 목표&lt;/a&gt; 는 아쉽지만 반도 지키지 못했다고 한다.&lt;/p&gt;</content:encoded><category>life</category></item><item><title>토스 3년 이하 Server Developer Challenge 지원 및 합격 후기</title><link>https://ks1ksi.io/blog/%ED%86%A0%EC%8A%A4-3%EB%85%84-%EC%9D%B4%ED%95%98-server-developer-challenge-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/%ED%86%A0%EC%8A%A4-3%EB%85%84-%EC%9D%B4%ED%95%98-server-developer-challenge-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</guid><description>토스 3년 이하 Server Developer Challenge 합격 후기. 토스페이먼츠 서버 개발자 전형의 서류, 코딩테스트, 직무 면접, 문화적합성 면접을 정리했다.</description><pubDate>Thu, 13 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;토스 3년 이하 Server Developer Challenge 합격 후기-1718226485349.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;7500&quot; height=&quot;2500&quot; src=&quot;https://ks1ksi.io/_astro/%ED%86%A0%EC%8A%A4%203%EB%85%84%20%EC%9D%B4%ED%95%98%20Server%20Developer%20Challenge%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1718226485349.DFOlH21__ZyS4cT.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;토스페이먼츠 소속 서버 개발자 채용 공고를 발견하여 지원해 보았다.&lt;/p&gt;
&lt;h2 id=&quot;jd&quot;&gt;JD&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;토스페이먼츠를 소개해드려요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;토스페이먼츠는 사업의 어려움과 비효율을 이해하고, 기술부터 운영까지 사업에 필요한 모든 솔루션을 제공하는 것을 목표로 합니다. 소비자들에게 쉽고 편한 서비스 경험을 제공하고, 가맹점들에게는 오직 사업에만 집중할 수 있는 환경이 보장되는 제품을 만들고 있어요.&lt;/li&gt;
&lt;li&gt;‘전자결제 시장 혁신’을 핵심 목표로 자율과 책임의 원칙 아래, 강력한 상호 신뢰의 문화 속에서 일하고 있어요. 결제 산업의 미래를 함께 만들어 갈 동료를 기다리고 있습니다!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;합류하면 함께할 업무예요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;지속적으로 증가하는 결제 요청량과 다양한 요구사항을 쉽게 구현할 수 있도록 확장성과 유연성이 높은 시스템을 만들어요&lt;/li&gt;
&lt;li&gt;선착순 결제와 같은 이벤트를 진행하여 수십배의 트래픽이 순간적으로 발생해도 무너지지 않는 시스템을 만들어요&lt;/li&gt;
&lt;li&gt;수많은 거래건을, 수백가지 요구사항으로 계산해도 빠르게, 오차없이 계산이 가능한 정산 시스템을 만들어요&lt;/li&gt;
&lt;li&gt;자유로운 무중단 배포가 가능한 MSA 환경에서 사업자의 비즈니스 어려움을 해결할 새로운 API 를 만들어요&lt;/li&gt;
&lt;li&gt;토스페이먼츠와 고객사 시스템의 접점이 되는 OpenAPI 와 OpenAPI 를 지탱하기 위한 생태계를 만들어요&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;이런 분들이 지원하실 수 있어요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;개발 실무 경력 3년 이하인 분&lt;/li&gt;
&lt;li&gt;해외여행에 결격사유가 없는 분&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;토스페이먼츠가 사용하는 기술&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Java, Kotlin, Gradle&lt;/li&gt;
&lt;li&gt;Spring MVC, Spring Webflux, Spring Batch, JPA, Spring Cloud Gateway, Spring Cloud Config, Netty&lt;/li&gt;
&lt;li&gt;MySQL, Redis, ElasticSearch, Kafka, Oracle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;어디선가 신입으로 써서 붙었다는 후기를 본 것 같아 용기를 얻고 지원했다.&lt;/p&gt;
&lt;h2 id=&quot;서류&quot;&gt;서류&lt;/h2&gt;
&lt;p&gt;자기소개서 제출이 없다는 점이 가장 마음에 든다. 이전에 만들어둔 이력서와 포트폴리오를 살짝 다듬어서 제출했다. 따로 지원 페이지에서 확인할 수 없고 이메일로 확인해야 한다.&lt;/p&gt;
&lt;p&gt;포트폴리오는 SAP 면접때 낸 것 처럼 노드로 만든 프로젝트 하나만 적어서 냈다.&lt;/p&gt;
&lt;h2 id=&quot;코딩테스트&quot;&gt;코딩테스트&lt;/h2&gt;
&lt;p&gt;총 90분간 진행되었고 알고리즘 6문제, 서술형 3문제가 나왔다. 문제당 10분정도 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;알고리즘은 별 어려움이 없었는데 서술형이 상당히 어려웠다. 제대로 작성하지 못한 것 같아서 탈락을 직감했다. (신입이라면)평소에 책을 많이 읽고 고민을 해본 사람만 풀 수 있을 것 같다.&lt;/p&gt;
&lt;p&gt;추천하는 책은 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001766482&quot;&gt;Real MySQL 8.0&lt;/a&gt;, &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001033116&quot;&gt;가상 면접 사례로 배우는 대규모 시스템 설계 기초&lt;/a&gt; 두 권이다.&lt;/p&gt;
&lt;h2 id=&quot;직무-면접&quot;&gt;직무 면접&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;토스 3년 이하 Server Developer Challenge 합격 후기-1718226921407.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1644&quot; height=&quot;726&quot; src=&quot;https://ks1ksi.io/_astro/%ED%86%A0%EC%8A%A4%203%EB%85%84%20%EC%9D%B4%ED%95%98%20Server%20Developer%20Challenge%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1718226921407.Ht9x4x-L_YXwsN.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;1시간 반동안 기술’만’ 이야기했다. 제출한 포트폴리오 기반으로 질문을 주셨는데 깊이가 상당했다. 지금까지 본 면접 중 가장 배울 점이 많았다. 문제를 해결하기 위해 어떤 기술을 사용했는지, 왜 그 기술을 사용했는지 고민을 해보자. 그 내용을 &lt;strong&gt;학교에서 배운 CS 지식으로 풀어서 설명&lt;/strong&gt;하는 연습도 해보자.&lt;/p&gt;
&lt;h2 id=&quot;문화적합성-면접&quot;&gt;문화적합성 면접&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;토스 3년 이하 Server Developer Challenge 합격 후기-1718226905449.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1652&quot; height=&quot;698&quot; src=&quot;https://ks1ksi.io/_astro/%ED%86%A0%EC%8A%A4%203%EB%85%84%20%EC%9D%B4%ED%95%98%20Server%20Developer%20Challenge%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1718226905449.qpBmKBru_ZEffr5.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;직무 인터뷰 결과가 다음날 아침에 바로 나왔고, 다음 면접은 바로 또 다음날이었다. 3일간 면접을 두 번 보게 되었다. 얼떨결에 마지막 관문 컬쳐핏까지 왔더니 욕심이 생겼고, 지금까지 내가 했던 경험들 중 &lt;a href=&quot;https://blog.toss.im/article/core-values-are-evolving&quot;&gt;토스 핵심 가치&lt;/a&gt;와 연결되는 경험을 정리했다. 다행히 내 평소 생각과 겹치는 부분이 많이 있었다.&lt;/p&gt;
&lt;p&gt;면접은 압박 없이 편안한 분위기 속에서 진행됐다. 토스 1, 2차 면접 둘 다 최고의 경험이었다.&lt;/p&gt;
&lt;h2 id=&quot;합격&quot;&gt;합격&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;토스 3년 이하 Server Developer Challenge 합격 후기-1718227240418.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1276&quot; height=&quot;1012&quot; src=&quot;https://ks1ksi.io/_astro/%ED%86%A0%EC%8A%A4%203%EB%85%84%20%EC%9D%B4%ED%95%98%20Server%20Developer%20Challenge%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1718227240418.BPRWm_8f_1WHK6A.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;문화적합성 면접 다음날 결과가 나오지 않아서 떨어진 줄 알았는데 일주일 정도 후에 결과가 나왔다. 운좋게도 4학년 1학기 재학 중 직장을 가지게 되었다. 아직 실감은 나지 않는다.&lt;/p&gt;
&lt;p&gt;학점을 최대한 많이 들어 둔 덕분에 2학기는 학교에 가지 않고 일을 할 수 있다. 아직 부족한게 많지만 성장 가능성을 보고 뽑아 주신 것 같다. 기대에 부응할 수 있도록 최선을 다 할 예정이다.&lt;/p&gt;</content:encoded><category>toss</category><category>job</category></item><item><title>SAP Labs Korea Vocational Training Program Intern 지원 및 합격 후기</title><link>https://ks1ksi.io/blog/sap-labs-korea-vocational-training-program-intern-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/sap-labs-korea-vocational-training-program-intern-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</guid><description>SAP Labs Korea Vocational Training Program Intern 합격 후기. SAC Planning 팀 지원, 영어 phone screening, JS 코딩테스트, HR/PT 면접과 오퍼 과정을 정리했다.</description><pubDate>Fri, 31 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;SAP Labs Korea에서 채용 연계형 인턴을 모집하고 있어 지원해 보았다. 여러 팀이 있었는데 그 중에서 SAC(SAP Analytics Cloud) Planning 팀에 지원했다.&lt;/p&gt;
&lt;h2 id=&quot;job-description&quot;&gt;Job Description&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Education and qualifications&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We require that you meet the core competencies and skills listed below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bachelor’s/Master’s degree or equivalent in Computer Science, Computer Engineering, related fields or related technical disciplines&lt;/li&gt;
&lt;li&gt;Will be graduated in Feb. 2025, Aug. 2025, or Feb. 2026 (Is a Must)&lt;/li&gt;
&lt;li&gt;An open-minded, problem-solving attitude, resilience, and positive spirit even under challenging conditions&lt;/li&gt;
&lt;li&gt;Experience in one or more programming languages
&lt;ul&gt;
&lt;li&gt;JavaScript, TypeScript&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Database operation, SQL, Stored Procedure&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Intermediate communication skills in English (Fluent is a plus)&lt;/li&gt;
&lt;li&gt;Analytical skills combined with the ability to work on complex topics is a plus&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Perspectives&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SAP Labs Korea’s Vocational Training Program provides an extensive array of opportunities for continual learning and career advancement. Notably, the program includes a ‘rotation’ system that allows you to participate in three different projects or teams within the organization. This facilitation of diverse experiences is designed for an enriching and comprehensive understanding of the business environment, which in turn promotes both personal and professional development among students. If you are selected, your first field of rotation is SAC Planning Development.&lt;/p&gt;
&lt;p&gt;SAP Analytics Cloud(SAC) is a strategic public cloud of SAP that purely developed by SAP development. SAC Planning is a feature that takes care the complex enterprise business process and calculation.&lt;/p&gt;
&lt;p&gt;Here is the example of a project topic&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SAC Planning backend development
&lt;ul&gt;
&lt;li&gt;Develop a specific module of SAC Planning backend&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AI Integration
&lt;ul&gt;
&lt;li&gt;Generate comments/formula through Generative AI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;That’s where YOU come in.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a VT/STAR student, you will be responsible to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Successfully complete an 18-month program that strengthens a foundation for a successful developer/researcher career at SAP.&lt;/li&gt;
&lt;li&gt;Participate in experiential learning opportunities and acquire a wide variety of business, project and SAP solution skills while working with emerging and cutting-edge technologies.&lt;/li&gt;
&lt;li&gt;Receive on-the-job training under the mentorship of a senior developer or researcher colleague to gain real business experience and acquire the skills.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The program will enrich your knowledge of SAP as well as give you the professional experience to be ready to serve our customers. Your official start date at SAP is &lt;strong&gt;1st of July 2024&lt;/strong&gt; and the total program period is 1 year 6 months. During your semester break, you will work full-time(40 hours per week) at SAP. During the semester, you will work on part-time (20 hours per week) or full-time at the company. You will be able to schedule your working time flexibly in accordance with your university schedule and the requirements of your department. You can apply for permanent positions after the completion of your studies and after half-completing this program(9 months), either in one of our business teams or in one of our graduate or Academy programs. If you get accepted, you can be converted into permanent employee by completing this program earlier than 18 months.&lt;/p&gt;
&lt;p&gt;The program provides maximum support for internships through the university-operated field practicum program(대학 현장실습 프로그램/학점인정 프로그램), allowing you to earn university credit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hiring Process&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deadline of application: End of April 2024&lt;/li&gt;
&lt;li&gt;Coding Test: During April or May 2024&lt;/li&gt;
&lt;li&gt;Interviews: During April or May 2024&lt;/li&gt;
&lt;li&gt;Job Offered: Early June 2024&lt;/li&gt;
&lt;li&gt;Early applicants can have a coding test and an interview early, so we recommend that you apply before the application deadline if you are ready.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What you can expect&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gain real-world experience in one of the world’s top software companies&lt;/li&gt;
&lt;li&gt;Technical &amp;#x26; soft-skill trainings&lt;/li&gt;
&lt;li&gt;1:1 mentoring &amp;#x26; coaching&lt;/li&gt;
&lt;li&gt;Project/research experience in the area of software development (SAP HANA &amp;#x26; Analytics)&lt;/li&gt;
&lt;li&gt;Flexibility on working hour aligned with your university schedule (Full-time or Part-time)&lt;/li&gt;
&lt;li&gt;Networking with SAP coworkers in 140+ countries&lt;/li&gt;
&lt;li&gt;Competitive intern salary&lt;/li&gt;
&lt;li&gt;Opportunity to join SAP after graduation&lt;/li&gt;
&lt;li&gt;International rotation in Germany or Singapore (potential)&lt;/li&gt;
&lt;li&gt;Various other benefits&lt;/li&gt;
&lt;li&gt;“This is an SAP global, strategic, paid internship placement that provides students with opportunities to find purpose in their careers.”&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;특징은 25년 2월 졸업 ~ 26년 2월 졸업 사이, 즉 3-1, 3-2, 4-1 재학 중인 사람만 지원할 수 있다는 것이다. 3-1 재학 중인 경우 최장 18개월까지 인턴십을 진행할 수 있고, &lt;strong&gt;학기 중에 파트타임으로 병행이 가능&lt;/strong&gt;하다. 인턴십 중간에 내부에서 정규직 포지션이 열리면 지원해서 전환되는 구조인 것 같다.&lt;/p&gt;
&lt;p&gt;난 25년 2월 졸업 예정이라 지원할 수 있었다. 특히 학기중에 인턴십을 병행할 수 있다는 점이 마음에 들었다. 다른 회사에서 인턴십을 할 때는 기간이 짧아서 아쉬웠는데, 기간이 길면 커다란 프로젝트를 할 수 있지 않을까 하는 기대감을 가지고 있었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resume, Cover Letter, Transcript&lt;/strong&gt;를 제출했다. 영문으로 작성했다.&lt;/p&gt;
&lt;h2 id=&quot;phone-screening&quot;&gt;Phone Screening&lt;/h2&gt;
&lt;p&gt;내 이력을 검증하기 위해 30분정도 Phone Screening Interview를 진행한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;물론 영어다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SAP Labs Korea Vocational Training Program Intern 지원 및 합격 후기-1717147680658.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2212&quot; height=&quot;932&quot; src=&quot;https://ks1ksi.io/_astro/SAP%20Labs%20Korea%20Vocational%20Training%20Program%20Intern%20%EC%A7%80%EC%9B%90%20%EB%B0%8F%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1717147680658.n7vzaBoy_1X30OS.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;in English? 벌써부터 어지럽다.&lt;/p&gt;
&lt;p&gt;다행히 어려운 질문은 없었다. 내가 작성한 Resume가 사실인지 검증하는 질문 위주였다. 간단한 자기소개와 다른 회사 인턴십동안 진행한 프로젝트 설명 등..&lt;/p&gt;
&lt;p&gt;인터뷰 마지막에는 코딩 테스트 일정을 잡았다. 그리고 코딩 테스트는 &lt;strong&gt;자바스크립트&lt;/strong&gt;로만 응시 가능하다는 소식을 들었다. 내가 가는 팀 백엔드가 JS라 그런 것 같다.&lt;/p&gt;
&lt;h2 id=&quot;coding-test&quot;&gt;Coding Test&lt;/h2&gt;
&lt;p&gt;조금 기다리면 Online Assessment에 응시하라는 메일이 온다. SHL이라는 플랫폼에서 시험을 본다. 정해진 기한 내 편한 시간에 접속해서 보면 된다.&lt;/p&gt;
&lt;p&gt;총 2문제였고 간단한 문제였다. Node.js 환경에서 입출력하는 연습만 미리 해두자.&lt;/p&gt;
&lt;h2 id=&quot;hr-interview&quot;&gt;HR Interview&lt;/h2&gt;
&lt;p&gt;코딩 테스트에 통과하면 SAP Korea의 HR Interview가 기다리고 있다. HR 1 : Candidates 3으로 진행되었다. 다른 회사의 일반적인 인성면접, 임원면접과 비슷한 느낌이었다. 자기소개, 지원 동기, 지원자를 뽑아야 하는 이유 등등… 나 말고 다른 2명이 대답을 너무 잘해서 떨어질 것 같았다. 1시간정도 걸렸다.&lt;/p&gt;
&lt;h2 id=&quot;pt-interview&quot;&gt;PT Interview&lt;/h2&gt;
&lt;p&gt;사전에 PT자료를 만들고 합류할 팀의 매니저분들께 발표하는 면접이다. 마찬가지로 1시간정도 걸렸다. 관심분야, 진행한 프로젝트 등을 소개하는 자료를 만들고 담당자분께 보냈다. 이 때 시험 기간이라 자료를 만드는데 시간을 거의 쏟지 못했다. 네이버 면접, PT자료 마감, HR Interview, PT Interview, 다수의 중간고사와 중간과제, 토스 코딩테스트 등등 모든 일정이 일주일동안 몰려있었다.&lt;/p&gt;
&lt;p&gt;정말 자신있는 프로젝트 하나만 제출하자는 전략으로 접근했고 어느정도 성공한 것 같다. 대부분의 질문에 잘 대답했다.&lt;/p&gt;
&lt;p&gt;HR Interview를 너무 말아먹고 오히려 마음 편하게 봐서 잘 본 것 같기도 하다.&lt;/p&gt;
&lt;h2 id=&quot;offer&quot;&gt;Offer&lt;/h2&gt;
&lt;p&gt;합격하면 이런식으로 오퍼레터가 온다.&lt;/p&gt;
&lt;p&gt;Resume Screening - Phone Screening - Coding Test - HR Interview - PT Interview 라는 험난한 과정을 거쳐서 합격하게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SAP Labs Korea Vocational Training Program Intern 지원 및 합격 후기-1717150878671.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1390&quot; height=&quot;754&quot; src=&quot;https://ks1ksi.io/_astro/SAP%20Labs%20Korea%20Vocational%20Training%20Program%20Intern%20%EC%A7%80%EC%9B%90%20%EB%B0%8F%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1717150878671.jgEjtqkR_1g1tOA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;합격 이후 삼성전자 인턴, NH투자증권 인턴, 네이버 클라우드 인턴 등 진행중인 전형 전부 중단했다.&lt;/p&gt;
&lt;p&gt;SAP는 정말 가고싶은 회사였지만 토스페이먼츠 정규직 합격으로 인해 입사를 취소하게 되었다…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/%ED%86%A0%EC%8A%A4-3%EB%85%84-%EC%9D%B4%ED%95%98-server-developer-challenge-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/&quot;&gt;토스 3년 이하 Server Developer Challenge 지원 및 합격 후기&lt;/a&gt;&lt;/p&gt;</content:encoded><category>job</category><category>sap</category></item><item><title>Real MySQL 8.0 9장 옵티마이저와 힌트</title><link>https://ks1ksi.io/blog/real-mysql-80-9%EC%9E%A5-%EC%98%B5%ED%8B%B0%EB%A7%88%EC%9D%B4%EC%A0%80%EC%99%80-%ED%9E%8C%ED%8A%B8/</link><guid isPermaLink="true">https://ks1ksi.io/blog/real-mysql-80-9%EC%9E%A5-%EC%98%B5%ED%8B%B0%EB%A7%88%EC%9D%B4%EC%A0%80%EC%99%80-%ED%9E%8C%ED%8A%B8/</guid><description>Real MySQL 8.0 옵티마이저와 힌트 장 정리. 쿼리 실행 절차, 비용 기반 최적화, 실행 계획, DISTINCT와 임시 테이블 처리를 요약한다.</description><pubDate>Wed, 17 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;DBMS의 옵티마이저는 쿼리를 최적으로 실행하기 위해 각 테이블의 데이터가 어떤 분포로 저장되어 있는지 등의 정보를 참고하여 최적의 실행 계획을 수립한다.&lt;/p&gt;
&lt;p&gt;MySQL에서는 &lt;code&gt;EXPLAIN&lt;/code&gt; 이라는 명령으로 쿼리의 실행 계획을 확인할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;1-개요&quot;&gt;1. 개요&lt;/h2&gt;
&lt;h3 id=&quot;쿼리-실행-절차&quot;&gt;쿼리 실행 절차&lt;/h3&gt;
&lt;p&gt;MySQL 서버에서 쿼리가 실행되는 과정은 크게 세 단계로 나눌 수 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;사용자로부터 요청된 SQL 문장을 잘게 쪼개서 분리한다 (Parse Tree)
&lt;ul&gt;
&lt;li&gt;SQL 문장의 문법 오류를 검사&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SQL의 Parse Tree를 확인하면서 어떤 테이블부터 읽고 어떤 인덱스를 이용해 테이블을 읽을지 선택한다.
&lt;ul&gt;
&lt;li&gt;불필요한 조건 제거 등 복잡한 연산의 단순화&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;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;옵티마이저의-종류&quot;&gt;옵티마이저의 종류&lt;/h3&gt;
&lt;p&gt;크게 &lt;strong&gt;규칙 기반 최적화와 비용 기반 최적화&lt;/strong&gt; 두 가지로 나눌 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule-based optimizer&lt;/strong&gt;는 테이블의 레코드 건수나 선택도 등을 고려하지 않고 옵티마이저에 내장된 우선순위에 따라 실행 계획을 수립하는 방식이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cost-based optimizer&lt;/strong&gt;는 쿼리를 처리하기 위한 여러 방법을 만들고 각 단위 작업의 비용 정보와 대상 테이블의 예측된 통계 정보를 이용해 실행 계획별 비용을 산출한다.&lt;/p&gt;
&lt;p&gt;현재 대부분의 DBMS들은 &lt;strong&gt;Cost-based optimizer&lt;/strong&gt;를 사용중이다.&lt;/p&gt;
&lt;h2 id=&quot;기본-데이터-처리&quot;&gt;기본 데이터 처리&lt;/h2&gt;
&lt;h3 id=&quot;풀-테이블-스캔과-풀-인덱스-스캔&quot;&gt;풀 테이블 스캔과 풀 인덱스 스캔&lt;/h3&gt;
&lt;p&gt;풀 테이블 스캔은 인덱스를 사용하지 않고 테이블을 처음부터 끝까지 읽어서 요청된 결과를 처리한다.  MySQL 옵티마이저는 다음과 같은 조건일 때 주로 풀 테이블 스캔을 선택한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;테이블의 레코드 건수가 너무 작아서 인덱스를 통해 읽는 것보다 테이블을 직접 읽는 것이 빠를 때&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WHERE&lt;/code&gt; 절이나 &lt;code&gt;ON&lt;/code&gt; 절에 인덱스를 이용할 수 있는 적절한 조건이 없는 경우&lt;/li&gt;
&lt;li&gt;인덱스 레인지 스캔을 사용할 수 있어도 조건 일치 레코드 건수가 너무 많은 경우 (인덱스 샘플링 조사 결과)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;풀 테이블 스캔시 페이지 하나씩 읽지 않고 백그라운드 스레드가 한번에 여러 페이지를 읽어 버퍼 풀에 저장해준다. 이를 Read Ahead 라고 한다.&lt;/p&gt;
&lt;p&gt;풀 인덱스 스캔도에서도 동일하게 작동한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;해당 쿼리는 용량이 더 작은 인덱스를 풀 스캔한다.&lt;/p&gt;
&lt;h3 id=&quot;병렬-처리&quot;&gt;병렬 처리&lt;/h3&gt;
&lt;p&gt;MySQL 8.0 이후부터 &lt;code&gt;innodb_parallel_read_threads&lt;/code&gt; 시스템 변수로 하나의 쿼리를 최대 몇 개의 스레드를 이용해서 처리할지 설정할 수 있다. 물론 스레드 개수를 무한정 늘려 봤자 코어 개수가 정해져 있기 때문에 성능이 무한정 늘어나지는 않는다.&lt;/p&gt;
&lt;h3 id=&quot;order-by-처리&quot;&gt;ORDER BY 처리&lt;/h3&gt;
&lt;p&gt;인덱스를 이용한 정렬, &lt;strong&gt;Filesort&lt;/strong&gt;를 이용한 정렬 두 가지 방식이 존재한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;인덱스
&lt;ul&gt;
&lt;li&gt;장점 : 인덱스는 이미 정렬되어 있어서 조회가 매우 빠르다. 순서대로 읽기만 하면 된다.&lt;/li&gt;
&lt;li&gt;단점 : INSERT, UPDATE, DELETE 작업 시 부가적인 인덱스 추가, 삭제 작업이 필요해서 느리다. 인덱스 때문에 디스크 공간이 더 많이 필요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Filesort
&lt;ul&gt;
&lt;li&gt;장점 : 인덱스를 생성하지 않아도 되므로 INSERT, UPDATE, DELETE가 더 빠르다.&lt;/li&gt;
&lt;li&gt;단점 : 정렬 작업이 쿼리를 실행할 때 처리되므로 레코드 대상 건수가 많아질수록 응답 속도가 느려진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MySQL 서버에서 인덱스를 사용하지 않고 별도의 정렬 처리를 수행했는지 여부를 알 수 있다. 실행 계획의 Extra 컬럼에 “Using Filesort” 메시지가 표시된다.&lt;/p&gt;
&lt;h4 id=&quot;소트-버퍼&quot;&gt;소트 버퍼&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;정렬을 위한 별도의 메모리 공간&lt;/strong&gt;을 &lt;strong&gt;Sort Buffer&lt;/strong&gt;라고 한다. 정렬이 필요한 경우에만 할당된다.&lt;/p&gt;
&lt;p&gt;정렬해야 할 레코드의 건수가 매우 많아서 소트 버퍼로만 해결할 수 없다면 어떻게 될까? 정렬해야 하는 레코드를 여러 조각으로 나눠서 정렬한다. 이 때 임시 저장 공간으로 &lt;strong&gt;디스크를 사용&lt;/strong&gt;하게 된다. 이후 각 버퍼 크기만큼 정렬된 레코드를 다시 병합하면서 정렬한다.&lt;/p&gt;
&lt;p&gt;이러한 과정은 디스크 읽기, 쓰기를 유발한다.&lt;/p&gt;
&lt;p&gt;Sort Buffer 크기를 너무 크게 만들면 메모리를 할당하는 과정에서 오버헤드가 발생할 수 있고, OOM이 발생하여 프로세스가 종료될 수도 있다.&lt;/p&gt;
&lt;h4 id=&quot;정렬-알고리즘&quot;&gt;정렬 알고리즘&lt;/h4&gt;
&lt;p&gt;레코드를 정렬할 때 레코드 전체를 소트 버퍼에 담아서 정렬할지, 정렬 기준이 되는 컬럼만 소트 버퍼에 담을지에 따라 싱글 패스와 투 패스 2가지 정렬 모드로 나눌 수 있다.&lt;/p&gt;
&lt;p&gt;투 패스 방식은 테이블을 두 번 읽어야 한다. 싱글 패스 정렬 방식은 더 많은 소트 버퍼 공간을 사용한다. 최신 버전은 일반적으로 &lt;strong&gt;싱글 패스 정렬 방식&lt;/strong&gt;을 사용한다.&lt;/p&gt;
&lt;p&gt;만약 레코드의 크기가 &lt;code&gt;max_length_for_sort_data&lt;/code&gt; 변수에 설정된 값보다 크거나, &lt;code&gt;BLOB&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt; 타입의 컬럼이 대상이 되는 경우 &lt;strong&gt;투 패스 정렬 방식&lt;/strong&gt;을 사용한다.&lt;/p&gt;
&lt;h4 id=&quot;정렬-처리-방법&quot;&gt;정렬 처리 방법&lt;/h4&gt;
&lt;p&gt;다음 세 가지 방법 중 하나로 정렬이 처리된다. 아래로 갈수록 처리 속도가 떨어진다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;인덱스를 이용한 정렬&lt;/li&gt;
&lt;li&gt;조인에서 드라이빙 테이블만 정렬 =&gt; Using filesort&lt;/li&gt;
&lt;li&gt;조인 결과를 임시 테이블에 저장 후 정렬 =&gt; Using temporary; Using filesort&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;먼저 옵티마이저는 정렬 처리를 위해 인덱스르 이용할 수 있는지 검토한다. 인덱스를 사용할 수 없다면 &lt;code&gt;WHERE&lt;/code&gt; 조건에 일치하는 레코드를 소트 버퍼에 저장하면서 정렬한다.&lt;/p&gt;
&lt;p&gt;MySQL 옵티마이저는 정렬 대상 레코드를 최소화하기 위해 2가지 방법 중 하나를 선택한다&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;조인의 드라이빙 테이블만 정렬한 다음 조인 수행&lt;/li&gt;
&lt;li&gt;조인이 끝나고 일치하는 레코드를 모두 가져온 후 정렬을 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;조인이 수행되면서 레코드 크기가 늘어나기 때문에 전자가 더 효율적이다.&lt;/p&gt;
&lt;h5 id=&quot;인덱스를-이용한-정렬&quot;&gt;인덱스를 이용한 정렬&lt;/h5&gt;
&lt;p&gt;반드시 &lt;code&gt;ORDER BY&lt;/code&gt;에 명시된 칼럼이 &lt;strong&gt;제일 먼저 읽는 테이블(조인이 사용된 경우 드라이빙 테이블)&lt;/strong&gt; 에 속하고 &lt;code&gt;ORDER BY&lt;/code&gt;의 순서대로 생성된 인덱스가 있어야 한다. &lt;code&gt;WHERE&lt;/code&gt; 절에 제일 먼저 읽는 테이블의 컬럼에 대한 조건이 있다면 그 조건과 &lt;code&gt;ORDER BY&lt;/code&gt;는 같은 인덱스를 사용해야 한다.&lt;/p&gt;
&lt;p&gt;당연하지만 해시 인덱스나 전문 검색 인덱스에서는 인덱스를 이용한 정렬을 수행할 수 없다.&lt;/p&gt;
&lt;h5 id=&quot;조인의-드라이빙-테이블만-정렬&quot;&gt;조인의 드라이빙 테이블만 정렬&lt;/h5&gt;
&lt;blockquote&gt;
&lt;p&gt;드라이빙 테이블은 조인 쿼리에서 가장 먼저 스캔되는 테이블로, 다른 테이블과의 조인 과정에서 기준이 되는 테이블입니다. 일반적으로 처리해야 할 데이터의 양이 적은 테이블을 드라이빙 테이블로 선택하여 쿼리 성능을 향상시킵니다. 강력한 필터링 조건(즉, 결과를 크게 줄일 수 있는 조건)을 가진 테이블이 유리합니다. 인덱스를 효과적으로 사용할 수 있는 테이블을 드라이빙 테이블로 설정하여 접근 속도를 빠르게 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;조인이 수행되면 레코드 건수도 늘어나고 레코드 하나하나의 크기도 늘어난다. 그래서 드라이빙 테이블을 먼저 정렬한 다음 조인을 실행하면 효율적이다. 이 방법으로 정렬이 수행되려면 드라이빙 테이블의 컬럼만으로 &lt;code&gt;ORDER BY&lt;/code&gt; 절을 작성해야 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees e, salaries s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s.emp_no&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;e.emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;AND&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.emp_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;BETWEEN&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 102&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 110&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.last_name;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; 절의 조건은 employees 테이블의 PK를 사용한다. 또 salaries의 조인 컬럼인 emp_no에 인덱스가 존재한다. 따라서 옵티마이저는 &lt;strong&gt;employees 테이블을 드라이빙 테이블로 선택&lt;/strong&gt;한다.&lt;/p&gt;
&lt;h5 id=&quot;임시-테이블을-이용한-정렬&quot;&gt;임시 테이블을 이용한 정렬&lt;/h5&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees e, salaries s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s.emp_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;AND&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.emp_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;BETWEEN&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 102&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 110&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s.salary;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 쿼리는 정렬 기준이 드라이빙 테이블이 아닌 드리븐 테이블에 존재한 컬럼이다. 이 경우 &lt;strong&gt;조인 결과를 임시 테이블에 저장하고, 그 결과를 다시 정렬&lt;/strong&gt;해야 한다. 가장 느린 정렬 방법이다.&lt;/p&gt;
&lt;h5 id=&quot;정렬-처리-방법의-성능-비교&quot;&gt;정렬 처리 방법의 성능 비교&lt;/h5&gt;
&lt;p&gt;일반적으로 &lt;code&gt;LIMIT&lt;/code&gt; 을 사용하면 처리하는 양을 줄일 수 있을 것이라고 생각한다. 그러나 &lt;code&gt;ORDER BY&lt;/code&gt; 혹은 &lt;code&gt;GROUP BY&lt;/code&gt; 같은 작업은 &lt;code&gt;WHERE&lt;/code&gt; 조건을 만족하는 결과를 &lt;code&gt;LIMIT&lt;/code&gt;만큼만 가져와서 처리할 수 없고 모두 가져온 후 정렬을 수행하거나 그루핑을 한 후 &lt;code&gt;LIMIT&lt;/code&gt;을 처리하게 된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;스트리밍 방식: 서버 쪽에서 레코드가 검색될 때마다 바로바로 클라이언트로 결과를 전송해주는 방식이다. &lt;code&gt;LIMIT&lt;/code&gt;을 사용하면 처리량을 줄일 수 있다.&lt;/li&gt;
&lt;li&gt;버퍼링 방식: 조건을 만족하는 모든 레코드를 가져와서 정렬한 후 차례대로 보내야 한다. &lt;code&gt;LIMIT&lt;/code&gt;을 사용해도 처리량이 개선되지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;ORDER BY&lt;/code&gt; 처리 방식에서 &lt;strong&gt;인덱스를 이용한 정렬 방식&lt;/strong&gt;만 스트리밍 형태의 처리이고 나머지는 모두 버퍼링 방식이다.&lt;/p&gt;
&lt;h3 id=&quot;group-by-처리&quot;&gt;GROUP BY 처리&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;GROUP BY&lt;/code&gt;도 쿼리가 스트리밍 될 수 없게 만든다. 똑같이 인덱스를 이용하는 경우와 이용하지 못하는 경우로 나눌 수 있다.&lt;/p&gt;
&lt;h4 id=&quot;인덱스-스캔&quot;&gt;인덱스 스캔&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;ORDER BY&lt;/code&gt;와 마찬가지로 드라이빙 테이블에 속한 컬럼만 이용해 그루핑할 때 인덱스 스캔을 하게 된다. 이미 정렬된 인덱스를 차례대로 읽으면서 그루핑을 한다.&lt;/p&gt;
&lt;h4 id=&quot;루스-인덱스-스캔&quot;&gt;루스 인덱스 스캔&lt;/h4&gt;
&lt;p&gt;루스 인덱스 스캔은 인덱스의 레코드를 건너뛰면서 필요한 부분만 읽어서 가져오는 방식이다. 루스 인덱스 스캔을 사용할 때는 실행 계획의 Extra 컬럼에 “Using index for group-by” 라는 코멘트가 표시된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;EXPLAIN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; salaries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; from_date&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&apos;1985-03-01&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	GROUP BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; emp_no;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(emp_no, from_date)로 인덱스가 생성되어 있다고 하자. 이 경우 &lt;code&gt;WHERE&lt;/code&gt; 절에 있는 조건은 인덱스 레인지 스캔을 사용할 수 없다.&lt;/p&gt;
&lt;p&gt;하지만 이 쿼리의 실행 계획은 인덱스 레인지 스캔을 사용했으며, &lt;code&gt;GROUP BY&lt;/code&gt; 처리까지 인덱스를 사용했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;(emp_no, from_date) 인덱스를 차례대로 스캔하면서 emp_no의 첫 번째 유일한 값(10001)을 찾아 낸다.&lt;/li&gt;
&lt;li&gt;(emp_no, from_date) 인덱스에서  emp_no=10001인 것 중에서 from_date=‘1985-03-01’인 레코드만 가져온다. AND 조건으로 (emp_no, from_date) 인덱스를 검색하는 것과 비슷하다.&lt;/li&gt;
&lt;li&gt;(emp_no, from_date) 인덱스에서 그 다음 emp_no를 가져온다.&lt;/li&gt;
&lt;li&gt;반복한다&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;임시-테이블-이용&quot;&gt;임시 테이블 이용&lt;/h4&gt;
&lt;p&gt;인덱스를 사용하지 못하는 경우 임시 테이블을 만든다. 이 때 &lt;code&gt;GROUP BY&lt;/code&gt; 절의 컬럼들로 구성된 유니크 인덱스를 가진 테이블을 만들어서 중복 제거와 집합 함수 연산을 수행한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;EXPLAIN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.last_name, &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(s.salary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees e, salaries s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s.emp_no&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;e.emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	GROUP BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.last_name;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 쿼리는 다음과 같은 임시 테이블을 생성한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; TEMPORARY &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;TABLE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ... (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	last_name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	salary &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;INT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	UNIQUE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ux_lastname (last_name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그리고 조인 결과를 한 건씩 가져와 임시 테이블에서 중복 체크를 하면서 &lt;code&gt;INSERT&lt;/code&gt; 혹은 &lt;code&gt;UPDATE&lt;/code&gt;를 실행한다. 별도의 정렬 작업 없이 &lt;code&gt;GROUP BY&lt;/code&gt;가 처리된다.&lt;/p&gt;
&lt;h3 id=&quot;distinct-처리&quot;&gt;DISTINCT 처리&lt;/h3&gt;
&lt;p&gt;특정 컬럼의 유니크한 값만 조회하려면 &lt;code&gt;DISTINCT&lt;/code&gt;를 사용한다. 크게 &lt;code&gt;MIN()&lt;/code&gt;, &lt;code&gt;MAX()&lt;/code&gt;, &lt;code&gt;COUNT()&lt;/code&gt; 같은 집합 함수와 사용되는 경우, 집합 함수가 없는 경우 2가지로 나눌 수 있다.&lt;/p&gt;
&lt;h4 id=&quot;select-distinct&quot;&gt;SELECT DISTINCT&lt;/h4&gt;
&lt;p&gt;단순히 &lt;code&gt;SELECT&lt;/code&gt; 되는 레코드 중에서 유니크한 레코드만 가져오고자 하는 경우 &lt;code&gt;GROUP BY&lt;/code&gt;와 똑같이 처리된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT DISTINCT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; emp_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; salaries;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; emp_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; salaries &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; emp_no;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;두 쿼리는 내부적으로 같은 작업을 수행한다.&lt;/p&gt;
&lt;h4 id=&quot;집합-함수와-함께-사용된-distinct&quot;&gt;집합 함수와 함께 사용된 DISTINCT&lt;/h4&gt;
&lt;p&gt;집합 함수가 없는 쿼리에서는 조회하는 모든 칼럼의 조합이 유니크한 것들만 가져온다. 하지만 집합 함수 내에서 사용되는 경우는 그 인자로 전달된 칼럽값이 유니크한 것들을 가져온다.&lt;/p&gt;
&lt;p&gt;집합 함수와 함께 사용할 때는 항상 임시 테이블을 생성하게 된다. 하지만 실행 계획에는 따로 표시되지 않는다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;EXPLAIN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;DISTINCT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s.salary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees e, salaries s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.emp_no&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;s.emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	and&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.emp_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;BETWEEN&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 101&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 110&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 쿼리는 조인 결과에서 salary 칼럼의 값만 저장하기 위한 임시 테이블을 만들어서 사용한다. 만약 &lt;code&gt;COUNT(DISTINCT )&lt;/code&gt;가 더 추가된다면 임시 테이블도 추가된다.&lt;/p&gt;
&lt;p&gt;하지만 인덱스된 컬럼에 대해 &lt;code&gt;COUNT(DISTINCT )&lt;/code&gt;를 처리하는 경우는 인덱스를 타면서 임시 테이블 없이 최적화된 처리를 할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;내부-임시-테이블-활용&quot;&gt;내부 임시 테이블 활용&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MySQL 엔진이 스토리지 엔진으로부터 받아온 레코드를 &lt;strong&gt;정렬하거나 그루핑&lt;/strong&gt;할 때는 &lt;strong&gt;내부적인 임시 테이블(Internal temporary table)을&lt;/strong&gt; 사용한다.&lt;/li&gt;
&lt;li&gt;내부적(internal)이라 표현하는 이유는 &lt;code&gt;CREATE TEMPORARY TABLE&lt;/code&gt; 명령어로 만든 임시 테이블과는 다르기 때문이다.&lt;/li&gt;
&lt;li&gt;내부적인 임시 테이블은 메모리에 생성됐다가 테이블의 크기가 커지면 디스크로 옮겨진다. 또한 다른 세션이나 쿼리에서는 볼 수 없고 쿼리가 완료되면 자동으로 삭제된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;메모리-임시-테이블과-디스크-임시-테이블&quot;&gt;메모리 임시 테이블과 디스크 임시 테이블&lt;/h4&gt;
&lt;p&gt;MySQL 8.0부터 TempTable이라는 스토리지 엔진이 도입되었다. &lt;code&gt;temptable_max_ram&lt;/code&gt; 기본값 1G까지 메모리 사용 가능하고 더 커지면 디스크에 기록하게 된다. 이 때 두 가지 방식으로 저장할 수 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MMAP 파일&lt;/li&gt;
&lt;li&gt;InnoDB 테이블&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MMAP는 디스크 파일을 메모리에 매핑하여 마치 메모리처럼 접근할 수 있다. 대신 InnoDB 테이블에서 사용할 수 있는 크래시 복구 등의 기능을 사용할 수 없다.&lt;/p&gt;
&lt;h4 id=&quot;임시-테이블이-필요한-쿼리&quot;&gt;임시 테이블이 필요한 쿼리&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ORDER BY&lt;/code&gt;와 &lt;code&gt;GROUP BY&lt;/code&gt;에 명시된 칼럼이 다른 쿼리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ORDER BY&lt;/code&gt;와 &lt;code&gt;GROUP BY&lt;/code&gt;에 명시된 칼럼이 조인의 순서상 첫 번째 테이블이 아닌 쿼리&lt;/li&gt;
&lt;li&gt;distinct와 &lt;code&gt;ORDER BY&lt;/code&gt;가 동시에 쿼리에 존재하는 경우 또는 &lt;code&gt;DISTINCT&lt;/code&gt; 가 인덱스로 처리되지 못하는 쿼리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UNION&lt;/code&gt;이나 &lt;code&gt;UNION DISTINCT&lt;/code&gt; 가 사용된 쿼리(select_type 칼럼이 &lt;code&gt;UNION RESULT&lt;/code&gt;인 경우)&lt;/li&gt;
&lt;li&gt;쿼리의 실행 계획에서 select_type이 &lt;code&gt;DERIVED&lt;/code&gt;인 쿼리&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 밖에도 인덱스를 사용하지 못할 때는 내부 임시 테이블을 생성해야 하는 경우가 많다.&lt;/p&gt;
&lt;h4 id=&quot;임시-테이블이-디스크에-생성되는-경우&quot;&gt;임시 테이블이 디스크에 생성되는 경우&lt;/h4&gt;
&lt;p&gt;내부 임시 테이블은 기본적으로 메모리에 만들어 지지만 다음과 같은 조건을 만족하는 경우 메모리 기반 임시 테이블을 사용할 수 없게 된다. 디스크 기반 임시 테이블을 사용하게 된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;UNION&lt;/code&gt; 이나 &lt;code&gt;UNION ALL&lt;/code&gt;에서 &lt;code&gt;SELECT&lt;/code&gt;되는 칼럼 중에서 길이가 512바이트 이상인 크기의 칼럼이 있는 경우&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GROUP BY&lt;/code&gt;나 &lt;code&gt;DISTINCT&lt;/code&gt; 칼럼에서 512바이트 이상인 크기의 칼럼이 있는 경우&lt;/li&gt;
&lt;li&gt;메모리 임시 테이블의 크기가 &lt;code&gt;temp_table_max_ram&lt;/code&gt; 시스템 변수 값보다 큰 경우&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>cs</category><category>db</category></item><item><title>Real MySQL 8.0 8장 인덱스</title><link>https://ks1ksi.io/blog/real-mysql-80-8%EC%9E%A5-%EC%9D%B8%EB%8D%B1%EC%8A%A4/</link><guid isPermaLink="true">https://ks1ksi.io/blog/real-mysql-80-8%EC%9E%A5-%EC%9D%B8%EB%8D%B1%EC%8A%A4/</guid><description>Real MySQL 8.0 인덱스 장 정리. 디스크 I/O, B-Tree 인덱스, 클러스터링 인덱스, 다중 칼럼 인덱스와 인덱스 스캔 방식을 요약한다.</description><pubDate>Sat, 06 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;1-디스크-읽기-방식&quot;&gt;1. 디스크 읽기 방식&lt;/h2&gt;
&lt;p&gt;랜덤 I/O, 순차 I/O 두 가지 디스크 읽기 방식을 간단히 살펴 보자.&lt;/p&gt;
&lt;p&gt;3개의 페이지를 디스크에 기록하기 위해, 랜덤 I/O와 순차 I/O는 몇 번의 시스템 콜을 요청할까?
순차 I/O는 시스템 콜을 한 번만 요청해도 되지만 랜덤 I/O는 총 3번 요청해야 한다. 순차 I/O는 디스크 헤드를 한 번 움직이지만, 랜덤 I/O는 3번 움직인다. 데이터를 읽거나 쓰는 성능은 디스크 헤드를 얼마나 적게 움직이느냐가 결정하게 된다.&lt;/p&gt;
&lt;p&gt;여러 번의 랜덤 I/O 요청이 부하를 일으키기 때문에, MySQL은 이런 요청들을 모아 한 번에 처리하여 디스크 부하를 줄이는 그룹 커밋, 바이너리 로그 버퍼, InnoDB 로그 버퍼 등의 기능을 가지고 있다.&lt;/p&gt;
&lt;p&gt;쿼리를 튜닝해서 랜덤 I/O를 순차 I/O로 바꾸는 것은 쉽지 않고, 랜덤 I/O를 최대한 줄이는 것이 쿼리 튜닝의 목표가 된다.&lt;/p&gt;
&lt;h2 id=&quot;2-인덱스란&quot;&gt;2. 인덱스란?&lt;/h2&gt;
&lt;p&gt;책을 사서 뒷부분을 펼쳐 보면 ‘찾아보기’ 라는 부분이 있다. 단어와 해당 단어가 나오는 페이지가 key-value pair를 이루고 있다. 그리고 단어가 정렬되어 있다. 책을 처음부터 읽으면서 해당 단어가 나오는 부분을 찾는 것 보다 훨씬 빠르게 찾을 수 있다.&lt;/p&gt;
&lt;p&gt;DBMS도 비슷하다. 칼럼의 값과 해당 레코드가 저장된 주소를 key-value pair를 이루도록 하고, 칼럼의 값을 정렬해서 보관해 둔다.&lt;/p&gt;
&lt;p&gt;즉, 인덱스는 &lt;code&gt;SortedList&lt;/code&gt;이다. 데이터가 삽입되면, 정렬을 해야 하기 때문에 &lt;code&gt;ArrayList&lt;/code&gt;보다 삽입 속도가 느리지만, 데이터를 찾는 속도는 훨씬 빠르다. 따라서 인덱스가 많은 테이블은 &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;가 느려진다. 대신 &lt;code&gt;SELECT&lt;/code&gt;는 훨씬 빠르게 처리할 수 있다.&lt;/p&gt;
&lt;p&gt;인덱스를 추가할지 말지는 &lt;strong&gt;“저장 속도를 얼마나 희생할 수 있는지, 읽기 속도를 얼마나 빠르게 만들어야 하는지”&lt;/strong&gt; 에 따라 결정해야 한다. &lt;code&gt;WHERE&lt;/code&gt; 절에 사용되는 칼럼이라고 전부 인덱스를 걸어 버리면 저장 속도가 현저히 떨어질 것이다.&lt;/p&gt;
&lt;p&gt;인덱스는 알고리즘, 중복 값 허용 여부 등 여러 가지 기준으로 나눌 수 있다. 지금부터 Key == Index 라고 생각하자.&lt;/p&gt;
&lt;p&gt;우선 역할별로 구분해 보면 Primary Key 그리고 Secondary Key로 구분할 수 있다. PK는 해당 레코드를 대표하는 값으로 중복을 허용하지 않고, &lt;code&gt;NULL&lt;/code&gt;도 허용하지 않는다. PK를 제외한 나머지 인덱스는 보조 키이다.&lt;/p&gt;
&lt;p&gt;알고리즘별로 나눌 경우 대표적으로 두 가지 인덱스가 있다. B-Tree 인덱스, 그리고 Hash 인덱스이다. B-Tree 인덱스는 칼럼의 원래 값을 이용해 인덱싱하고, Hash 인덱스는 칼럼의 값에 해시 연산을 수행하여 인덱싱한다. 때문에 Hash 인덱스는 부분 일치나 범위 검색을 처리할 수 없다.&lt;/p&gt;
&lt;p&gt;데이터의 중복 여부로 나누면 Unique 인덱스, Non-Unique 인덱스로 나눌 수 있다. Unique 하다는 사실은 쿼리를 실행할 때 아주 중요한 사실이다. Equal 조건으로 검색했을 때 하나의 결과를 찾으면 더 이상 찾지 않아도 되기 때문이다.&lt;/p&gt;
&lt;p&gt;전문 검색 인덱스, 공간 검색 인덱스 등등 여러 종류의 인덱스가 존재한다.&lt;/p&gt;
&lt;h2 id=&quot;3-b-tree-인덱스&quot;&gt;3. B-Tree 인덱스&lt;/h2&gt;
&lt;p&gt;B-Tree는 가장 중요하고, 가장 일반적으로 사용되는 인덱스이다. B-Tree의 ‘B’는 “Balanced”이다. 인덱스로 설정한 원본 값을 변형시키지 않고, &lt;strong&gt;정렬된 상태를 유지&lt;/strong&gt;한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Real MySQL 8.0 8장 인덱스-1712426195346.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1850&quot; height=&quot;982&quot; src=&quot;https://ks1ksi.io/_astro/Real%20MySQL%208.0%208%EC%9E%A5%20%EC%9D%B8%EB%8D%B1%EC%8A%A4-1712426195346.DrBJKcAo_SRwhI.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;여러가지 변형이 존재한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Real MySQL 8.0 8장 인덱스-1712427542357.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1672&quot; height=&quot;834&quot; src=&quot;https://ks1ksi.io/_astro/Real%20MySQL%208.0%208%EC%9E%A5%20%EC%9D%B8%EB%8D%B1%EC%8A%A4-1712427542357.i9EasXIV_ZsYhoY.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Real MySQL 8.0 8장 인덱스-1712428256696.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1378&quot; height=&quot;710&quot; src=&quot;https://ks1ksi.io/_astro/Real%20MySQL%208.0%208%EC%9E%A5%20%EC%9D%B8%EB%8D%B1%EC%8A%A4-1712428256696._F3WLg60_2dcUpE.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Real MySQL 8.0 8장 인덱스-1712426289895.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1702&quot; height=&quot;882&quot; src=&quot;https://ks1ksi.io/_astro/Real%20MySQL%208.0%208%EC%9E%A5%20%EC%9D%B8%EB%8D%B1%EC%8A%A4-1712426289895.o7vpDGyo_Z25973i.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;InnoDB는 B+Tree 방식을 사용한다. &lt;strong&gt;리프 노드에만 데이터가 저장&lt;/strong&gt;된다. 책에서는 B-Tree 라고 묶어서 부르고 있다.&lt;/p&gt;
&lt;h3 id=&quot;구조-및-특성&quot;&gt;구조 및 특성&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Real MySQL 8.0 8장 인덱스-1712427633811.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1760&quot; height=&quot;906&quot; src=&quot;https://ks1ksi.io/_astro/Real%20MySQL%208.0%208%EC%9E%A5%20%EC%9D%B8%EB%8D%B1%EC%8A%A4-1712427633811.CUUoXIH-_jFTp7.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;B-Tree는 루트 노드 - 브랜치 노드 - 리프 노드의 구조를 가지고 있다. 반드시 최상위에 하나의 루트 노드를 가지고 있다. 최하위의 리프 노드들은 &lt;strong&gt;실제 데이터 레코드를 찾아가기 위한 주소&lt;/strong&gt;를 가지고 있다. 다른 노드들은 하위 노드들의 주소를 가지고 있다(B+Tree).&lt;/p&gt;
&lt;p&gt;인덱스는 테이블의 키 칼럼만 가지고 있기 때문에 나머지 칼럼을 읽으러면 실제 레코드를 찾아서 읽어야 한다. InnoDB 스토리지 엔진을 사용하는 경우, PK를 주소처럼 활용한다. 세컨더리 인덱스를 통해 레코드를 찾는 경우, 리프 노드에 적혀 있는 PK를 얻고, PK 인덱스의 리프 페이지에 저장된 레코드를 읽는 방식이다. 실제 물리적인 주소 대신 PK를 사용하는 것은 장단점이 존재한다. 클러스터링 인덱스를 다룰 때 알아보도록 하자.&lt;/p&gt;
&lt;h3 id=&quot;b-tree-인덱스-키-추가-및-삭제&quot;&gt;B-Tree 인덱스 키 추가 및 삭제&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html&quot;&gt;B+Tree Visualization&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;삽입&quot;&gt;삽입&lt;/h4&gt;
&lt;p&gt;&lt;img alt=&quot;Real MySQL 8.0 8장 인덱스-1712428048683.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1446&quot; height=&quot;912&quot; src=&quot;https://ks1ksi.io/_astro/Real%20MySQL%208.0%208%EC%9E%A5%20%EC%9D%B8%EB%8D%B1%EC%8A%A4-1712428048683.AmR4K2WV_eNfNg.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;새로운 키 값이 트리에 추가될 때, 키 값을 이용해 트리에서 저장될 위치를 찾아야 한다. 저장될 위치가 결정되면 키 값과 레코드의 주소 정보를 트리의 리프 노드에 저장한다.
이 때 리프 노드가 꽉 차서 공간이 부족한 경우, 노드를 반으로 나눈다. 분할 시 중간값이 부모 노드로 복사된다.&lt;/p&gt;
&lt;p&gt;인덱스 추가로 인해 &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt; 문장이 어떤 영향을 받을 지 예측하는 방법이 있다. 테이블에 레코드를 추가하는 비용을 1이라고 했을 때, 인덱스 하나당 1.5의 비용이 추가로 든다고 예측하는 것이다. 인덱스가 3개 걸려 있는 테이블에 레코드를 추가하는 데 드는 비용은 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1.5&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;5.5&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1 + (1.5 \times 3) = 5.5&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;5.5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 될 것이다.&lt;/p&gt;
&lt;p&gt;이 비용의 대부분은 디스크 I/O이다.&lt;/p&gt;
&lt;h4 id=&quot;삭제&quot;&gt;삭제&lt;/h4&gt;
&lt;p&gt;&lt;img alt=&quot;Real MySQL 8.0 8장 인덱스-1712428297149.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1432&quot; height=&quot;934&quot; src=&quot;https://ks1ksi.io/_astro/Real%20MySQL%208.0%208%EC%9E%A5%20%EC%9D%B8%EB%8D%B1%EC%8A%A4-1712428297149.CnrUF7sa_bhUnk.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;삭제할 키가 있는 리프 노드를 찾고, 해당 키를 삭제한다. 이 때 리프 노드에 존재하는 키 개수가 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M/2 - 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/2&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개가 되면, 형제 노드에서 키를 빌려 오거나 합쳐서 트리의 특성을 만족시킨다.&lt;/p&gt;
&lt;p&gt;InnoDB는 실제로 데이터를 즉시 삭제하지 않고, 해당 공간을 재활용할 수 있도록 삭제되었다는 표시만 한다(Lazy Deletion).&lt;/p&gt;
&lt;h4 id=&quot;변경&quot;&gt;변경&lt;/h4&gt;
&lt;p&gt;단순히 노드에 있는 값을 변경만 하면 트리 구조가 깨진다. 먼저 키 값을 삭제한 후, 다시 새로운 키 값을 추가하는 형태로 처리할 수 있다.&lt;/p&gt;
&lt;h4 id=&quot;검색&quot;&gt;검색&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;UPDATE&lt;/code&gt;나 &lt;code&gt;DELETE&lt;/code&gt;를 위해 키를 검색해야 한다. 이 때 트리를 탐색하며 키를 찾는다.
100% 일치, 전방 일치, 부등호 연산에 인덱스가 사용된다.  함수 연산 등으로 값이 변경되면 인덱스를 이용할 수 없다.&lt;/p&gt;
&lt;p&gt;InnoDB 테이블에서 지원하는 레코드 락, 넥스트 키 락이 검색을 수행한 인덱스를 잠근 후 테이블의 레코드를 잠그는 방식으로 구현되어 있다. 인덱스가 적절히 설정되어 있지 않다면, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;를 수행할 때 &lt;strong&gt;테이블 전체가 잠기는 참사&lt;/strong&gt;가 일어날 수 있으니 조심해야 한다.&lt;/p&gt;
&lt;h3 id=&quot;b-tree-인덱스-사용에-영향을-미치는-요소&quot;&gt;B-Tree 인덱스 사용에 영향을 미치는 요소&lt;/h3&gt;
&lt;h4 id=&quot;인덱스-키-값의-크기&quot;&gt;인덱스 키 값의 크기&lt;/h4&gt;
&lt;p&gt;InnoDB 스토리지 엔진은 디스크에 데이터를 저장하는 기본 단위를 &lt;strong&gt;페이지(Page)&lt;/strong&gt; 라고 한다. 디스크의 모든 읽기 쓰기 작업의 최소 단위가 된다. 인덱스도 결국은 페이지 단위로 관리된다.&lt;/p&gt;
&lt;p&gt;일반적으로 DBMS의 B-Tree의 자식 노드 개수는 가변적이다. 자식 노드 개수는 인덱스의 페이지 크기, 그리고 키 값의 크기에 따라 결정된다.&lt;/p&gt;
&lt;p&gt;InnoDB 페이지 사이즈는 기본적으로 16KB이다. 인덱스 키 값이 16바이트, 자식 노드 주소를 나타내는 공간이 12바이트라고 하면, 페이지 하나 당 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;16&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1024&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;16&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;12&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;585&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;16 \times 1024 / (16 + 12) = 585&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1024/&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;585&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 개의 키를 저장할 수 있다. 인덱스 키 값이 16바이트가 아닌 32바이트가 된다면, 페이지당 저장할 수 있는 인덱스 키가 줄어들 것이다.&lt;/p&gt;
&lt;p&gt;이렇게 되면 디스크에 더 여러 번 접근해야 한다.&lt;/p&gt;
&lt;h4 id=&quot;b-tree-깊이&quot;&gt;B-Tree 깊이&lt;/h4&gt;
&lt;p&gt;인덱스 키 값이 16바이트, B-Tree 깊이가 3인 경우 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;585&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;200&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;201&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;625&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;585^{3} = 200,201,625&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;58&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;625&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 키 값을 담을 수 있지만, 32바이트로 늘어나면  약 5천만개정도로 줄어든다.&lt;/p&gt;
&lt;p&gt;인덱스 키 값의 크기는 가능하면 작은 게 좋다.&lt;/p&gt;
&lt;p&gt;실제로 B-Tree의 깊이가 5단계 이상이 되는 경우는 거의 없다.&lt;/p&gt;
&lt;h4 id=&quot;기수성&quot;&gt;기수성&lt;/h4&gt;
&lt;p&gt;Cardinality는 키 값 중 고유한 값의 수를 의미한다. Cardinality가 높을수록 인덱스 검색 성능이 좋아진다.&lt;/p&gt;
&lt;h4 id=&quot;읽어야-하는-레코드의-수&quot;&gt;읽어야 하는 레코드의 수&lt;/h4&gt;
&lt;p&gt;전체 100만 건의 레코드 중 50만 건을 읽어와야 하는 상황이라면 인덱스를 통해 50만건을 검색하는 것 보다 테이블을 모두 읽어서 필요한 레코드만 가려내는 방식으로 처리하는 것이 좋을 것이다. 일반적인 DBMS의 옵티마이저는 테이블에서 레코드 1건을 읽는 것보다 인덱스를 통해 레코드를 읽는 것을 4~5배 비싼 작업으로 예측한다.&lt;/p&gt;
&lt;h3 id=&quot;b-tree-인덱스를-통한-데이터-읽기&quot;&gt;B-Tree 인덱스를 통한 데이터 읽기&lt;/h3&gt;
&lt;h4 id=&quot;인덱스-레인지-스캔&quot;&gt;인덱스 레인지 스캔&lt;/h4&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; first_name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;BETWEEN&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;Ebbe&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;GAD&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;라는 쿼리가 있다고 해보자. 인덱스 레인지 스캔은 검색해야 할 인덱스의 범위가 결정됐을 때 사용하는 방식이다. 루트 노드부터 비교하며 필요한 레코드의 시작 지점을 찾고, 거기서부터 순서대로 읽고, 스캔을 멈춰야 할 위치에 다다르면 지금까지 읽은 레코드를 반환하면 된다.&lt;/p&gt;
&lt;p&gt;레코드의 주소가 적혀 있고, 실제 데이터 파일의 레코드를 가져 와야 할 때는 랜덤 I/O가 발생한다. 그래서 대량의 데이터를 읽을 때는 인덱스를 통해 읽는 것 보다 테이블의 데이터를 직접 읽는 것이 효율적이다.&lt;/p&gt;
&lt;h4 id=&quot;인덱스-풀-스캔&quot;&gt;인덱스 풀 스캔&lt;/h4&gt;
&lt;p&gt;인덱스의 처음부터 끝까지 모두 읽는 방식을 인덱스 풀 스캔이라고 한다.
대표적으로 쿼리 조건절에 사용된 칼럼이 인덱스의 첫 번째 칼럼이 아닌 경우 인덱스 풀 스캔을 하게 된다. 즉, 인덱스가 (A, B, C) 순서로 만들어져 있는데, &lt;code&gt;WHERE&lt;/code&gt; 절이 (B, C)로 검색하는 경우이다.&lt;/p&gt;
&lt;p&gt;일반적으로 인덱스의 크기는 테이블의 크기보다 작다. 테이블 전체를 읽는 것 보다는 효율적이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;테이블 전체를 읽거나 인덱스 풀 스캔을 하는 경우 보통 ‘인덱스를 사용하지 못한다’, ‘인덱스를 효율적으로 사용하지 못한다’ 라고 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;루스-인덱스-스캔&quot;&gt;루스 인덱스 스캔&lt;/h4&gt;
&lt;p&gt;루스 인덱스 스캔은 레인지 스캔과 비슷하지만 &lt;strong&gt;중간에 필요하지 않은 키 값은 무시하고 다음으로 넘어간다.&lt;/strong&gt; 일반적으로 &lt;code&gt;GROUP BY&lt;/code&gt; 또는 &lt;code&gt;MAX()&lt;/code&gt;, &lt;code&gt;MIN()&lt;/code&gt; 함수에 대해 최적화를 하는 경우 사용된다.&lt;/p&gt;
&lt;h4 id=&quot;인덱스-스킵-스캔&quot;&gt;인덱스 스킵 스캔&lt;/h4&gt;
&lt;p&gt;인덱스가 (A, B, C) 순서로 만들어져 있는데, &lt;code&gt;WHERE&lt;/code&gt; 절이 (B, C)로 검색하는 경우, MySQL 8.0 버전부터 옵티마이저가 최적화를 해서 A 칼럼을 건너뛴다. 루스 인덱스 스캔은 &lt;code&gt;GROUP BY&lt;/code&gt; 절을 처리하기 위해서만 사용됐지만 인덱스 스킵 스캔은 &lt;code&gt;WHERE&lt;/code&gt; 절도 처리 가능하도록 용도가 넓어졌다.&lt;/p&gt;
&lt;h3 id=&quot;다중-칼럼-인덱스&quot;&gt;다중 칼럼 인덱스&lt;/h3&gt;
&lt;p&gt;인덱스가 (A, B) 순서로 만들어져 있다면, 두 번째 칼럼 B는 첫 번째 칼럼 A에 의존해 정렬되어 있다.&lt;/p&gt;
&lt;p&gt;(1, 1) -&gt; (1, 2) -&gt; (1, 3) -&gt; (2, 1) -&gt; (2, 2) -&gt; (2, 3) -&gt; (3, 1) -&gt; (3, 2) -&gt; (3, 3)&lt;/p&gt;
&lt;p&gt;때문에 인덱스 내에서 각 칼럼의 순서가 상당히 중요하다.&lt;/p&gt;
&lt;h3 id=&quot;b-tree-인덱스의-정렬-및-스캔-방향&quot;&gt;B-Tree 인덱스의 정렬 및 스캔 방향&lt;/h3&gt;
&lt;p&gt;인덱스의 키 값은 오름차순이거나 내림차순으로 정렬되어 저장된다. 하지만 항상 그 방향으로만 읽을 수 있는 것은 아니다. 어느 방향으로 읽을지는 옵티마이저가 만들어 내는 실행 계획이 결정한다.&lt;/p&gt;
&lt;h4 id=&quot;인덱스-스캔-방향&quot;&gt;인덱스 스캔 방향&lt;/h4&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; first_name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;Anneke&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; first_name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ASC&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; LIMIT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; first_name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; LIMIT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;첫 번째 쿼리는 &lt;code&gt;first_name&lt;/code&gt; 칼럼에 정의된 인덱스로 ‘Anneke’레코드를 찾고, 정순으로 4개를 가져온다. 두 번째 쿼리는 역순으로 읽으면서 5개를 가져온다.&lt;/p&gt;
&lt;p&gt;쿼리의 &lt;code&gt;ORDER BY&lt;/code&gt;, &lt;code&gt;MIN&lt;/code&gt;, &lt;code&gt;MAX&lt;/code&gt; 함수 등 최적화가 필요하면 옵티마이저가 알아서 읽기 방향을 전환한다.&lt;/p&gt;
&lt;h4 id=&quot;내림차순-인덱스&quot;&gt;내림차순 인덱스&lt;/h4&gt;
&lt;p&gt;페이지 잠금이 인덱스 정순 스캔에 유리한 구조이고, 페이지 내에서 인덱스 레코드가 단방향으로만 연결되어 있기 때문에 역순으로 스캔하는 경우는 조금 느리다.&lt;/p&gt;
&lt;p&gt;역순 스캔 쿼리가 많은 경우, 내림차순 인덱스를 만드는 것이 좋은 선택이 될 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;b-tree-인덱스의-가용성과-효율성&quot;&gt;B-Tree 인덱스의 가용성과 효율성&lt;/h3&gt;
&lt;p&gt;쿼리의 &lt;code&gt;WHERE&lt;/code&gt;, &lt;code&gt;GROUP BY&lt;/code&gt;, &lt;code&gt;ORDER BY&lt;/code&gt;절이 어떤 경우에 인덱스를 타는지 식별할 수 있어야 한다.&lt;/p&gt;
&lt;h4 id=&quot;비교-조건의-종류와-효율성&quot;&gt;비교 조건의 종류와 효율성&lt;/h4&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dept_emp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dept_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;d002&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; emp_no &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 10114&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인덱스 순서가 (dept_no, emp_no) 인 경우, ‘d002’를 찾고, ‘10114’를 찾고 쭉 읽기만 하면 된다. 하지만 인덱스 순서가 (emp_no, dept_no) 인 경우는 emp_no &gt;= 10114, dept_no = ‘d002’인 레코드를 찾고,  그 이후 모든 레코드에 대해 dept_no를 비교해야 한다.&lt;/p&gt;
&lt;p&gt;첫 번째 경우의는 작업 범위 결정 조건, 두 번째 경우는 필터링 조건이 된다. 작업 범위를 결정하는 조건이 많을 수록 쿼리 성능이 높아진다. 하지만 필터링 조건은 많아져도 성능이 높아지지 않는다. 오히려 느리게 만들 때가 많다.&lt;/p&gt;
&lt;h4 id=&quot;인덱스의-가용성&quot;&gt;인덱스의 가용성&lt;/h4&gt;
&lt;p&gt;B-Tree 인덱스의 특징은 왼쪽 값에 기준해서 오른쪽 값이 정렬돼 있다는 것이다. 인덱스 키 하나의 정렬도 그렇고, 다중 칼럼에서도 왼쪽 칼럼의 값을 모르면 인덱스 레인지 스캔을 할 수 없다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; first_name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;LIKE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;%mer&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;정렬 우선순위가 낮은 뒷부분의 값만으로는 B-Tree 인덱스의 효과를 얻을 수 없다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dept_emp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; emp_no&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10144&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;인덱스가 (dept_no, emp_no)로 생성되어 있다면,  dept_no 조건 없이는 레인지 스캔을 할 수 없게 된다.&lt;/p&gt;
&lt;h2 id=&quot;4-클러스터링-인덱스&quot;&gt;4. 클러스터링 인덱스&lt;/h2&gt;
&lt;h3 id=&quot;클러스터링-인덱스란&quot;&gt;클러스터링 인덱스란?&lt;/h3&gt;
&lt;p&gt;MySQL 서버에서 클러스터링은 테이블의 레코드를 PK를 기준으로 비슷한 것끼리 묶어서 저장하는 형태로 구현된다. InnoDB 스토리지 엔진에서만 지원한다.&lt;/p&gt;
&lt;p&gt;중요한 것은 &lt;strong&gt;PK값에 의해 레코드의 저장 위치가 결정&lt;/strong&gt;된다는 것이다. 즉, PK값이 변경되면 그 레코드의 물리적인 저장 위치가 바뀌어야 한다. 때문에 PK에 대한 의존도가 높다. PK를 신중하게 설정해야 한다.&lt;/p&gt;
&lt;p&gt;사실 인덱스 알고리즘이라기 보다는 테이블 레코드의 저장 방식이다. InnoDB처럼 항상 클러스터링 인덱스로 저장되는 테이블은 PK 기반의 검색이 매우 빠른 대신 레코드의 저장이나 PK의 변경이 상대적으로 느리다.&lt;/p&gt;
&lt;h3 id=&quot;클러스터링-인덱스의-장단점&quot;&gt;클러스터링 인덱스의 장단점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;장점
&lt;ul&gt;
&lt;li&gt;PK로 검색할 때 처리 성능이 매우 빠르다.&lt;/li&gt;
&lt;li&gt;테이블의 모든 세컨더리 인덱스가 PK를 가지고 있기 때문에 인덱스만으로 처리될 수 있는 경우가 많음 (커버링 인덱스)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단점
&lt;ul&gt;
&lt;li&gt;테이블의 모든 세컨더리 인덱스가 PK를 가지고 있기 때문에 PK 값이 클 경우 전체적으로 인덱스의 크기가 커진다.&lt;/li&gt;
&lt;li&gt;세컨더리 인덱스를 통해 검색할 때 PK로 다시 한 번 검색해야 하므로 처리 성능이 느리다.&lt;/li&gt;
&lt;li&gt;PK에 의해 레코드의 물리적 저장 위치가 결정되기 때문에 &lt;code&gt;INSERT&lt;/code&gt; 처리 성능이 느리다&lt;/li&gt;
&lt;li&gt;PK를 변경할 때 레코드를 &lt;code&gt;DELETE&lt;/code&gt;하고 &lt;code&gt;INSERT&lt;/code&gt;하는 작업이 필요하기 때문에 처리 성능이 느리다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;일반적으로 웹 서비스와 같은 OLTP(On-Line Transaction Processing)에서는 쓰기와 읽기의 비율이 2:8 정도 되기 때문에 조금 느린 쓰기를 감수하고 읽기를 빠르게 유지하는 것이 중요하다.&lt;/p&gt;</content:encoded><category>cs</category><category>db</category></item><item><title>2024 LG CNS 채용연계형 인턴 최종 전환 후기</title><link>https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%B5%9C%EC%A2%85-%EC%A0%84%ED%99%98-%ED%9B%84%EA%B8%B0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%B5%9C%EC%A2%85-%EC%A0%84%ED%99%98-%ED%9B%84%EA%B8%B0/</guid><description>2024 LG CNS 채용연계형 인턴 최종 전환 후기. 8주 인턴십 동안 Spring Boot, Bedrock, Vue/Nuxt로 과제를 수행하고 전환 면접까지 마친 경험을 정리했다.</description><pubDate>Mon, 25 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;2024 LG CNS 채용연계형 인턴 최종 합격 후기-1711372606614.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2116&quot; height=&quot;1730&quot; src=&quot;https://ks1ksi.io/_astro/2024%20LG%20CNS%20%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95%20%EC%9D%B8%ED%84%B4%20%EC%B5%9C%EC%A2%85%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1711372606614.CZrrfZM1_Z1R6VmE.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;졸업 1년 남기고 합격해버린 모습..&lt;/p&gt;
&lt;p&gt;인턴십 지원은 &lt;a href=&quot;https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/&quot;&gt;2024 LG CNS 채용연계형 인턴 지원 및 합격 후기&lt;/a&gt; 참고.&lt;/p&gt;
&lt;h2 id=&quot;인턴십-기간&quot;&gt;인턴십 기간&lt;/h2&gt;
&lt;p&gt;총 8주동안 진행된다. 첫주는 오리엔테이션 + 아이스 브레이킹? 딱히 일을 하진 않고 인턴십 동기들과 인사할 기회를 준다.&lt;/p&gt;
&lt;p&gt;남은 7주는 각자 배정된 팀으로 가서 인턴 과제를 수행하게 된다.
말이 7주지 1주차는 여기저기 상담하고 권한받고 하느라 정신이 없고, 마지막 주차는 전환 면접 발표 준비라 사실상 과제는 5주만에 다 끝내야 한다.&lt;/p&gt;
&lt;p&gt;우리 집에서 마곡까지 거리가 꽤 돼서 출퇴근하기 힘들었다. 왕복 3시간을 빈 자리 하나 없는 대중교통에서 보내는 것은 상당히 괴로운 일이다.&lt;/p&gt;
&lt;h2 id=&quot;무엇을-하였는가&quot;&gt;무엇을 하였는가&lt;/h2&gt;
&lt;p&gt;회사 기술 스택에 맞춰 Spring Boot를 사용하게 되었다. &lt;a href=&quot;https://aws.amazon.com/ko/bedrock/&quot;&gt;Amazon Bedrock&lt;/a&gt;같은 매니지드 서비스 API와 연동하는 작업도 했다.
코드 레벨에서 어떻게 비동기로 돌게 할지, DB에 반영은 언제 할지, 실패했을 때는 어떻게 할지 등등 생각해볼 부분이 꽤 많았다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.spring.io/spring-framework/reference/data-access/transaction/event.html&quot;&gt;@TransactionalEventListener&lt;/a&gt;처럼 평소에 쓸 일 없던 기능들도 공부하게 됐다. 공부하면 할수록 배울게 점점 늘어나는 느낌이다. 바운더리를 잘 정하고, 샛길로 빠지지 않도록 조절해야겠다.&lt;/p&gt;
&lt;p&gt;프론트도 짜야 해서 Vue, Nuxt를 급하게 배워서 사용했다. Vue + tailwindcss 하니까 엄청 직관적으로 짤 수 있었다. 나중에 어드민 만들 일 있으면 애용해야겠다. css는 아직도 너무 어려운 것 같다.&lt;/p&gt;
&lt;h2 id=&quot;마무리&quot;&gt;마무리&lt;/h2&gt;
&lt;p&gt;면접은 진행한 과제 관련 + 인성 관련 질문이었다. 수요일에 최종 발표 겸 면접을 끝내고, 남은 기간동안 문서 작업도 끝내놓고 왔다. 나름 열심히 만들었는데 반출은 불가능해서 아쉬운대로 사내 위키에 열심히 정리해뒀다. 관련 작업을 하게 된 분, 혹은 다음에 오는 인턴이 참고해서 도움이 됐으면 한다.&lt;/p&gt;
&lt;h2 id=&quot;후기&quot;&gt;후기&lt;/h2&gt;
&lt;p&gt;운 좋게도 하고싶은 일을 하게 되었다. 공부하면서 돈도 받은 느낌이라 기분이 좋다. 졸업 전까지 열심히 공부해야겠다.
또, 출퇴근하며 책을 읽거나 개발 관련 영상을 보는 습관을 들였는데 도움이 많이 되는 것 같다. 책 읽는 시간을 좀 더 늘리고, 쓸데없는 유튜브 보는 시간을 줄이면 좀 더 나은 사람이 될 수 있지 않을까?&lt;/p&gt;</content:encoded><category>job</category><category>lgcns</category></item><item><title>2023 회고</title><link>https://ks1ksi.io/blog/2023-%ED%9A%8C%EA%B3%A0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2023-%ED%9A%8C%EA%B3%A0/</guid><description>2023 회고. 교육봉사, SW마에스트로, 학교생활, 여행, 프로젝트, 취업 준비를 분기별로 돌아본 글.</description><pubDate>Mon, 01 Jan 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;내가 2023년에 무엇을 했을까? 달력과 사진첩을 찾아보며 기억을 더듬어보자.&lt;/p&gt;
&lt;h2 id=&quot;q1&quot;&gt;Q1&lt;/h2&gt;
&lt;p&gt;졸업을 위해 교봉을 채워야 하는 상황이었다. 운좋게 학교에서 진행하는 삼정중학교 교육봉사 프로그램 티케팅에 성공해서 편안하게 30시간을 받게 되었다. 1월에는 수업 계획을 짜고 1월 말부터 2월 초까지 교육봉사를 진행했다.&lt;/p&gt;
&lt;p&gt;아이들을 가르치는 일이 그렇게 못할 일은 아니었지만 그래도 가슴이 뛰거나 하지는 않았다. 아무래도 교사를 평생 직장으로 가지기는 어려울 것 같다. 사명감이 정말 중요한 직업이라고 생각한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704084180920.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1310&quot; height=&quot;1004&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704084180920.kXhB4Msh_ZfAu4A.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;자취방도 새로 계약했다. 늦게, 급하게 구하다 보니 좋은 방은 별로 없고 어디 나사가 하나씩 빠진 방밖에 없었다. 그나마 좀 넓고 위치도 괜찮고 2층이라 벌레도 안나오는 방에 살게 되었다. 근데 창문 열면 벽이라 해가 들지 않는다. 이건 지금 비타민 D로 보충하고 있다.&lt;/p&gt;
&lt;p&gt;본격적으로 학교 다니기 전이라 여자친구랑 자주 놀러다녔다. 생일때 비싼 호텔도 가보고, 맛있는것도 먹고.. 동우랑 해외여행도 다녀왔다. 도쿄 처음 가봤는데 굉장히 즐거웠다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704084597168.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1094&quot; height=&quot;1458&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704084597168.CZ2lW77f_Z2lnoou.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;군대에 있을 때부터 하고 싶었던 SW마에스트로에 지원했다. 동기, 선배가 12기, 13기 활동 하는거 보면서 너무 하고싶다고 생각했고, 군대에 있을 때 준비도 나름 열심히 했었다. 코테는 그냥 풀었고, 포트폴리오는 방학때 만든 간단한 웹 프로젝트 하나와 학교다닐 때 만든 프로젝트 두 개를 제출했다.&lt;/p&gt;
&lt;p&gt;도쿄에 있을 때 코딩테스트 사전 점검날이라 노트북을 가져가서 점검하고, 귀국하자마자 바로 코딩 테스트를 풀었던 기억이 있다. 연습은 당연히 못했는데 나름 잘 풀어서 뿌듯했다. 면접은 엄청 절었는데 코딩 테스트에서 사람들이 많이 떨어진 덕분에 운좋게 붙었다고 생각한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704085139221.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;618&quot; height=&quot;652&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704085139221.CVwm9Do2_Z1EARVn.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/sw-%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C-14%EA%B8%B0-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/&quot;&gt;SW 마에스트로 14기 합격 후기&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;여자친구와 생일을 함께 보냈다. 22년 생일은 군대에 있어서 여자친구가 택배로 선물을 보내줬는데 23년 생일은 함께 보낼 수 있었다. 제일 좋았던건 여자친구가 차려준 생일상이 아니었나 ㅎㅎ..&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704085016386.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1822&quot; height=&quot;1274&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704085016386.hJnxkdI3_Zh0rKA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;수강신청을 말아먹고 어쩌다 보니 율전에서 수업을 듣게 되었다. 오랜만에 학교에 가게 되어 정신이 하나도 없었는데 율전까지 가게 되었다. 우리과 수강신청은 언제쯤 괜찮아질까?.. 같이 율전 가는 사람이 윤재뿐이라 율전에서 윤재랑 밥을 자주 먹게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704200388150.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1452&quot; height=&quot;1418&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704200388150.BXSVMgeL_13gmDW.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;q2&quot;&gt;Q2&lt;/h2&gt;
&lt;p&gt;SW마에스트로 예비과정과 학교 수업이 겹쳐서 너무 힘들었다. 온라인이면 괜찮은데 모두 오프라인으로 모여서 진행하다보니 뭐하나 쉬운게 없었다. 팀빌딩, 멘토선정, 다 오프라인으로 나가서 만나면서 해야 하는데 나는 명륜에서 수업 듣고 인자셔틀타고 율전가서 수업 듣고 끝나면 이미 저녁이고..&lt;/p&gt;
&lt;p&gt;그래도 어찌저찌 좋은 팀원들, 멘토님들과 함께하게 되었다. 역시 운이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704085923729.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2194&quot; height=&quot;1646&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704085923729.BoOyTlgx_hp0Md.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;예비군 처음 가는데 시원하게 늦잠자서 택시타고 아슬아슬하게 도착한 기억이 있다. 24년에는 일찍 일어나야지!&lt;/p&gt;
&lt;p&gt;공부가 정말정말 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;100&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\times 100&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 힘들었다. 선형대수학도 듣지 않고 기계학습원론 수업에 머리부터 박았는데 한학기 내내 고통스러웠다. 그리고 과제도 너무 많았다. 도서관가서 과제하고 공부하고 연수센터 끌려가고 기획 회의하고 멘토링하고 지금 생각하면 어떻게 살았는지 잘 모르겠다.&lt;/p&gt;
&lt;p&gt;특히 기말고사 기간이 쉽지 않았다. SW마에스트로 기획 심의와 기말고사 기간이 겹쳤고, 기말 프로젝트도 너무 많았다. 심지어 난 팀장이었고, 발표까지 해야 했다. 어떻게든 매일매일 밤새서 잠 줄여가면서 틀어막고, 기말과제도 다 내고, 기획심의도 한번에 통과했다. 다행.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704087006948.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2194&quot; height=&quot;1646&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704087006948.CTHOUtQJ_Z16w5d1.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;프로젝트 주제도 잘 정했고, 학점도 살면서 처음으로 4 넘어봤으니까 괜찮은 거 아닐까? 또 하나 얻은게 있다면 대학원에 갈 마음이 사라져버렸다. 기계학습원론 과목에 수식이 너무 많이 나와서 마음이 꺾여버렸다. 역시 개발이 훨씬 재밌다.&lt;/p&gt;
&lt;p&gt;우리 학교는 6월 초에 종강을 한다. 함께 하는 팀원은 6월 말 종강이라 그 전까지 미뤄두었던 웹 개발 공부를 조금 해봤다. 이것도 참 배울게 많았다. 겨울방학에 아주 잠깐 프로젝트 한거 말고는 거의 손을 대본적이 없어서 고생 많이 했다. 그래도 하다보면 늘지 않을까 하는 막연한 생각을 가지고 프로젝트에 임했다.&lt;/p&gt;
&lt;h2 id=&quot;q3&quot;&gt;Q3&lt;/h2&gt;
&lt;p&gt;본격적으로 SW마에스트로 과정이 시작되었다. 방학 기간동안 우리 팀은 평일은 매일매일 나와서 회의하고, 개발했다.&lt;/p&gt;
&lt;p&gt;제대로 된 개발도 이번이 처음이고, 협업하며 프로젝트를 진행하는 것도 이번이 사실상 처음이었다. 첫 번째 통곡의 벽은 ‘배포’였다. AWS도 잘 모르고, 네트워크도 잘 모르고, 이걸 어디서부터 어디까지 공부해야 하는지도 잘 몰라서 좀 많이 헤맸다. 결국 GG치고 같은 팀원인 상민이에게 도움을 구했는데 너무 빨리 돼서 신기하기도 하고 허망하기도 했다.&lt;/p&gt;
&lt;p&gt;나중에 SW마에스트로에서 AWS Training Center로 교육을 보내줬는데 이때 들으면서 아 그게 그거였구나~ 하고 깨달음을 얻게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704088061985.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1196&quot; height=&quot;1122&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704088061985.CThszZr6_Zd1lMw.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;아 AWS 가고싶다..&lt;/p&gt;
&lt;p&gt;7월 말에는 바쁜 와중에 여자친구랑 오사카로 여행을 다녀왔다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704197515964.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1712&quot; height=&quot;2282&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704197515964.TVcgyZDK_1YJwKJ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704197353926.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1678&quot; height=&quot;1036&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704197353926.CSHI1DjX_vVkcD.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;내가 제일 좋아하는 이치란 라멘과 오사카 국룰 플라잉 다이노소어.. 이때 좀 급하게 간거라 유니버셜 스튜디오 패스도 중고나라에서 겨우겨우 구했다. 역시 P처럼 살면 손해를 볼 수 밖에 없는 구조다. 다음 여행은 계획을 잘 세우는걸로..&lt;/p&gt;
&lt;p&gt;여행 출발 전에 거하게 싸웠는데 그래도 여행 출발하면서 화해하고 즐거운 여행 했다. 싸우지 말자!&lt;/p&gt;
&lt;p&gt;8월에는 소마 중간점검때문에 또 엄청 바빴다. 지금 생각해보면 발표 준비를 이렇게까지 할 필요가 없었던 것 같은데 왜 그렇게 열심히 했는지 모르겠다. 그시간에 개발이나 하지 그랬니 승일아..&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704197650912.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;884&quot; height=&quot;606&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704197650912.DtVjg6Du_ZaiEDv.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;아무쪼록 중간점검 잘 끝내고 오랜만에 시골 내려가서 푹 쉬다 개강했다. 2학기 수강신청? 당연히 말아먹었다. 그래도 졸업에 필요한 과목은 모두 잡아서 4-2는 좀 편하게 보낼 수 있을 것 같다. 한학년 35명에 복수전공, 편입까지 50명이 넘는데 수업 정원이 22명은 좀 ㅋㅋ.. 맘에 안드는게 한두가지가 아니지만 어쩔 수 없다. 네가 선택한 학교다.&lt;/p&gt;
&lt;p&gt;전공 3과목, 교육봉사(서류만 제출하면 P), 4차산업혁명(1학점 PF) 이렇게 편안한 시간표를 만들었다. 저번학기에 너무 고생해서 율전은 가지 않기로 했다. SW마에스트로와 학기 병행하기 힘들기도 하고 대중교통에 쓰는 시간이 너무 많아서 비효율적이라.. 4-2에 몰아 듣는거 말고는 갈 일이 없을 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704198014571.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1450&quot; height=&quot;1004&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704198014571.Cru-LwS1_Z2uaRw9.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;학교 수업시간에 수업 안듣고 개발하고, 끝나자마자 연수센터 달려가는 멋진 생활이 시작되었다. 수업 절반이 온라인이고, 원래 우리 팀은 늦게 모이는 편이라 원래 모이는 시간에 모일 수 있었다. 내가 좀 일찍 일어나야 했지만..&lt;/p&gt;
&lt;p&gt;9월 말쯤 윤재가 AI해커톤 나가자고 해서 나가게 되었다. 별 생각 없이 나갔는데 어쩌다 보니 1등을 해버렸다. 해커톤은 살면서 처음인데 앞으로는 안나가지 않을까 싶다. 너무 힘들기도 하고 하루만에 대충 만든 프로젝트라 별 기술적 고민이 없기도 해서..&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/2023-skku-ai-%EA%B5%90%EC%9C%A1-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9B%84%EA%B8%B0/&quot;&gt;2023 SKKU AI 교육 해커톤 후기&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704198140666.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;462&quot; height=&quot;724&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704198140666.CasInBkk_Z1LRqUG.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;9월에 검색 기능을 구현하느라 삽질을 좀 했다. DB에서 &lt;code&gt;LIKE&lt;/code&gt; 쿼리 날리는게 너무 별로라 검색엔진 도입하고 싶었고, 여러가지 방안 중 고민하다 결국 AWS OpenSearch 사용하기로 했다. 매니지드 서비스가 편하긴 하다. 공식 문서도 잘 되어 있어서 큰 문제 없이 도입 성공했다.&lt;/p&gt;
&lt;p&gt;임베딩 결과 벡터도 검색엔진에 넣었는데 이건 좀 별로였다. 비싼 인스턴스도 아니라 메모리도 얼마 없는데, 이런 것까지 검색할 때 메모리에 올라와서 JVM Memory Pressure가 엄청 높게 나왔다. 만약 다시 개발한다면 벡터 저장소는 다른 곳으로 빼서 검색엔진 부담을 줄이는 방향으로 갈 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704198858271.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;734&quot; height=&quot;546&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704198858271.BPwGXHtb_2i5w77.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;열심히 OpenSearch 삽질한 결과.. 물론 프로젝트 지원금으로 냈다. 소마 최고.&lt;/p&gt;
&lt;h2 id=&quot;q4&quot;&gt;Q4&lt;/h2&gt;
&lt;p&gt;10월에는 학교 중간고사가 있었지만 별로 공부할 시간이 없었다. 시험 당일 새벽에 1회독정도 하는게 끝이었다. 사실 이번학기 학점을 잘 받을 생각이 없었기 때문에 슬프진 않았다.&lt;/p&gt;
&lt;p&gt;TOPCIT 시험을 봤다. SW마에스트로 아니면 보통은 평생 볼 일 없는 시험이다. 근데 이 시험에서 일정 점수 이상 받으면 우리 학교 &amp;#x26; 우리 과 졸업 요건을 동시에 충족할수 있다. 학교 졸업 요건중 하나인 창의품은 TOPCIT 3수준 이상을 요구하고, 우리 과 졸업 요건은 TOPCIT 4수준 이상을 요구한다. 4수준 이상 받기가 힘들다고 해서 그냥 공부 안하고 봤다.&lt;/p&gt;
&lt;p&gt;그런데…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704199732323.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;946&quot; height=&quot;318&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704199732323.BxlWhprf_dKzmq.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;어우 달아.. 창의품과 컴교 졸업 요건이 충족되었다. 국제품은 예전에 카투사 가려고 본 토익으로 충족했고, 인성품은 올해부터 사범대 졸업 요건인 교육 봉사와 중복 인정이 된다고 해서 예전에 한 교육 봉사시간을 제출했다. 난 이제 남은 18학점만 들으면 그냥 졸업이다.&lt;/p&gt;
&lt;p&gt;아마 이때쯤 인텔 인턴십 모집 공고가 올라와서 지원했다.&lt;/p&gt;
&lt;p&gt;Intel Korea SW engineer Intern 지원 후기&lt;/p&gt;
&lt;p&gt;결과적으로 아쉽게 떨어지게 되었지만 영문 이력서도 작성해보고, 면접도 두번이나 보고 알찬 경험이었다. 300명정도 지원했다던데 생각보다는 적었다. 다들 외국계 기업에 지원하는걸 두려워하는 것 같다. 난 열심히 써야지.&lt;/p&gt;
&lt;p&gt;기술면접 전날 여자친구랑 시그니엘 갔던것도 기억에 남는다. 돈 많이 벌고싶다.&lt;/p&gt;
&lt;p&gt;11월 발표 직전 막판 스퍼트. 챗봇 기능에 유행하는 &lt;a href=&quot;https://learn.microsoft.com/ko-kr/azure/search/retrieval-augmented-generation-overview&quot;&gt;RAG&lt;/a&gt; 한스푼 첨가했다. 생각보다 잘 작동해서 놀랐다. 적절 Threshold를 정하지 못했는데, OpenAI 블로그에서 0.8정도로 잡으면 된다고 해서 실험 조금 더 해보고 그렇게 설정할 계획이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704200971578.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;3680&quot; height=&quot;2122&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704200971578.BDtIZIsq_Z1RGYa3.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;발표 준비는 정말 얼마 안했다. 애초에 인증이 목표가 아니었기도 하고, 중간때 너무 시간을 많이 써서 이 템플릿 거의 그대로 가져간 후, 개발한 내용 시연만 해도 충분하다고 판단했다. 잘 판단한 것 같다. 개발이 재밌다.&lt;/p&gt;
&lt;p&gt;2023년 가장 짜릿했던 일은 바로 페이커의 롤드컵 우승이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704200160964.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1280&quot; height=&quot;854&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704200160964.nVBV2sZC_Z28hvjP.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;내가 이걸 죽기 전에 또 보다니.. 물개박수 치면서 웃고, 감격의 눈물을 흘리고, 티켓값이 100만원이라도 그냥 사서 갈걸 하고 후회도 해보고..&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;이걸 보니 문득 10년째 정상을 지키는 페이커가 새삼 대단하다고 느껴지네…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;페이커가 ‘과정’이 즐거웠다고 인터뷰했는데 나도 올해 소프트웨어 마에스트로 과정이 즐거웠고, 그래서 결과가 어떻든 의미가 있었다고 생각한다. 인증 못받았지만 즐거웠잖아?&lt;/p&gt;
&lt;p&gt;사실 결과가 그렇게 나쁘지도 않았다. 겨울 방학을 백수로 보내지 않기 위해 6개의 기업에 인턴 지원을 했고, 요즘같이 팍팍한 세상에 하나라도 붙었으니 말이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704200496764.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1488&quot; height=&quot;548&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704200496764.Bejx9_W__L0SFP.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;빨간색은 서탈, 주황색은 면탈, 초록색은 최합이다.&lt;/p&gt;
&lt;p&gt;제일 아쉬운 기업은 아무래도 카카오가 아닐까? 코테를 잘 봐서 김칫국좀 마셨는데 역시 3학년 2학기 마친 내 신분으로는 어림도 없었나보다. 소마 최종 발표 끝나자마자 바로 코테라 준비를 많이 못했는데 24년에는 코테를 더 많이 볼거니까 준비를 좀 해야겠다고 느꼈다.&lt;/p&gt;
&lt;p&gt;2024 카카오 채용 연계형 겨울 인턴십 지원 후기&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/&quot;&gt;2024 LG CNS 채용연계형 인턴 지원 및 합격 후기&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;기말고사는 소마 끝났으니 양심상 공부를 해봤지만 망해버린 중간고사를 뒤집기엔 역부족이었다고 한다. 굉장히 사소한 부분이다.&lt;/p&gt;
&lt;p&gt;제한재 멘토님과 팀원들이랑 다같이 여행도 다녀왔다. 정말 멋지고, 존경스러운 멘토님이다. 그래서 나도 나중에 소마 엑스퍼트나 멘토가 되고싶다. 열심히 살아야겠다.&lt;/p&gt;
&lt;p&gt;수료식도 참여해서 사진도 찍고, 수료증도 받았다. 뭔가 후련하면서도 아쉬웠다. 지금 드는 생각은 ‘학교 더 대충 다니고 소마 더 열심히 할걸’이다. 학교 출석이 뭐라고.. 끝날때쯤 돌아보니 수업시간이랑 겹처서 멘토링, 특강을 거의 듣지 못했다. 재밌어 보이는 주제가 많았는데 너무 아쉽다.&lt;/p&gt;
&lt;p&gt;모든 행사가 끝나고, 연말은 대부분 여자친구와 함께 보냈다. 크리스마스를 기념해서 제주도로 여행도 가고, 29일에는 2주년 기념으로 맛있는 스시도 먹고, 커플링도 새로 맞췄다. 2023년에는 바쁘고 여유가 없다는 핑계로 같이 보내는 시간이 많지 않았는데, 2024년에는 더 많은 시간을 같이 보내고싶다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 회고-1704201454824.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1712&quot; height=&quot;2282&quot; src=&quot;https://ks1ksi.io/_astro/2023%20%ED%9A%8C%EA%B3%A0-1704201454824.BJIof1Db_2jd3vd.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;2023년의 대부분을 차지했던 SW마에스트로 기간동안 ‘난 왜 이것도 모르지?’ 라는 생각에 사로잡혀 괴로워하며 시간을 보낸 것 같다. 그래도 1년 전과 비교하면 실력이 꽤 많이 늘었다. 실력이 는 것도 의미가 있지만, 더 의미있는건 &lt;strong&gt;내가 무엇을 모르는지 모르는 상태에서, 내가 무엇을 모르는지 아는 상태&lt;/strong&gt;가 된 것이라고 생각한다.&lt;/p&gt;
&lt;p&gt;전역하고 개발 처음 시작했을 때 너무 막막했다. 내가 가고싶은 회사 JD를 보면, 아는게 단 하나도 없었고, 얼마나 공부해야 저기 도달할 수 있을지 감도 잡히지 않았다. 그래도 지금은 그게 뭔지, 그리고 무엇이 중요하고, 무엇을 더 알아야 하는지 어느정도 윤곽이 보인다고 해야하나?&lt;/p&gt;
&lt;p&gt;이런 부분을 2024년에 좀 더 채워서, 올해보다 빠른 속도로, 더 많이 발전하고 싶다. 공부도 열심히 하고, 인턴도 열심히 해서 전환되고.. 김승일 화이팅!&lt;/p&gt;</content:encoded><category>life</category></item><item><title>2024 LG CNS 채용연계형 인턴 지원 및 합격 후기</title><link>https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%A7%80%EC%9B%90-%EB%B0%8F-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</guid><description>2024 LG CNS 채용연계형 인턴 지원 및 합격 후기. CAM 직무 지원서, 코딩테스트 세 문제, 기술 중심 면접 경험을 정리했다.</description><pubDate>Wed, 20 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;2024 LG CNS 채용연계형 인턴 지원 및 합격 후기-1703083267256.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1264&quot; height=&quot;740&quot; src=&quot;https://ks1ksi.io/_astro/2024%20LG%20CNS%20%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95%20%EC%9D%B8%ED%84%B4%20%EC%A7%80%EC%9B%90%20%EB%B0%8F%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1703083267256.CDl0fIX4_2t7dkA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;난 CAM (Cloud Application Modernization) 직무로 썼다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.lgcns.com/careers/job/build-center/&quot;&gt;여기&lt;/a&gt; 가고싶어서..&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2024 LG CNS 채용연계형 인턴 지원 및 합격 후기-1703087821031.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2550&quot; height=&quot;552&quot; src=&quot;https://ks1ksi.io/_astro/2024%20LG%20CNS%20%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95%20%EC%9D%B8%ED%84%B4%20%EC%A7%80%EC%9B%90%20%EB%B0%8F%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1703087821031.BRFOfpGB_ElhYK.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이거 완전 &lt;del&gt;카카오&lt;/del&gt;&lt;/p&gt;
&lt;h2 id=&quot;자소서&quot;&gt;자소서&lt;/h2&gt;
&lt;h3 id=&quot;lg-cns에-지원한-동기와-입사-이후-꿈꾸는-것은-무엇인가요&quot;&gt;LG CNS에 지원한 동기와 입사 이후 꿈꾸는 것은 무엇인가요?&lt;/h3&gt;
&lt;p&gt;CAM 직무소개 내용 바탕으로 썼다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cloud Application Modernization&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;상세내용
&lt;ul&gt;
&lt;li&gt;이런 일을 해요
&lt;ul&gt;
&lt;li&gt;신규 서비스 및 레거시 시스템을 클라우드 환경 내에서 구성하여 현대화(Modernization)하는 일을 합니다.&lt;/li&gt;
&lt;li&gt;클라우드와 최신 기술(Agile, React, DevOps 등)을 활용한 AM/Cloud Native Application을 구축하는 일을 합니다.&lt;/li&gt;
&lt;li&gt;최신 개발 스택 및 클라우드 서비스를 경험할 기회가 많습니다.&lt;/li&gt;
&lt;li&gt;애자일 방법론을 적용하여 프로젝트가 진행되며, 다양한 직무를 가진 분들이 함께 Scrum팀을 구성합니다.&lt;/li&gt;
&lt;li&gt;Sprint 단계별로 결과물을 고객에게 전달하고 피드백을 받아 결과물을 개선하며 시스템을 구현합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이런 분이면 더 좋겠어요!
&lt;ul&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;지원분야와-관련된-구체적인-지식이나-경험을-기술해주십시오&quot;&gt;지원분야와 관련된 구체적인 지식이나 경험을 기술해주십시오.&lt;/h3&gt;
&lt;p&gt;SW마에스트로 프로젝트 한거 적어서 냈고, 그중에서도 클라우드 기술 활용했던거 약간 강조했다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;둘 다 500자 제한이라 쉽지 않았다. 뭐 조금 써보려고 하면 500자 넘고..&lt;/p&gt;
&lt;h2 id=&quot;코딩테스트&quot;&gt;코딩테스트&lt;/h2&gt;
&lt;p&gt;3문제 나왔고 다 풀었다.&lt;/p&gt;
&lt;h3 id=&quot;1번&quot;&gt;1번&lt;/h3&gt;
&lt;p&gt;그냥 구현 문제다. &lt;code&gt;n&lt;/code&gt;이 10정도라 단순무식하게 완전탐색해도 풀리는 간단한 문제.&lt;/p&gt;
&lt;h3 id=&quot;2번&quot;&gt;2번&lt;/h3&gt;
&lt;p&gt;간단한 이분탐색 문제다. &lt;code&gt;n&lt;/code&gt;이 10억정도 돼서 완전탐색은 불가능했다.&lt;/p&gt;
&lt;h3 id=&quot;3번&quot;&gt;3번&lt;/h3&gt;
&lt;p&gt;도형 문제다. 이전 SW마에스트로 1차 코딩테스트 2번과 상당히 유사했다. 정사각형 모양, 마름모 모양 색종이를 여러 개 겹쳐서 놓았을 때 각 색종이별로 마지막에 얼마나 차지하고 있는지 계산하는 문제다. 정사각형 한 칸을 4개로 (대각선 방향) 나눈다. 그리고 각 부분마다 어떤 색종이가 차지하고 있는지 기록해주면 된다. 2차원 배열에 &lt;code&gt;tuple&amp;#x3C;int, int, int, int&gt;&lt;/code&gt;을 넣어서 풀었다.&lt;/p&gt;
&lt;h2 id=&quot;면접&quot;&gt;면접&lt;/h2&gt;
&lt;p&gt;이전 인텔 최종 면접을 말아먹고 불합격한 PTSD가 있어 나름 열심히 준비했다. 자기소개랑 예상되는 인성 질문들을 준비해서 갔는데 자기소개 빼고 다 쓸모가 없었다.&lt;/p&gt;
&lt;p&gt;SW 마에스트로에서 어떤 역할 했는지, 개발한 서비스에 그 기술을 왜 사용했는지 등 거의 기술면접 위주였다.&lt;/p&gt;
&lt;p&gt;아키텍트, 개발 중 뭐가 더 하고싶냐고 물어보여서 백엔드 개발 하고싶다고 답변했다. 백엔드 개발 하게 되면 좋을 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2024 LG CNS 채용연계형 인턴 지원 및 합격 후기-1703088469581.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1812&quot; height=&quot;1986&quot; src=&quot;https://ks1ksi.io/_astro/2024%20LG%20CNS%20%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95%20%EC%9D%B8%ED%84%B4%20%EC%A7%80%EC%9B%90%20%EB%B0%8F%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1703088469581.DytRn-kh_Z1PD24J.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/2024-lg-cns-%EC%B1%84%EC%9A%A9%EC%97%B0%EA%B3%84%ED%98%95-%EC%9D%B8%ED%84%B4-%EC%B5%9C%EC%A2%85-%EC%A0%84%ED%99%98-%ED%9B%84%EA%B8%B0/&quot;&gt;2024 LG CNS 채용연계형 인턴 최종 전환 후기&lt;/a&gt;&lt;/p&gt;</content:encoded><category>job</category><category>lgcns</category></item><item><title>백준 17835번 면접보는 승범이네</title><link>https://ks1ksi.io/blog/%EB%B0%B1%EC%A4%80-17835%EB%B2%88-%EB%A9%B4%EC%A0%91%EB%B3%B4%EB%8A%94-%EC%8A%B9%EB%B2%94%EC%9D%B4%EB%84%A4/</link><guid isPermaLink="true">https://ks1ksi.io/blog/%EB%B0%B1%EC%A4%80-17835%EB%B2%88-%EB%A9%B4%EC%A0%91%EB%B3%B4%EB%8A%94-%EC%8A%B9%EB%B2%94%EC%9D%B4%EB%84%A4/</guid><description>백준 17835번 면접보는 승범이네 풀이. 가상 정점에서 면접장들을 0거리로 연결해 역방향 다익스트라 한 번으로 각 도시의 최단 거리를 구한다.</description><pubDate>Fri, 24 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17835&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;모든 정점에서 다익스트라를 한 번씩 돌린다거나, 플로이드를 써서 각 정점에서의 최단 거리를 모두 구하면 시간 초과를 받는다.&lt;/p&gt;
&lt;p&gt;가상의 정점을 하나 만들고, 면접장까지의 거리를 0이라 하자. 그리고 여기서 다익스트라를 돌리면 각 정점에서 면접장까지의 최단 거리를 구할 수 있다.&lt;/p&gt;
&lt;p&gt;양방향 간선이 아님에 주의하자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ld&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; double&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; adj&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;  // cost, next&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(k);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;        // 길을 반대로 넣어준다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        adj&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[b]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace_back&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mv) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    priority_queue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; greater&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        pq;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    fill&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;18&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;    // 면접장까지 거리 0으로 설정&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;    // 길 반대로 넣고 모든 면접장에서 출발한다고 가정하고 풀기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mv) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[x] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        auto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [cost&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cur] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;top&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pop&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[cur] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cost) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; adj&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[cur]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[n] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cost &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[n] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cost &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[n]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ll idx &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; d &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; d) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            d &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            idx &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; idx &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; d &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;long long&lt;/code&gt; 써야한다. 거리의 최댓값이 &lt;code&gt;int&lt;/code&gt; 범위를 넘어간다.&lt;/p&gt;</content:encoded><category>ps</category><category>boj</category><category>graph</category></item><item><title>OSTEP 40 File System Implementation</title><link>https://ks1ksi.io/blog/ostep-40-file-system-implementation/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-40-file-system-implementation/</guid><description>OSTEP File System Implementation 정리. vsfs를 예로 block, inode, bitmap, superblock, 디렉터리, 파일 읽기와 쓰기 흐름을 설명한다.</description><pubDate>Tue, 31 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;이번 장에서는 vsfs(Very Simple File System)라고 하는 간단한 파일 시스템에 대해 알아보도록 하자.
이 파일 시스템은 UNIX 파일 시스템을 단순화한 것으로 디스크 자료 구조와 접근 방법, 그리고 다양한 파일 시스템들의 정책을 소개하기 위해 제작되었다.&lt;/p&gt;
&lt;h2 id=&quot;1-생각하는-방법&quot;&gt;1. 생각하는 방법&lt;/h2&gt;
&lt;p&gt;파일 시스템에 대해 학습할 때 이런 방식으로 접근하면 도움이 된다.&lt;/p&gt;
&lt;p&gt;첫 번째는 파일 시스템의 &lt;strong&gt;자료 구조&lt;/strong&gt;이다. 파일 시스템이 자신의 데이터와 메타데이터를 관리하기 위해 어떤 자료 구조를 사용할까? vsfs같은 파일 시스템은 블럭과 다른 객체들을 배열과 같은 간단한 자료 구조로 표현했지만 XFS와 같은 파일 시스템들은 좀 더 복잡한 트리 기반의 자료 구조를 사용한다.&lt;/p&gt;
&lt;p&gt;두 번째는 &lt;strong&gt;접근 방법&lt;/strong&gt;이다. 프로세스가 호출하는 &lt;code&gt;open()&lt;/code&gt;, &lt;code&gt;read()&lt;/code&gt;, &lt;code&gt;write()&lt;/code&gt; 등의 명령들은 파일 시스템의 자료 구조와 어떤 관련이 있을까? 특정 시스템 콜을 실행할 때 어떤 자료 구조들이 읽힐까? 어떤 것들이 쓰일까?&lt;/p&gt;
&lt;p&gt;자료 구조와 접근 방법에 대해 이해하면 파일 시스템이 어떻게 작동하는지에 대한 개념을 잘 정립할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;2-전체-구성&quot;&gt;2. 전체 구성&lt;/h2&gt;
&lt;p&gt;가장 먼저 해야 할 것은 디스크를 &lt;strong&gt;블럭(block)&lt;/strong&gt; 단위로 나누는 것이다. 단일 블럭 크기만 사용하고, 4KB로 정하자. N개의 4KB 블럭 크기를 가지는 파티션에서, 블럭은 0부터 N-1까지 주소를 가지고 있다. 블럭이 64개 있는 작은 디스크를 생각해보자.&lt;/p&gt;
&lt;p&gt;이 블럭에 무엇이 들어가야 할까? 가장 먼저 떠오르는 것은 사용자의 데이터이다. 대부분의 공간이 사용자의 데이터로 채워져 있다. 이를 &lt;strong&gt;데이터 영역 (data region)&lt;/strong&gt; 이라고 하자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698691347509.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1194&quot; height=&quot;282&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698691347509.Dz2L0LXw_Z1K8aXQ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;파일 시스템은 각 파일에 대한 정보를 관리한다. 그 정보가 &lt;strong&gt;메타데이터&lt;/strong&gt;의 핵심이다. 파일을 구성하는 데이터 블럭들, 그 파일의 크기, 소유자, 접근 권한, 접근과 변경 시간 등과 같은 정보가 메타데이터이다. 파일 시스템은 이러한 정보를 &lt;strong&gt;아이노드(inode)&lt;/strong&gt; 라고 부르는 자료 구조에 저장한다.&lt;/p&gt;
&lt;p&gt;이 아이노드들은 아이노드 테이블에 저장된다. 아이노드당 256bytes를 가정하면 4KB 블럭 하나에 16개의 아이노드를 저장할 수 있다. 우리 디스크 파티션에는 80개의 아이노드를 저장할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698691362740.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1164&quot; height=&quot;278&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698691362740.CxJ8tumc_Z1psHp5.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;아직 더 필요한 정보가 남아 있다. 아이노드나 데이터 블럭의 사용 여부에 관한 정보이다. &lt;strong&gt;할당 구조(allocation structure)&lt;/strong&gt; 가 필요하다.&lt;/p&gt;
&lt;p&gt;블럭이 사용 중인지 아닌지를 표현하는 데에는 다양한 방법이 있다. free list를 사용해서, 사용 중이 아닌 블럭들을 연결 리스트로 관리하는 방법도 있다. 아이노드는 첫 번째 프리 블럭의 위치만 기억하면 된다. 우리는 단순한 비트맵을 사용한다. 데이터 비트맵으로 데이터 영역이 사용 중인지, 아이노드 비트맵으로 아이노드 테이블에 있는 아이노드들이 사용 중인지를 나타낸다. 비트맵은 비트들의 배열이다. 각 비트는 해당 블럭이나 객체가 사용 중인지(in-use: 1) 사용 중이 아닌지(free: 0)나타낸다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698692494348.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1136&quot; height=&quot;274&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698692494348.CRon68yk_1507WF.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;남은 한 블럭은 &lt;strong&gt;슈퍼블럭(superblock)&lt;/strong&gt; 을 위한 공간이다 (S로 나타냄). 슈퍼블럭은 이 &lt;strong&gt;파일 시스템 전체에 대한 정보&lt;/strong&gt;를 담고 있다. 예를 들어, 파일 시스템에 몇 개의 아이노드와 데이터 블럭이 있는지, 아이노드 테이블은 어디서 시작하는지와 같은 정보를 가지고 있다. 파일 시스템을 식별할 수 있는 매직 넘버도 가지고 있다. 파일 시스템이 깨진다는 것은, 슈퍼블럭이 저장된 디스크 블럭이 훼손되는 것이다. 일반적으로 파일 시스템은 슈퍼블럭을 몇 개 복사해둔다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698692641707.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1168&quot; height=&quot;282&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698692641707.DaziJCKO_Z1Mf4DL.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;운영체제가 우선 슈퍼블럭을 읽어들여서 파일 시스템의 여러 요소들을 초기화하고, 그 후 각 파티션을 파일 시스템 트리에 붙이는 작업을 통해 &lt;strong&gt;파일 시스템을 마운트&lt;/strong&gt;한다.&lt;/p&gt;
&lt;h2 id=&quot;3-파일-구성-아이노드&quot;&gt;3. 파일 구성: 아이노드&lt;/h2&gt;
&lt;p&gt;파일 시스템의 자료 구조 중 가장 중요한 것은 &lt;strong&gt;아이노드&lt;/strong&gt;이다. index node의 줄임말이다.&lt;/p&gt;
&lt;p&gt;각 아이노드는 숫자 inumber로 표현된다. vsfs에서는 아이넘버를 통해 해당 아이노드가 디스크 어디에 있는지를 직접적으로 계산할 수 있다. 위에서 사용한 아이노드 테이블로 계산해보자. 아이노드 영역은 크기가 20KB이고 80개의 아이노드(각 256bytes)로 이루어져 있다. 아이노드 영역은 12KB 위치부터 시작한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698692990523.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1286&quot; height=&quot;324&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698692990523.BkQwe7XB_1eX2Fq.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;32번 아이노드를 읽기 위해 파일 시스템은 아이노드 영역에서의 오프셋을 계산한다. 그후 아이노드 테이블의 시작 위치를 더하면 원하는 아이노드 블럭의 정확한 바이트 주소를 계산할 수 있다.&lt;/p&gt;
&lt;p&gt;디스크는 바이트 단위로는 접근이 불가능하며, 대신에 512바이트 크기를 갖는 섹터로 이루어졌다. 32번 아이노드가 존재하는 블럭을 가져오기 위해 파일 시스템은 섹터 주소를 계산하여 읽기 요청을 한 후 해당 아이노드 블럭을 가져온다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;blk &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (inumber &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;inode_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; blockSize;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;sector &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ((blk &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; blockSize) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; inodeStartAddr) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sectorSize;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;아이노드에는 파일에 대한 정보가 다 들어있다. 파일의 종류, 크기, 할당된 블럭 수, 보호 정보, 시간 정보와 더불어 데이터 블럭이 디스크 어디에 존재하는지(포인터의 일종) 등과 같은 정보들이 담겨 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698720772308.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1252&quot; height=&quot;824&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698720772308.C1C7fULe_Z1VDSiA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;아이노드 설계시 가장 중요한 부분 중 하나는 데이터 블럭의 위치를 표현하는 방법이다. 간단한 방법은 아이노드 내에 여러 개의 &lt;strong&gt;직접 포인터&lt;/strong&gt;를 두는 것이다. 각 포인터는 파일의 디스크 블럭 하나를 가리킨다. 이 방법에는 파일 크기의 제한이 있다. 파일 크기가 &lt;strong&gt;포인터의 개수 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\times&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;×&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 블럭 크기&lt;/strong&gt;로 제한된다.&lt;/p&gt;
&lt;h3 id=&quot;멀티-레벨-인덱스&quot;&gt;멀티 레벨 인덱스&lt;/h3&gt;
&lt;p&gt;파일 크기 제한으로 인해, 파일 시스템 개발자들은 아이노드 내에 다른 자료 구조를 추가했다. 일반적으로는 &lt;strong&gt;간접 포인터&lt;/strong&gt;를 사용한다. 간접 포인터는 데이터 블럭을 가리키지 않고, &lt;strong&gt;데이터 블럭을 가리키는 포인터들이 저장된 블럭을 가리킨다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;블럭이 4KB이고 디스크 주소가 4바이트라고 하면 1024개의 포인터들을 추가할 수 있게 된다. 최대 파일 크기는 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;12&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1024&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(12 + 1024) \times 4&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;KB 가 된다. 여기서 12는 정해진 수의 직접 포인터이다.&lt;/p&gt;
&lt;p&gt;저 사이즈가 모자라면 &lt;strong&gt;이중, 삼중 간접 포인터&lt;/strong&gt;를 사용하면 원하는 만큼 큰 파일을 표현할 수 있다.&lt;/p&gt;
&lt;p&gt;이제까지 설명한 것을 종합하면, 디스크 블럭들은 트리 형태로 구성되어 하나의 파일을 이룬다. 이러한 구성 방식을 &lt;strong&gt;멀티 레벨 인덱스&lt;/strong&gt; 기법이라 한다.&lt;/p&gt;
&lt;p&gt;이 때 트리의 형태는 편향된 트리이다. 파일의 시작 부분을 이루는 블럭들은 한 번의 포인터로 접근 가능하지만, 파일의 끝부분에 있는 블럭들은 포인터를 세 번 따라가야 실제 블럭을 읽을 수 있다. 이렇게 설계된 이유는 &lt;strong&gt;대부분의 파일의 크기는 작다&lt;/strong&gt; 라는 사실에 기인한 것이다.&lt;/p&gt;
&lt;h2 id=&quot;4-디렉터리-구조&quot;&gt;4. 디렉터리 구조&lt;/h2&gt;
&lt;p&gt;vsfs의 디렉터리는 간단한다. 디렉터리는 (항목의 이름, 아이노드 번호) 쌍의 배열로 구성되어 있다. 디렉터리의 데이터 블럭에는 문자열과 숫자가 쌍으로 존재하며 문자열 길이에 대한 정보도 있다.&lt;/p&gt;
&lt;p&gt;dir이라는 디렉터리 안에 foo, bar, foobar 라는 3개의 파일이 있고 각각의 아이노드 번호가 12, 13, 24라고 하자. dir의 데이터 블럭은 아래와 같은 내용을 가지고 있을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698694041519.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;598&quot; height=&quot;176&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698694041519.RZfR3wGa_Z1cAOhY.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;아이노드 번호, 레코드 길이(이름에 사용된 총 바이트 + 남은 공간), 이름 길이, 항목의 이름으로 이루어져 있다.&lt;/p&gt;
&lt;p&gt;.은 현재 디렉터리, ..은 부모 디렉터리를 가리킨다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;unlink()&lt;/code&gt; 등의 호출로 파일이 삭제되면 디렉터리 중간에 빈 공간이 발생한다. 영역이 비었다는 것을 표시할 방법이 필요하다(ex: 아이노드 번호 0은 비었다는 뜻). 항목의 길이를 명시하는 이유 중 하나가 중간에 빈 공간이 생기기 때문이다. 새로운 디렉터리 항목을 생성할 때 빈 공간에 위치시킬 수 있다.&lt;/p&gt;
&lt;p&gt;디렉터리는 대체 어디에 저장되는 걸까? 대부분 파일 시스템에서 디렉터리는 특수한 종류의 파일로 간주한다. 디렉터리는 자신의 아이노드를 가지며, 아 아이노드는 아이노드 테이블에 존재한다. 디렉터리는 자신의 데이터 블럭을 가지고 있으며 이들 블럭의 위치는 일반 파일과 마찬가지로 아이노드에 명시되어 있다.&lt;/p&gt;
&lt;h2 id=&quot;5-빈-공간의-관리&quot;&gt;5. 빈 공간의 관리&lt;/h2&gt;
&lt;p&gt;vsfs에서는 두 개의 비트맵을 사용해서 빈 공간을 관리한다.&lt;/p&gt;
&lt;p&gt;파일 생성 시 아이노드를 할당해야 한다. 아이노드 비트맵을 탐색하여 비어 있는 아이노드를 찾아 파일에 할당한다. 파일 시스템은 해당 아이노드를 사용 중 (1) 로 표기하고 디스크 비트맵도 적절히 갱신한다. 데이터 블럭을 할당할 때도 이와 비슷하다.&lt;/p&gt;
&lt;p&gt;데이터 블럭을 할당할 때도 고려할 사항이 있다. 데이터 블럭 할당 시 가능하다면 여러 개의 블럭들이 연속적으로 비어 있는 공간을 할당한다. 이를 통해 해당 파일의 입출력 성능을 개선할 수 있다. 이를 &lt;strong&gt;선할당(pre-allocation)&lt;/strong&gt; 정책이라 한다.&lt;/p&gt;
&lt;h2 id=&quot;6-실행-흐름-읽기와-쓰기&quot;&gt;6. 실행 흐름: 읽기와 쓰기&lt;/h2&gt;
&lt;p&gt;파일 시스템은 마운트되었고 슈퍼블럭은 메모리 상에 위치한다고 가정하자. 다른 모든 것 (아이노드, 디렉터리)들은 디스크에 존재한다. 메모리에는 아직 탑재되지 않았다.&lt;/p&gt;
&lt;h3 id=&quot;디스크에서-파일-읽기&quot;&gt;디스크에서 파일 읽기&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;open(&quot;/foo/bar&quot;, O_RDONLY)&lt;/code&gt; 시스템 콜을 하면 파일 시스템은 먼저 파일 bar에 대한 아이노드를 찾아서 파일에 대한 기본적인 정보를 획득해야 한다. 전체 경로명을 가지고 있기 때문에 파일 시스템은 경로를 따라 원하는 아이노드를 찾는다.&lt;/p&gt;
&lt;p&gt;경로명을 따라가는 것은 항상 파일 시스템의 루트에서 시작한다. &lt;code&gt;/&lt;/code&gt;로 표기된다.&lt;/p&gt;
&lt;p&gt;루트 디렉터리의 아이노드를 찾아야 한다. 루트 디렉터리의 아이노드 번호는 보통 2로 정의되어 있다. 파일 시스템은 아이넘버 2가 포함된 블럭을 읽는다.&lt;/p&gt;
&lt;p&gt;파일 시스템은 읽어들인 아이노드에서 데이터 블럭의 포인터를 추출한다. 이 포인터들을 사용하여 디렉터리 정보를 읽고, foo 라는 항목을 찾는다. 디렉터리에 많은 항목이 들어있으면 여러 개의 데이터 블럭이 필요할 수 있다. 이들을 모두 읽어서 foo를 찾아야 한다.&lt;/p&gt;
&lt;p&gt;foo 파일의 디렉터리 항목을 찾아서, foo의 아이노드 번호를 파악한다. 44번이라고 하자. 이를 통해 bar에 대한 아이노드 번호도 찾아낼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;open()&lt;/code&gt;을 통해 bar에 대한 아이노드를 메모리에 적재한다. 파일 시스템에서는 최종적으로 해당 파일에 대한 접근 권한을 확인하고, 이 프로세스의 open file table에서 파일 디스크립터를 할당받아 사용자에게 리턴한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;open()&lt;/code&gt; 이후에는 &lt;code&gt;read()&lt;/code&gt; 시스템 콜을 통해 파일을 읽는다. 이 때 첫 번째 읽기 작업이므로 첫 번째 블럭을 읽게 될 것이고, 마지막으로 읽은 시간을 아이노드에 기록한다. &lt;code&gt;read()&lt;/code&gt;는 open file table에서 해당 파일 디스크립터에 대한 오프셋을 갱신한다. 다음 읽기 작업을 할 때 오프셋 다음부터 읽게 할 것이다.&lt;/p&gt;
&lt;p&gt;어느 시점이 되면 파일을 닫아야 하는데 이건 그냥 할당된 파일 디스크립터를 해제하면 된다. 디스크 I/O는 발생하지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698695920532.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1142&quot; height=&quot;686&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698695920532.BQxvqtEm_Z1oDSqY.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 그림에서는 파일을 여는 과정 중에 파일의 아이노드를 찾기 위해서 여러 번의 읽기가 일어나는 것을 보여주고 있다. 그 뒤에 각 블럭을 읽기 위해서 파일 시스템은 먼저 아이노드를 읽고 블럭을 읽는다. 그리고 아이노드의 마지막 접근 시간을 갱신한다. 무슨 일이 발생하는지 다시 한 번 차분히 이해해 보자.&lt;/p&gt;
&lt;p&gt;I/O 발생 횟수는 경로의 길이에 비례한다. 디렉터리가 많아지면 더 오래 걸린다.&lt;/p&gt;
&lt;h3 id=&quot;디스크에-쓰기&quot;&gt;디스크에 쓰기&lt;/h3&gt;
&lt;p&gt;디스크에 쓰기도 비슷한 과정이다.&lt;/p&gt;
&lt;p&gt;먼저 파일을 열고, &lt;code&gt;write()&lt;/code&gt;를 호출하여 새로운 내용으로 파일을 갱신한다. 최종적으로는 파일을 닫는다.&lt;/p&gt;
&lt;p&gt;읽기와는 다르게 파일 쓰기는 &lt;strong&gt;블럭 할당&lt;/strong&gt;을 필요로 할 수 있다. 새로운 파일에 쓸 때는 &lt;code&gt;write()&lt;/code&gt;는 데이터를 디스크에 기록해야 할 뿐만 아니라, &lt;strong&gt;파일에 어느 블럭을 할당해야 할 지&lt;/strong&gt;를 결정해야 하고, 그에 따라 데이터 비트맵, 아이노드 등을 갱신해야 한다.&lt;/p&gt;
&lt;p&gt;그러므로 파일에 대한 쓰기 요청은 &lt;strong&gt;논리적으로 5번의 I/O를 생성&lt;/strong&gt;한다.&lt;/p&gt;
&lt;ol&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;li&gt;실제 블럭에 기록&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;파일 생성과 같은 단순 작업에도 많은 양의 쓰기가 발생한다.&lt;/p&gt;
&lt;ol&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;li&gt;디렉터리 아이노드 읽기&lt;/li&gt;
&lt;li&gt;디렉터리 아이노드 쓰기&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;다음은 &lt;code&gt;/foo/bar&lt;/code&gt;를 생성하고 그 안에 세개의 블럭을 쓰는 과정이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 40 File System Implementation-1698696548926.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1110&quot; height=&quot;1068&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2040%20File%20System%20Implementation-1698696548926.BV-6BQne_Z1Eftg2.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;파일 생성이 얼마나 대형 작업인지를 알 수 있다. 경로명을 따라가서 파일을 생성하는 데 10번의 I/O가 발생했다. 그리고 &lt;code&gt;write()&lt;/code&gt; 한 번마다 5번의 I/O가 발생했다. 새로운 파일 블럭을 필요로 하는데 이를 &lt;strong&gt;allocating write&lt;/strong&gt;라 한다.&lt;/p&gt;
&lt;h2 id=&quot;7-캐싱과-버퍼링&quot;&gt;7. 캐싱과 버퍼링&lt;/h2&gt;
&lt;p&gt;I/O가 너무 많이 발생한다. 성능 개선을 위해 대부분 파일 시스템은 자주 쓰는 블럭들을 메모리에 캐싱한다. 가상 메모리에서 했던 것 처럼, LRU와 기타 캐시 교체 정책들을 고려해야 한다.&lt;/p&gt;
&lt;p&gt;캐싱과 함께하는 파일 열기&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;디렉터리 아이노드와 데이터로 인해 많은 I/O 발생&lt;/li&gt;
&lt;li&gt;같은 파일을 열면 캐시에서 히트가 되기 때문에 추가 I/O 발생하지 않음&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;캐싱과 함께하는 파일 쓰기&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;읽기 I/O는 캐시가 충분히 크면 대부분 제거 가능&lt;/li&gt;
&lt;li&gt;메모리에 쓴 경우, 영속성을 위해 이걸 디스크로 내려 보내야 한다.&lt;/li&gt;
&lt;li&gt;캐시는 쓰기 시점을 연기할 수 있다 -&gt; 쓰기 버퍼링
&lt;ul&gt;
&lt;li&gt;다수 작업 배치 처리&lt;/li&gt;
&lt;li&gt;스케줄링&lt;/li&gt;
&lt;li&gt;만들고 바로 삭제하는 경우 아예 없던 일로 할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DB 시스템 등은 버퍼링으로 발생하는 문제점을 용납하지 않는다. 방금 입금했는데 컴퓨터가 꺼져서 디스크에 기록이 되지 않았다면? 이런 일을 피하기 위해 &lt;code&gt;fsync()&lt;/code&gt;를 사용한다. 이를 호출하면 갱신된 내용이 디스크에 강제적으로 기록된다. 캐시를 아예 사용하지 않도록 하는 경우도 있다.&lt;/p&gt;</content:encoded><category>os</category><category>cs</category></item><item><title>OSTEP 38 Redundant Disk Arrays (RAID)</title><link>https://ks1ksi.io/blog/ostep-38-redundant-disk-arrays-raid/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-38-redundant-disk-arrays-raid/</guid><description>OSTEP RAID 정리. RAID 0, 1, 4, 5의 striping, mirroring, parity 구조와 용량, 신뢰성, 성능 trade-off를 설명한다.</description><pubDate>Mon, 30 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;RAID는 여러 개의 디스크를 조화롭게 사용하여 고속이면서 대용량의 신뢰할 수 있는 디스크 시스템을 만드는 기술이다. 하나의 디스크처럼 보이지만 사실은 여러 개의 디스크와 메모리, 시스템을 관리하기 위한 하나 또는 그 이상의 프로세서로 이루어진 복잡한 기계이다.&lt;/p&gt;
&lt;p&gt;RAID는 단일 디스크에 비해 여러 장점들을 제공한다. 첫 번째는 &lt;strong&gt;성능&lt;/strong&gt;이다. 디스크 여러 개를 병렬로 사용하면 I/O 시간이 크게 개선된다. 또 다른 장점은 &lt;strong&gt;용량&lt;/strong&gt;이다. 여러 디스크를 사용해서 용량을 늘릴 수 있다. 마지막 장점은 &lt;strong&gt;신뢰성&lt;/strong&gt;이다. 데이터 중복 기술을 사용해서 RAID는 디스크 고장이 전혀 없던 것 처럼 데이터를 잃지 않을 수 있다.&lt;/p&gt;
&lt;p&gt;호스트 시스템은 RAID를 그저 거대한 디스크로 인식한다. 운영체제와 클라이언트 응용 프로그램은 코드 한 줄 바꾸지 않고 RAID를 사용할 수 있다. 이 투명성은 RAID가 확산되는데 기여하였다.&lt;/p&gt;
&lt;h2 id=&quot;1-인터페이스와-raid의-내부&quot;&gt;1. 인터페이스와 RAID의 내부&lt;/h2&gt;
&lt;p&gt;파일 시스템이 RAID에 &lt;em&gt;논리적&lt;/em&gt; I/O를 요청하면 RAID 내부에서 어떤 디스크를 접근해야 요청을 완료할 수 있는지 계산한 후, 하나 혹은 그 이상의 &lt;em&gt;물리적&lt;/em&gt; I/O를 발생시킨다. 간단한 예로 서로 다른 디스크 2개에 복사본을 유지하는 &lt;em&gt;미러링 기반&lt;/em&gt; RAID를 생각해 보자. 이 시스템에서 블럭에 쓰기를 하는 경우, 하나의 논리적 I/O에 대해 두 개의 물리적 I/O가 발생한다.&lt;/p&gt;
&lt;p&gt;RAID 시스템은 보통 별도의 하드웨어 박스 형태로 되어 있고, 호스트와 SCSI / SATA와 같은 표준 인터페이스로 연결된다. RAID 시스템의 내부에는 작업을 지시하는 펌웨어를 위한 마이크로 컨트롤러, 블럭을 읽고 쓸 때 버퍼로 쓰는 휘발성 메모리 DRAM, 안전한 쓰기를 위한 비휘발성 메모리, 패리티 계산을 위한 전용 회로 등이 존재한다. 사실상 하나의 특수한 컴퓨터 시스템이다. 차이점은 응용 프로그램을 실행하는 대신 RAID를 동작시키기 위해 설계된 전용 소프트웨어를 실행한다는 점이다.&lt;/p&gt;
&lt;h2 id=&quot;2-결함-모델&quot;&gt;2. 결함 모델&lt;/h2&gt;
&lt;p&gt;RAID는 특정 종류의 결함을 파악하고 이를 복구하도록 설계되어 있다.&lt;/p&gt;
&lt;p&gt;가장 간단한 모델은 고장 시 멈춤 (fail-stop) 모델이다.&lt;/p&gt;
&lt;p&gt;이 모델에서 디스크는 “정상 작동” 이거나 “멈춤” 둘중 하나의 상태로 존재한다고 가정한다. 동작 중인 디스크에는 모든 블럭을 읽거나 쓸 수 있다. 멈춤 상태의 디스크는 완전히 사용 불가능하다고 간주한다.&lt;/p&gt;
&lt;p&gt;고장 시 멈춤 모델의 치명적인 단점은 &lt;strong&gt;결함이 발견되는 경우에 대한 가정&lt;/strong&gt;이다. 결함이 발생하면 바로 알 수 있을까? 쉽지 않은 일이다.&lt;/p&gt;
&lt;h2 id=&quot;3-raid의-평가-방법&quot;&gt;3. RAID의 평가 방법&lt;/h2&gt;
&lt;p&gt;3개의 축을 중심으로 RAID 설계를 평가할 것이다.&lt;/p&gt;
&lt;p&gt;첫 번째 평가의 축은 &lt;strong&gt;용량&lt;/strong&gt;이다. B개의 블럭을 가지는 N개의 디스크가 주어졌을 때 RAID의 클라이언트가 사용할 수 있는 유효 용량은 얼마일까? 중복 저장이 없는 경우라면 답은 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N \times B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 가 될 것이다. 각 블럭에 대해 두 개의 복사본을 가지는 경우 (미러링) 답은 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;÷&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(N \times B) \div 2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;÷&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 될 것이다. 패리티 기반 기법같이 다른 기법들은 그 사이의 값을 가지게 된다.&lt;/p&gt;
&lt;p&gt;두 번째 평가의 축은 &lt;strong&gt;신뢰성&lt;/strong&gt;이다. 평가 대상의 설계 방법은 몇 개의 디스크 결함을 감내할 수 있는가? 우리의 결함 모델에 따라 하나의 디스크만 고장날 수 있다고 가정하고, 좀 더 복잡한 결함 모드를 처리하는 방법은 추후에 알아보도록 하자.&lt;/p&gt;
&lt;p&gt;마지막 세 번째 평가의 축은 &lt;strong&gt;성능&lt;/strong&gt;이다. 디스크가 처리할 워크로드에 따라 성능 지표가 달라진다. 성능을 평가하기 이전에 고려해야 할 일반적인 워크로드를 제시할 것이다.&lt;/p&gt;
&lt;p&gt;이제 세 개의 중요한 RAID 설게를 살펴보며 평가해보자.
RAID 레벨 0(스트라이핑), RAID 레벨 1(미러링) 그리고 RAID 레벨 4/5(패리티에 기반을 둔 중복 저장)를 다루도록 하겠다.&lt;/p&gt;
&lt;h2 id=&quot;4-raid-레벨-0-스트라이핑&quot;&gt;4. RAID 레벨 0: 스트라이핑&lt;/h2&gt;
&lt;p&gt;가장 간단한 스트라이핑은 블럭들을 여러 디스크에 걸쳐서 줄을 긋는 것 처럼 저장한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698697470879.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;990&quot; height=&quot;370&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698697470879.BA72WOMF_ZF4qLa.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 접근법은 배열의 연속적인 청크에 대해 요청을 받았을 때 &lt;strong&gt;병렬성&lt;/strong&gt;을 가장 잘 활용할 수 있도록 설계되었다 . 같은 행에 있는 블럭들을 &lt;strong&gt;스트라이프(stripe)&lt;/strong&gt; 라고 부른다.&lt;/p&gt;
&lt;p&gt;이 예에서는 단순하게 하나의 블럭 (4KB)만이 다음 디스크로 넘어가기 전에 현재 디스크에 배치되도록 했다. 하지만 이렇게 배치할 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698674794744.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1198&quot; height=&quot;476&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698674794744.DbQDHtyj_ZBOmPq.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 예제에서는 각 디스크바다 두 개의 4KB 블럭을 배치한 후에 다음 디스크로 넘어갔다. 그러므로 이 RAID 배열의 &lt;strong&gt;청크 크기는 8KB&lt;/strong&gt;이고, &lt;strong&gt;스트라이프는 4개의 청크 또는 32KB&lt;/strong&gt; 크기의 데이터를 저장한다.&lt;/p&gt;
&lt;h3 id=&quot;청크-크기&quot;&gt;청크 크기&lt;/h3&gt;
&lt;p&gt;청크 크기는 RAID의 성능에 큰 영향을 준다. 작은 청크 크기는 많은 파일들이 여러 디스크에 걸쳐서 스트라이프 된다는 뜻이고 결국 &lt;strong&gt;하나의 파일을 읽고 쓰는데 병렬성이 증가&lt;/strong&gt;하게 된다.&lt;/p&gt;
&lt;p&gt;하지만 블럭의 위치를 여러 디스크에서 찾아야 하므로 &lt;strong&gt;위치 찾기&lt;/strong&gt; 시간이 늘어난다. 요청 처리 시간은 여러 디스크에 걸친 요청들 중 가장 오래걸린 찾기 시간에 의해 결정되기 때문이다.&lt;/p&gt;
&lt;p&gt;반면 큰 청크 크기의 경우에는 파일 내의 병렬성은 줄어들고 위치 찾기 시간은 줄어든다. 파일이 작아서 단일 청크에 저장이 된다면, 한 디스크에서 그 위치를 찾는 시간만큼 걸리기 때문이다.&lt;/p&gt;
&lt;p&gt;최적의 청크 크기를 정하는 것은 워크로드에 따라 다르다. 이 글에서는 청크 크기를 한 블럭의 크기 (4KB)로 가정하지만 대부분의 RAID에선 64KB처럼 큰 청크를 사용한다.&lt;/p&gt;
&lt;h3 id=&quot;평가&quot;&gt;평가&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;용량: 중복 저장이 없으므로 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N \times B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;신뢰성: 중복 저장이 없기 때문에 하나의 디스크라도 고장나면 데이터 손실 위험이 존재&lt;/li&gt;
&lt;li&gt;성능: 스트라이핑을 통해 여러 디스크에 동시에 데이터를 저장하므로 높은 성능 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;5-raid-레벨-1-미러링&quot;&gt;5. RAID 레벨 1: 미러링&lt;/h2&gt;
&lt;p&gt;미러링을 사용하는 시스템에서는 각 블럭에 대해 하나 이상의 사본을 둔다. 각 사본은 서로 다른 디스크에 저장되어야 한다. 이를 통해 디스크 고장에 대처할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698675720052.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;674&quot; height=&quot;438&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698675720052.CGkABwcF_23D1qt.webp&quot; &gt;&lt;/p&gt;
&lt;h3 id=&quot;평가-1&quot;&gt;평가&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;용량: 모든 데이터가 미러링되기 때문에 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;÷&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(N \times B) \div 2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;÷&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; . 비용이 좀 더 들게 된다&lt;/li&gt;
&lt;li&gt;신뢰성: 미러링 기법으로 인해 하나의 디스크가 고장나도 데이터가 손실되지 않는다. 최소 1개의 디스크 결함 감내 가능. 이론상 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;÷&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N \div 2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;÷&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개까지 감내 가능.&lt;/li&gt;
&lt;li&gt;성능: 읽기 성능은 양쪽 디스크에서 동시에 데이터를 읽을 수 있기 때문에 높은 편이지만, 쓰기 성능은 데이터를 두 디스크에 동시에 써야 하기 때문에 RAID 0에 비해 감소.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;6-raid-레벨-4-패리티를-이용한-공간-절약&quot;&gt;6. RAID 레벨 4: 패리티를 이용한 공간 절약&lt;/h2&gt;
&lt;p&gt;패리티 기반의 접근 방법은 저장 공간을 더 적게 사용하기 위해 나타났다. 미러링 기반 시스템의 공간 낭비를 해결해보자. 대신 성능은 좋지 못하다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698678115713.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;844&quot; height=&quot;434&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698678115713.B5Kkrp57_1qYbUe.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;각 데이터 스트라이프마다 해당 스트라이프에 대한 중복 정보를 담고 있는 &lt;strong&gt;패리티 블럭&lt;/strong&gt; 하나를 추가한다. 패리티를 계산하기 위해 스트라이프에 속해 있는 블럭 중 하나의 블럭이 고장나더라도 견딜 수 있게 하는 함수가 필요하다. &lt;strong&gt;XOR&lt;/strong&gt;을 이용해보자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698678418793.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;766&quot; height=&quot;222&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698678418793.LWCSHoXz_Z2oIWmT.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;1이 짝수 개일 때는 0을 반환하고 홀수 개일 때는 1을 반환한다.&lt;/p&gt;
&lt;p&gt;C2열이 깨졌다고 해보자. 그러면 그 열에 있었던 값들을 알아보기 위해 그 행의 모든 값을 읽은 후 올바른 값을 &lt;strong&gt;다시&lt;/strong&gt; 계산하면 된다. 첫 번째 행에서 C0, C1, C3의 값을 XOR 하면 1이 되고, XOR 값은 0이 되어야 하기 때문에 C2 값은 1이 되어야 한다는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;블럭 단위로 XOR은 어떻게 해야 할까?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698678929072.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;740&quot; height=&quot;242&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698678929072.D1RcHLVQ_1CPaDQ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;블럭의 각 비트들에 대해 XOR을 수행하면 된다.&lt;/p&gt;
&lt;h3 id=&quot;평가-2&quot;&gt;평가&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;용량: 패리티 정보의 저장을 위해 각 디스크 그룹에 속한 디스크 하나를 사용하기 때문에 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(N-1) \times B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 의 저장 공간을 제공한다.&lt;/li&gt;
&lt;li&gt;신뢰성: 오직 하나의 디스크 고장만을 감내할 수 있다. 두 개 이상의 디스크가 고장나면 패리티 계산이 불가능해 데이터를 복원할 수 없다.&lt;/li&gt;
&lt;li&gt;성능: 패리티 디스크를 제외한 모든 디스크를 활용할 수 있기 때문에 읽기 성능은 높다. 하지만 쓰기의 경우는 생각해볼 필요가 있다. 순차 쓰기의 경우는 &lt;em&gt;스트라이프 전부 쓰기&lt;/em&gt;로 최적화할 수 있다. 한 행에 모두 쓰면서 패리티까지 계산하고 쓸 수 있다. 랜덤 쓰기의 경우는 이전 블럭의 값이 새로 쓰는 값과 동일한지 보고, 패리티 비트를 반전시키는 방식을 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;문제점&quot;&gt;문제점&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698689027071.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;936&quot; height=&quot;424&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698689027071.2kJ13nRh_1DK8c5.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;블럭 4번과 13번을 갱신하는 쓰기는 병렬으로 처리될 수 있다. 하지만 패리티 1번과 3번을 읽어야 한다. 이 부분은 병렬으로 처리될 수 없다. 이같은 경우를 패리티 기반 RAID의 &lt;strong&gt;small-write&lt;/strong&gt; 문제라고 한다.&lt;/p&gt;
&lt;h2 id=&quot;7-raid-레벨-5-순환-패리티&quot;&gt;7. RAID 레벨 5: 순환 패리티&lt;/h2&gt;
&lt;p&gt;small-write 문제를 해결하기 위해 패리티 블럭을 순환시킨다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698689123661.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;922&quot; height=&quot;494&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698689123661.BJHoNt2b_ZbdPmi.webp&quot; &gt;&lt;/p&gt;
&lt;h3 id=&quot;평가-3&quot;&gt;평가&lt;/h3&gt;
&lt;p&gt;모두 RAID 4와 동일하지만 모든 디스크를 활용할 수 있기 때문에 랜덤 읽기 성능이 약간 더 좋고, 랜덤 쓰기 성능이 RAID 4에 비해 눈에 띄게 좋아진다.&lt;/p&gt;
&lt;h2 id=&quot;8-정리&quot;&gt;8. 정리&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 38 Redundant Disk Arrays (RAID)-1698689190850.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1220&quot; height=&quot;794&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2038%20Redundant%20Disk%20Arrays%20(RAID)-1698689190850.Nm8GHZ88_ZwVh33.webp&quot; &gt;&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 37 Hard Disk Drives</title><link>https://ks1ksi.io/blog/ostep-37-hard-disk-drives/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-37-hard-disk-drives/</guid><description>OSTEP Hard Disk Drives 정리. 디스크의 트랙, 섹터, 탐색 시간, 회전 지연, 전송 시간과 디스크 스케줄링의 기본을 요약한다.</description><pubDate>Tue, 10 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;파일 시스템 기술은 거의 대부분 하드 디스크 드라이브의 동작에 기반을 두고 개발되었다. 디스크를 관리하는 파일 시스템 소프트웨어를 구현하기 전에 디스크의 상세한 동작을 이해하는 것이 중요하다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;디스크에 데이터를 어떻게 저장하고 접근하는가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-인터페이스&quot;&gt;1. 인터페이스&lt;/h2&gt;
&lt;p&gt;우선 현대 디스크 드라이브의 인터페이스부터 이해해보자. 모든 현대 드라이브의 기본적인 인터페이스는 단순하다. 드라이브는 읽고 쓸 수 있는 매우 많은 수의 섹터 (512 byte 블럭)들로 이루어져 있다. 디스크 위의 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 섹터들은 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;부터 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;까지의 이름이 붙어 있다. 그렇기 때문에 디스크를 섹터들의 배열로 볼 수 있고, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;부터 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이 드라이브의 &lt;strong&gt;주소 공간&lt;/strong&gt;이 된다.&lt;/p&gt;
&lt;p&gt;멀티 섹터 작업도 가능하다. 사실 많은 파일 시스템들이 한 번에 4KB 또는 그 이상을 읽거나 쓴다. 하지만 드라이브 제조사는 하나의 512 byte 쓰기만 &lt;em&gt;원자적&lt;/em&gt;이라고 보장한다.&lt;/p&gt;
&lt;p&gt;디스크 드라이브 사용자들은 몇 가지 가정을 한다. 인터페이스에 명시되어 있지는 않다. (계약 불문율)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;드라이브의 주소 공간에서 가깝게 배치되어 있는 두 개의 블럭을 접근하는 것은, 멀리 떨어져 있는 두 개의 블럭을 접근하는 것보다 빠르다고 가정한다.&lt;/li&gt;
&lt;li&gt;연속적인 청크의 블럭을 접근하는 것 (순차 접근) 이 가장 빠르다. 어떤 랜덤 접근 패턴보다도 매우 빠르다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;2-기본-구조&quot;&gt;2. 기본 구조&lt;/h2&gt;
&lt;p&gt;원형의 딱딱한 표면을 가지고 있는 &lt;strong&gt;플래터(platter)&lt;/strong&gt; 에, 자기적 성질을 변형하여 데이터를 지속시킨다. 디스크는 하나 또는 그 이상의 플래터를 갖고 있으며, 각각은 2개의 표면을 갖고 있다. 이런 플래터는 대체적으로 단단한 알루미늄같은 물질로 만들어지며, &lt;strong&gt;드라이브의 전원이 나가더라도 비트를 드라이브에 영구적으로 저장&lt;/strong&gt;하기 위해 &lt;strong&gt;얇은 자성 층&lt;/strong&gt;이 입혀져 있다.&lt;/p&gt;
&lt;p&gt;플래터들은 &lt;strong&gt;회전축(spindle)&lt;/strong&gt; 이라는 것으로 고정되어 있다. 모터에 연결되어 있어 플래터를 일정한 속도로 회전시킨다. 회전 속도는 7200RPM ~ 15000RPM 정도이다. 만약 10000RPM의 속도로 드라이브가 회전한다면, 드라이브가 한 바퀴 회전하는 데 걸리는 시간은 6ms이다.&lt;/p&gt;
&lt;p&gt;각 표면에 동심원을 따라 배치되어 있는 &lt;strong&gt;섹터(sector)&lt;/strong&gt; 들 위에 데이터가 부호화된다. 이 때 동심원 하나를 &lt;strong&gt;트랙(track)&lt;/strong&gt; 이라고 한다. 표면에는 수많은 트랙들이 서로 촘촘하게 붙어 있다. 수백 개의 트랙들이 모여야 사람의 머리카락 두께 정도가 된다.&lt;/p&gt;
&lt;p&gt;표면 위를 읽거나 쓸 때에는 디스크의 자기적 패턴을 감지하거나 (읽거나) 변형을 유도하는 (쓰는) 기계적 장치가 필요하다. 읽기와 쓰기 동작은 &lt;strong&gt;디스크 헤드(disk head)&lt;/strong&gt; 라는 것을 통해 할 수 있으며 각 표면마다 그런 헤드가 하나씩 존재한다. 디스크 헤드는 &lt;strong&gt;디스크 암(disk arm)&lt;/strong&gt; 에 연결이 되어 있으며 이것을 통해서 헤드가 원하는 트랙 위에 위치하도록 이동시킬 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;3-간단한-디스크-드라이브&quot;&gt;3. 간단한 디스크 드라이브&lt;/h2&gt;
&lt;p&gt;디스크가 어떻게 동작하는지 이해하기 위해 한 트랙씩 모형을 만들어 보자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696879418338.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;892&quot; height=&quot;506&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696879418338.5VzqBWtl_ZwBhLU.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 트랙에는 12개의 섹터가 있고 각 섹터는 512바이트의 크기를 갖고 있으며 주소 영역은 0부터 11까지로 이루어져 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696879480625.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;660&quot; height=&quot;628&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696879480625.CSDK9Tw3_1znghc.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 디스크 헤드를를 붙여서 섹터에 무엇인가를 읽거나 쓸 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;단일-트랙-지연-시간-회전-지연&quot;&gt;단일 트랙 지연 시간: 회전 지연&lt;/h3&gt;
&lt;p&gt;트랙이 하나 뿐인 이 간단한 디스크에서 요청이 어떻게 처리될까? 디스크가 돌아서 디스크 헤드 아래에 원하는 섹터가 위치하기를 기다리면 된다.&lt;/p&gt;
&lt;p&gt;이런 기다림은 &lt;strong&gt;회전 지연(rotation delay)&lt;/strong&gt; 이라고 불린다.&lt;/p&gt;
&lt;h3 id=&quot;멀티-트랙-탐색-시간&quot;&gt;멀티 트랙: 탐색 시간&lt;/h3&gt;
&lt;p&gt;현대 디스크들은 수백만 개의 트랙을 가지고 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696880050395.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1278&quot; height=&quot;732&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696880050395.BQa8rBHR_ZmIf3n.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 그림에서 헤드는 가장 안쪽의 트랙에 위치하고 있다. 드라이브가 지정된 섹터들을 접근하는 방식을 이해해보자. 만약 섹터 11번처럼 멀리 떨어져 있는 섹터에 대한 요청을 받으면 어떻게 할까?&lt;/p&gt;
&lt;p&gt;이 읽기 요청을 처리하기 위해, 드라이브는 디스크 암을 먼저 올바른 트랙 위에 위치시킨다. 이 과정을 &lt;strong&gt;탐색(seek)&lt;/strong&gt; 이라고 한다. 회전과 더불어 탐색은 가장 비싼 디스크 동작 중 하나이다.&lt;/p&gt;
&lt;p&gt;탐색은 여러 단계로 이루어져 있다.&lt;/p&gt;
&lt;ol&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;안정화 시간은 매우 중요하며 0.5~2ms 정도로 오래 걸린다.&lt;/p&gt;
&lt;p&gt;탐색 과정에서 디스크 암이 원하는 트랙 위로 이동하는 동안, 플래터 역시 회전한다. 이 경우 3개의 섹터만큼 이동하였다. 섹터 9번이 디스크 헤드 아래로 지나가고 있다. 약간의 회전 지연 후 11번 섹터를 찾아 전송을 완료할 수 있게 될 것이다.&lt;/p&gt;
&lt;p&gt;섹터 11번이 디스크 헤드를 지나가게 되면, I/O의 마지막 단계인 &lt;strong&gt;전송&lt;/strong&gt;이 이루어져, 표면 위의 데이터를 읽거나 쓰게 된다. 이제 I/O 시간은 탐색과 회전 지연 동안 기다린 후 전송한다는 전체 윤곽이 그려졌다.&lt;/p&gt;
&lt;h3 id=&quot;그-외-세부-사항&quot;&gt;그 외 세부 사항&lt;/h3&gt;
&lt;p&gt;많은 드라이브는 &lt;strong&gt;트랙 비틀림(track skew)&lt;/strong&gt; 이라 불리는 기술을 사용해서 트랙의 경계를 지나 순차적으로 존해는 섹터들을 올바르게 읽을 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696880165840.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1028&quot; height=&quot;824&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696880165840.CDCh-JbH_Z1N0KXX.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;연속적인 트랙에서 데이터를 읽거나 쓸 때, 헤드가 한 트랙에서 다음 트랙으로 이동하는 시간을 고려하여, 다음 트랙의 시작 섹터를 해당 딜레이만큼 “skew”한다. 여기서는 2개 뒤로 skew 되어 있다.&lt;/p&gt;
&lt;p&gt;이런 skew가 없다면 헤드가 다음 트랙으로 넘어갔을 때 다음에 읽어야 하는 블럭이 이미 헤드를 지나쳤을 수도 있어 거의 한 바퀴에 해당하는 회전 지연을 감수해야 한다.&lt;/p&gt;
&lt;p&gt;또, 바깥 측에 공간이 더 많다는 구조적 이유 때문에, 바깥 트랙들에는 안쪽 트랙들보다 더 많은 섹터가 존재한다. 이를 multi zoned 디스크 드라이브 라고 부른다.&lt;/p&gt;
&lt;p&gt;마지막으로, 디스크 드라이브에 &lt;strong&gt;캐시(트랙 버퍼)&lt;/strong&gt; 가 존재한다. 디스크에서 하나의 섹터를 읽을 때 드라이브가 그 트랙 위의 모든 섹터를 다 읽어서 캐시에 저장할 수 있다.&lt;/p&gt;
&lt;p&gt;쓰기의 경우, 메모리에 데이터가 기록된 시점에 쓰기가 완료되었다고 할지, 디스크에 실제로 기록되었을 때 완료가 되었다고 할지를 정할 수 있다. 전자는 &lt;strong&gt;write-back&lt;/strong&gt;, 후자는 &lt;strong&gt;write-through&lt;/strong&gt; 라고 부른다.&lt;/p&gt;
&lt;p&gt;write-back 캐싱을 사용할 경우 드라이버가 더 빠른 것 처럼 보이지만 정합성에 문제가 생길 수도 있다.&lt;/p&gt;
&lt;h2 id=&quot;4-io-시간-계산&quot;&gt;4. I/O 시간 계산&lt;/h2&gt;
&lt;p&gt;간단한 분석으로 디스크의 성능을 구할 수 있다.&lt;/p&gt;
&lt;p&gt;세 개의 항으로 이루어진 다음 식으로, &lt;strong&gt;I/O 시간&lt;/strong&gt;을 나타낼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{I/O} = T_{seek} + T_{rotation} + T_{transfer}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0385em;vertical-align:-0.3552em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.5198em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3552em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;see&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.03148em;&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3117em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;ro&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9694em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I/O의 속도&lt;/strong&gt;는 다음의 식과 같이 간단하게 나타낼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;R_{I/O} = \frac{Size_{Transfer}}{T_{I/O}}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0385em;vertical-align:-0.3552em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.00773em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.5198em;margin-left:-0.0077em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3552em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.5951em;vertical-align:-0.6036em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9914em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.3448em;margin-left:-0.1389em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5357em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3695em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.5131em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.04398em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.3488em;margin-left:0em;margin-right:0.0714em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.5em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size3 size1 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2901em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6036em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;두 개의 워크로드가 있다고 가정하자.&lt;/p&gt;
&lt;p&gt;하나는 &lt;strong&gt;랜덤 워크로드&lt;/strong&gt;로 디스크에 4KB의 작은 읽기 요청을 발생시킨다. 랜덤 워크로드는 DBMS 등에서 흔하게 사용된다.&lt;/p&gt;
&lt;p&gt;다른 하나는 &lt;strong&gt;순차 워크로드&lt;/strong&gt;로서 헤드의 이동 없이 디스크에 연속되어 있는 여러개의 섹터를 단순히 읽는 것이다. 순차 접근 패턴 역시 흔하기 때문에 마찬가지로 중요한 워크로드이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696882282416.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1026&quot; height=&quot;464&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696882282416.BJ3N16s6_1sLbe4.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;하나는 고성능 드라이브, 빠르게 회전하도록 설계되어 있어 낮은 탐색 시간과 빠른 데이터 전송 속도를 가지고 있다.
다른 하나는 용량, 속도는 낮지만 주어진 공간에 가능한 많은 비트를 저장한다.&lt;/p&gt;
&lt;p&gt;그림에 나타난 드라이브의 값들을 사용하여 앞에서 정리한 두 개의 워크로드가 얼마나 잘 동작하는지를 계산해 볼 수 있다. 먼저 랜덤 워크로드의 경우를 살펴보자. 랜덤한 디스크의 위치에서 4 KB씩 읽기가 발생한다고 했을 때 Cheetah에서 각 읽기가 얼마나 오래 걸릴지를 다음의 식처럼 계산할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{seek} = 4ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;see&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.03148em;&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{rotation} = 2ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3117em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;ro&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;30&lt;/mn&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{transfer} = 30 us&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9694em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10764em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 이고, 따라서 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{I/O}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0385em;vertical-align:-0.3552em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.5198em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3552em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 약 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;6ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 된다. (전송 시간 무시)&lt;/p&gt;
&lt;p&gt;회전 시간은 RPM으로 쉽게 구할 수 있다. 한 바퀴 도는 데 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;4ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 걸리고, 평균적으로 절반 정도 회전하기 때문에 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;로 계산했다.&lt;/p&gt;
&lt;p&gt;그러므로 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;R_{I/O}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0385em;vertical-align:-0.3552em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.00773em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.5198em;margin-left:-0.0077em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3552em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 0.66 MB/s가 된다.&lt;/p&gt;
&lt;p&gt;같은 방식으로 계산하면 Barracuda의 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{I/O}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0385em;vertical-align:-0.3552em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.5198em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3552em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 약 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;13.2&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;13.2ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;13.2&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;R_{I/O}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0385em;vertical-align:-0.3552em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.00773em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.5198em;margin-left:-0.0077em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3552em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 0.31 MB/s이다.&lt;/p&gt;
&lt;p&gt;이제 순차 워크로드를 살펴보자. 아주 긴 시간의 전송 전에 한 번의 탐색과 회전이 있다고 가정해 보자. 논의하기 쉽도록 전송할 데이터의 크기는 100 MB라고 하자. 그러면 Barracuda와 Cheetah의 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{I/O}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0385em;vertical-align:-0.3552em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3448em;&quot;&gt;&lt;span style=&quot;top:-2.5198em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.07847em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3552em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 각각 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;800&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;800 ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;950&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;950 ms&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;950&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 된다. I/O의 속도는 드라이브의 최고 전송 속도인 125 MB/s와 105 MB/s와 거의 비슷하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696882925270.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;954&quot; height=&quot;312&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696882925270.D0rwGiPb_ZogRwy.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 그림은 몇 가지 중요한 사실을 알려준다. 첫 번째 가장 중요한 사실은 랜덤 워크로드와 순차 워크로드의 드라이브 간 성능 차이가 크다는 것이다. Cheetah의 경우에는 거의 200배 이상 차이 나고, Barracuda의 경우 300배 이상 차이가 난다. 이렇게 컴퓨터 역사 상 가장 분명한 디자인 팁에 이르게 된다.&lt;/p&gt;
&lt;p&gt;두 번째는 좀 더 미묘한데 “성능” 위주의 드라이브와 저사양의 “용량” 위주의 드라이브 간의 성능 차이가 상당히 크다는 것이다. 이러한 이유로 (또한 다른 이유로) 전자를 위해서는 비싼 돈을 들이는 데 주저하지 않으면서도 후자를 구하기 위해서는 가능한 싸게 사려고 한다.&lt;/p&gt;
&lt;h2 id=&quot;5-디스크-스케줄링&quot;&gt;5. 디스크 스케줄링&lt;/h2&gt;
&lt;p&gt;I/O의 비용이 크기 때문에 역사적으로 운영체제는 디스크에게 요청되는 I/O의 순서를 결정하는 데 중요한 역할을 했다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;디스크 스케줄러&lt;/strong&gt;는 요청을 보고 다음에 어떤 I/O를 처리할지 결정하였다.&lt;/p&gt;
&lt;p&gt;각 작업의 길이가 얼마나 될지 알 수 없는 작업 스케줄링과는 다르게, 디스크 스케줄링의 경우 요청 작업이 얼마나 걸릴지를 꽤 정확하게 예측할 수 있다. 따라서 greedy하게 처리할 수 있는 가장 빠른 요청을 선택할 수 있다.&lt;/p&gt;
&lt;p&gt;즉 디스크 스케줄러는 &lt;strong&gt;SJF(shortest job first)&lt;/strong&gt; 원칙을 따르려고 노력한다.
기억이 잘 나지 않으면 &lt;a href=&quot;https://ks1ksi.io/blog/ostep-07-cpu-scheduling/&quot;&gt;OSTEP 07 CPU Scheduling&lt;/a&gt; 파트를 다시 읽어보자.&lt;/p&gt;
&lt;h3 id=&quot;최단-탐색-시간-우선shortest-seek-time-first-sstf&quot;&gt;최단 탐색 시간 우선(Shortest-seek-time-first, SSTF)&lt;/h3&gt;
&lt;p&gt;초기에는 이 방법을 사용했다. 트랙을 기준으로 I/O 요청 큐를 정렬하여 가장 가까운 트랙의 요청이 우선 처리되도록 하였다. 예를 들어, 현재 헤드가 안쪽 트랙에 위치해 있고, 가운데 트랙의 섹터와 바깥 트랙의 섹터에 대한 요척을 받으면, 가운데 트랙의 요청을 먼저 처리하고, 완료된 후 바깥 트랙의 요청을 처리한다.&lt;/p&gt;
&lt;p&gt;하지만 SSTF가 만능은 아니다. 드라이브의 구조는 호스트 OS에게 공개되어 있지 않고, 운영체제는 그저 블럭들의 배열로만 인식한다. 때문에 가장 가까운 블럭 우선(Nearest-block-first, NBF) 방식을 사용하면 된다.&lt;/p&gt;
&lt;p&gt;더 큰 문제는 기아 현상이다. 계속 안쪽 트랙에만 지속적으로 요청이 발생되면, 바깥 트랙은 읽을 수 없게 된다.
기아 현상을 해결해보자.&lt;/p&gt;
&lt;h3 id=&quot;elevator-aka-scan-or-c-scan&quot;&gt;Elevator (a.k.a. SCAN or C-SCAN)&lt;/h3&gt;
&lt;p&gt;SCAN이라고 불렸던 이 알고리즘은 트랙의 순서에 따라 디스크를 앞뒤로 가로지르며 요청을 서비스한다. 디스크를 한 번 가로지르는 것을 sweep 이라고 부르자. 따라서 어떤 요청이 이번 스위프에 이미 지나간 트랙에 대해 들어온다면, 다음 번 스위프에 처리되도록 큐에서 대기한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696884828781.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;388&quot; height=&quot;363&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696884828781.lL96Na5W_1h4DAW.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;F-SCAN은 스위프하는 동안 큐를 동결시켜 멀리 떨어져 있는 요청에 대한 기아 현상을 없애는 방법이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696885005945.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1152&quot; height=&quot;606&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696885005945.fhn2Xi7Y_Z28rD4I.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;C-SCAN(Circular SCAN) 알고리즘은 디스크를 가로질러 양방향으로 스위핑하는 대신에 외부에서 내부로만 스위핑한 다음 외부 트랙에서 재설정하여 다시 시작한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696884834206.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;388&quot; height=&quot;363&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696884834206.DgyGsTw9_1Q7GYq.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;이 기법들은 회전을 무시한다.&lt;/strong&gt;&lt;/em&gt; 따라서 최적은 아니다.&lt;/p&gt;
&lt;h3 id=&quot;최단-위치-잡기-우선shortest-positioning-time-first---sptf&quot;&gt;최단 위치 잡기 우선(shortest positioning time first) - SPTF&lt;/h3&gt;
&lt;p&gt;최단 접근 시간 우선(shortest access time first) 이라고도 불리는 기법이다. 어떤 섹터로 접근하는게 가장 빠를까?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 37 Hard Disk Drives-1696885123195.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;934&quot; height=&quot;892&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2037%20Hard%20Disk%20Drives-1696885123195.BoBqjXh4_ZbLLWE.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;헤드가 섹터 30번에 위치해 있는데, 스케줄러는 다음 요청을 처리하기 위해 8번 섹터로 가야할까 아니면 16번 섹터로 가야할까? 정답은 &lt;strong&gt;상황에 따라 다르다&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;여기서 상황에 의존적인 이유는 &lt;strong&gt;탐색에 걸리는 시간과 회전에 걸리는 시간이 다르기 때문이다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;때문에 SPTF가 성능을 개선시킬 수 있다. 하지만 트랙의 경계가 어디인지, 현재 디스크 헤드가 어디인지(회전의 관점에서)를 정확히 할 수 없기 때문에 운영체제에서 이를 구현하기는 어렵고, 드라이브 내부에서 실행된다.&lt;/p&gt;
&lt;h3 id=&quot;다른-쟁점들&quot;&gt;다른 쟁점들&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;디스크 스케줄링은 현대 시스템에서 어느 부분이 담당해야 하는가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;예전에는 운영체제가 모든 것을 결정하였다.&lt;/p&gt;
&lt;p&gt;현대 시스템에서, 디스크는 대기 중인 여러 개의 요청들을 수용할 수 있으며 복잡한 내부 스케줄러를 자체적으로 가지고 있다. 이 스케줄러는 디스크 컨트롤러 내부에 있기 때문에 헤드의 정확한 위치도 알 수 있을 뿐만 아니라 그 외의 필요한 정보들도 알 수 있다. 그래서 &lt;strong&gt;SPTF&lt;/strong&gt; 방식을 정밀하게 구현할 수 있다.&lt;/p&gt;
&lt;p&gt;디스크 스케줄러가 수행하는 또 다른 중요한 작업은 &lt;strong&gt;I/O 병합&lt;/strong&gt;이다. 33번, 8번, 34번을 읽는 연속된 요청이 있을 때, 33번과 34번을 읽는 요청을 병합하여 두 블럭 길이의 요청으로 만든다. 디스크로 내려보내는 요청의 개수를 줄여 오버헤드를 줄일 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;병합을 위해 얼마나 기다려야 하는가&lt;/strong&gt;도 고민해볼 문제 중 하나이다.&lt;/p&gt;
&lt;h2 id=&quot;6-요약&quot;&gt;6. 요약&lt;/h2&gt;
&lt;p&gt;전자공학과 재료공학과 화이팅~&lt;/p&gt;</content:encoded><category>os</category><category>cs</category></item><item><title>OSTEP 36 IO Devices</title><link>https://ks1ksi.io/blog/ostep-36-io-devices/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-36-io-devices/</guid><description>OSTEP IO Devices 정리. 장치 인터페이스, polling과 interrupt, DMA, 운영체제가 I/O 장치를 다루는 기본 구조를 설명한다.</description><pubDate>Mon, 09 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Three Easy Pieces 중 마지막 &lt;strong&gt;Persistence(영속성)&lt;/strong&gt; 하나 남았다. 영속성에 대해 소개하기 전, 입출력 장치의 개념을 소개하고, 운영체제가 어떻게 이들과 상호작용 하는지 알아 보도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;1-시스템-구조-system-architecture&quot;&gt;1. 시스템 구조 (System Architecture)&lt;/h2&gt;
&lt;p&gt;우선 일반적인 시스템 구조에 대해 알아야 한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696860281452.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1020&quot; height=&quot;936&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696860281452.B0Um89K9_fxfDj.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;CPU와 메인 메모리가 &lt;strong&gt;Memory Bus&lt;/strong&gt;로 연결되어 있다. 또 몇 가지 장치들이 범용 &lt;strong&gt;I/O Bus&lt;/strong&gt;에 연결되어 있다. 보통 &lt;strong&gt;PCI&lt;/strong&gt;를 사용하고, 여기에 그래픽 카드나 다른 고성능 I/O 장치들이 연결된다. 마지막으로, SCSI, SATA, USB같은 &lt;strong&gt;Peripheral I/O Bus&lt;/strong&gt; (주변장치용 버스) 가 있다. 이 버스들을 통해 디스크나 마우스같이 가장 느린 주변 장치가 연결된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696875011175.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1064&quot; height=&quot;924&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696875011175.D-vba3lX_Z1GoNE8.webp&quot; &gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“PCI”는 “Peripheral Component Interconnect”의 약자로, 1990년대 중반부터 2000년대 초반까지 컴퓨터에서 주로 사용되던 IO Bus 표준 중 하나입니다.&lt;/p&gt;
&lt;p&gt;PCI에 대한 몇 가지 주요 특징은 다음과 같습니다:&lt;/p&gt;
&lt;p&gt;플러그 앤 플레이: 장치를 컴퓨터에 연결하면 운영 체제가 자동으로 장치를 감지하고 설정합니다.&lt;/p&gt;
&lt;p&gt;32비트와 64비트 버전: 초기 PCI 버스는 32비트 데이터 경로를 사용했지만, 나중에 64비트 버전도 출시되었습니다.&lt;/p&gt;
&lt;p&gt;높은 데이터 전송 속도: PCI 버스는 그 당시 다른 버스 표준에 비해 높은 데이터 전송 속도를 제공했습니다.&lt;/p&gt;
&lt;p&gt;범용성: 여러 종류의 장치 (그래픽 카드, 네트워크 카드, 사운드 카드 등)와 호환됩니다.&lt;/p&gt;
&lt;p&gt;그러나 PCI는 오래된 기술이기 때문에 현대의 PC나 서버에서는 더 빠른 성능과 확장성을 제공하는 PCI Express (PCIe)와 같은 새로운 표준에 의해 대체되었습니다. PCIe는 PCI의 후속 표준으로, 데이터 전송 속도와 확장성, 그리고 세밀한 전력 관리 기능 등 여러 가지 향상된 기능을 제공합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이렇게 계층적인 구조를 만든 이유는 무엇일까? 버스가 고속화되려면 짧아야 한다. 때문에 고속의 메모리 버스는 여러 장치들을 수용할 공간이 없고, 그런 고속의 메모리 버스는 굉장히 비싸다. 때문에 그래픽 카드와 같은 고성능 장치는 CPU와 가깝게 배치하고, 디스크와 같은 느린 장치들은 주변 장치 I/O 버스에 연결했다. 이런 느린 장치들은 여러 개 연결할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;2-표준-장치-a-canonical-device&quot;&gt;2. 표준 장치 (A Canonical Device)&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696872204065.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1082&quot; height=&quot;404&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696872204065.Bv1cmO7b_Z1b0HuA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;표준 장치에는 두 개의 중요한 구성 요소가 있다. 첫 번째는 &lt;strong&gt;인터페이스(Interface)&lt;/strong&gt; 이다. 소프트웨어가 인터페이스를 제공하듯, &lt;strong&gt;하드웨어도 인터페이스를 제공&lt;/strong&gt;하여 시스템 소프트웨어가 동작을 제어할 수 있도록 해야 한다.&lt;/p&gt;
&lt;p&gt;두 번째 구성 요소는 &lt;strong&gt;내부 구조(Internals)&lt;/strong&gt; 이다. &lt;strong&gt;시스템에게 제공하는 장치에 대한 추상화&lt;/strong&gt;를 정의하는 책임을 가지고 있다.  내부 구조 안에는 장치에 따라 다르지만 한두개의 하드웨어 칩을 사용하는 경우도 있고, CPU와 범용 메모리, 그리고 장치에 특화된 칩을 사용하는 경우도 있다.&lt;/p&gt;
&lt;p&gt;최신 RAID 컨트롤러는 수십만 줄에 달하는 &lt;strong&gt;펌웨어&lt;/strong&gt; 라는 소프트웨어가 하드웨어 내부의 동작을 정의하고 있다.&lt;/p&gt;
&lt;h2 id=&quot;3-표준-방식-the-canonical-protocol&quot;&gt;3. 표준 방식 (The Canonical Protocol)&lt;/h2&gt;
&lt;p&gt;위에 그려진 표준 장치 그림을 보면, 세 개의 레지스터가 존재하는 것을 볼 수 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;상태(status)&lt;/strong&gt; 레지스터는 장치의 현재 상태를 읽을 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;명령어(command)&lt;/strong&gt; 레지스터는 장치가 특정 동작을 수행하도록 요청할 때 사용된다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터(data)&lt;/strong&gt; 레지스터는 장치에 데이터를 보내거나 받을 때 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이번에는 장치가 운영체제를 대신하여 어떤 동작을 할 때, 운영체제와 장치 간에 일어날 수 있는 상호 작용 과정을 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;While&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (STATUS &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; BUSY)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 장치가 바쁜 상태가 아닐 때까지 대기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;데이터를 DATA 레지스터에 쓰기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;명령어를 COMMAND 레지스터에 쓰기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	(장치가 명령어 실행)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;While&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (STATUS &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; BUSY)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 요청이 완료될 때까지 대기&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;표준 방식 (Canonical Protocol)은 네 단계로 이루어져 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;반복적으로&lt;/strong&gt; 장치의 상태 레지스터를 읽어서 명령의 수신 가능 여부를 확인한다. -&gt; 장치에 대해 &lt;strong&gt;폴링(polling)&lt;/strong&gt; 한다고 표현함&lt;/li&gt;
&lt;li&gt;운영체제가 데이터 레지스터에 어떤 데이터를 전달한다. ex) 디스크 블럭. 데이터 전송에 메인 CPU가 관여하는 경우를 &lt;strong&gt;programmed I/O&lt;/strong&gt; 라고 한다.&lt;/li&gt;
&lt;li&gt;운영체제가 명령어 레지스터에 명령어를 기록한다. 명령어가 기록되면 데이터는 이미 준비되었다고 가정하고 명령어를 처리한다.&lt;/li&gt;
&lt;li&gt;장치가 처리를 완료했는지를 확인한다. 여기서도 폴링한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 표준 방식 (Canonical Protocol)은 계속 polling을 하기 때문에 비효율적이다. 다른 프로세스에게 CPU를 양도하지 않고 장치가 동작을 완료하는 동안 계속 반복문을 돌며 상태를 확인한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;폴링 사용에 대한 cost를 어떻게 피할 수 있을까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;4-인터럽트를-이용한-cpu-오버헤드-개선&quot;&gt;4. 인터럽트를 이용한 CPU 오버헤드 개선&lt;/h2&gt;
&lt;p&gt;디바이스를 계속 polling 하는 대신 운영체제는 입출력 작업을 요청한 프로세스를 block 시키고, CPU를 다른 프로세스에게 양도한다. 장치가 작업을 끝마치면, 하드웨어 인터럽트를 발생시키고, CPU는 운영체제가 미리 정의해놓은 &lt;strong&gt;인터럽트 서비스 루틴(interrupt service routine(ISR))&lt;/strong&gt; 또는 간단하게 &lt;strong&gt;인터럽트 핸들러(interrupt handler)&lt;/strong&gt; 를 실행한다. 이 핸들러는 운영체제 코드의 일부분이다.&lt;/p&gt;
&lt;p&gt;인터럽트 핸들러는 입출력 요청의 완료, I/O 대기중인 프로세스 깨우기 등을 담당한다.&lt;/p&gt;
&lt;p&gt;사용률을 높이기 위한 핵심 방법 중 하나는 인터럽트를 활용하여 CPU 연산과 I/O 연산을 &lt;strong&gt;중첩&lt;/strong&gt;시키는 것이다. 그림으로 알아보자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696873722013.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1334&quot; height=&quot;212&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696873722013.UOWxViyA_Z24SVyU.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 예제는 CPU가 장치의 작업이 끝날 때 까지 polling 하는 것이고,&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696873741066.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1380&quot; height=&quot;250&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696873741066.DTxKw-D1_ZhnN5u.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 예제는 장치가 작업을 하는 동안 CPU가 다른 프로세스 2를 실행하는 것이다.
디스크 요청이 완료되어 인터럽트가 발생하면 운영체제가 다시 프로세스 1을 깨워 실행시킨다.&lt;/p&gt;
&lt;p&gt;인터럽트가 항상 최적의 해법은 아니다. 작업이 한 번의 폴링만으로 끝나는 매우 빠른 작업이라면, 인터럽트가 시스템을 느리게 할 것이다. Context Switching, 인터럽트 처리는 매우 비싼 작업이다. 빠른 장치에 대해서는 polling, 느린 장치에 대해서는 인터럽트가 좋은 해법이 될 것이다.&lt;/p&gt;
&lt;p&gt;만약 장치의 속도를 잘 모르거나, 빠를 때도 있고 느릴 때도 있는 장치라면 어떻게 하는게 좋을까? 짧은 시간 동안 폴링을 하다 처리가 완료되지 않으면 인터럽트를 사용하는 하이브리드 방식을 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;네트워크 환경에서도, 대량으로 패킷이 도착하는 경우 인터럽트를 사용한다면, live lock에 빠질 가능성이 높다. 사용자가 많이 몰리면 웹 서버가 폴링을 사용해서 좀 더 효율적으로 처리할 수 있다.&lt;/p&gt;
&lt;p&gt;또 다른 인터럽트 최적화 기법은 &lt;strong&gt;병합(coalescing)&lt;/strong&gt; 이다. CPU에게 인터럽트를 전달하기 전에 잠시 기다린 후, 한 번에 모아서 인터럽트를 전달한다. 이 방법으로 인터럽트 처리의 오버헤드를 줄일 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;5-dma를-이용한-효율적인-데이터-이동&quot;&gt;5. DMA를 이용한 효율적인 데이터 이동&lt;/h2&gt;
&lt;p&gt;많은 양의 데이터를 디스크로 전달하기 위해 programmed I/O (PIO)를 사용하면 CPU가 또 다시 단순 작업 처리에 소모된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696874902759.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1126&quot; height=&quot;158&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696874902759.coQHHeLj_Z1pnXd6.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이런 식으로 데이터를 메모리에서 디스크로 한 워드씩 copy한다. 그림에서 c로 표시된 부분이다.&lt;/p&gt;
&lt;p&gt;이 문제에 대한 해법을 &lt;strong&gt;직접 메모리 접근 방식(Direct Memory Access, DMA)&lt;/strong&gt; 이라고 부른다. DMA 엔진은 시스템 내에 있는 특수 장치로서, CPU의 간섭 없이 메모리와 장치 간의 데이터 전송을 담당한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696874912204.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1150&quot; height=&quot;242&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696874912204.DPo7PU89_Za5cdr.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;데이터를 장치로 전송한다고 했을 때, 운영체제는 DMA 엔진에 메모리 상의 데이터 위치와 전송할 데이터의 크기, 그리고 대상 장치를 프로그램한다. 그러면 데이터가 전송되는 동안 운영체제는 다른 일을 진행할 수 있다. DMA 동작이 끝나면 DMA 컨트롤러가 인터럽트를 발생시키고, 운영체제는 전송이 완료되었음을 알 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;6-장치와-상호작용하는-방법&quot;&gt;6. 장치와 상호작용하는 방법&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;장치와 운영체제가 실제로 정보를 어떻게 교환할까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;첫 번째는 가장 오래된 방법으로, I/O 명령을 명시적으로 사용하는 것이다. 이 명령어들은 운영체제가 특정 장치 레지스터에 데이터를 전송할 수 있는 방법을 제공한다.&lt;/p&gt;
&lt;p&gt;예를 들어 x86의 경우 &lt;code&gt;in&lt;/code&gt;과 &lt;code&gt;out&lt;/code&gt; 명령어를 사용하여 장치들과 통신할 수 있다. 이 명령어들은 대부분 특권 명령어들이다. 때문에 운영체제만이 장치들과 직접 통신할 수 있다.&lt;/p&gt;
&lt;p&gt;두 번째 방법은 &lt;strong&gt;memory mapped I/O&lt;/strong&gt; 이다. 하드웨어는 장치의 레지스터들이 &lt;strong&gt;마치 메모리 상에 존재하는 것 처럼&lt;/strong&gt; 만든다. 특정 레지스터를 접근하기 위해서 운영체제는 해당 주소에 &lt;code&gt;load&lt;/code&gt;, &lt;code&gt;store&lt;/code&gt;를 하면 된다. 하드웨어는 &lt;code&gt;load&lt;/code&gt;, &lt;code&gt;store&lt;/code&gt; 명령어가 주 메모리를 향하는 대신 장치로 연결되게 한다.&lt;/p&gt;
&lt;h2 id=&quot;7-운영체제에-연결하기-장치-드라이버&quot;&gt;7. 운영체제에 연결하기: 장치 드라이버&lt;/h2&gt;
&lt;p&gt;최종적으로 다룰 문제는 서로 다른 인터페이스를 가지는 수많은 장치들과 운영체제를 연결시키는 일반화된 방법을 찾는 것이다.&lt;/p&gt;
&lt;p&gt;SCSI 디스크, IDE 디스크, USB 등과 같은 기기 위에서 동작하는 파일 시스템을 만들고자 하는데, 각 장치들의 구체적인 입출력 명령어 형식에 종속되게 만들고 싶지 않다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;어떻게 장치 중립적인 운영체제를 만들 수 있을까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;추상화(abstraction)라는 고전적 방법을 사용하여 이 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696879226707.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1070&quot; height=&quot;580&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696879226707.C6irHYpE_1Qumd.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;파일 시스템은 어떤 디스크 종류를 사용하는지 전혀 알지 못한다. 파일 시스템은 범용 블록 계층에 블럭 &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;를 요청할 뿐이다. 범용 블럭 계층은 적절한 디바이스 드라이버로 받은 요청을 전달하며, 디바이스 드라이버는 특정 요청을 장치에 내리기 위해 필요한 일들을 처리한다. 이 그림을 통해 장치에 대한 구체적인 동작이 어떻게 운영체제의 대부분에게 숨겨지는지 알 수 있다.&lt;/p&gt;
&lt;p&gt;이런 캡슐화는 단점도 있다. 커널이 범용적인 인터페이스만을 제공하는 경우, 특수 기능을 많이 가진 장치는 사용하기 힘들 것이다.&lt;/p&gt;
&lt;p&gt;어떤 장치를 시스템에 연결하든 디바이스 드라이버가 필요하기 때문에, &lt;strong&gt;시간이 지나면서 디바이스 드라이버 코드가 커널 코드의 대부분을 차지하게 되었다.&lt;/strong&gt; 드라이버들이 대부분 전업 커널 개발자가 아닌 개발자들에 의해 만들어지기 때문에 상당한 버그를 포함하고 있고, 커널 크래시의 주범이 되고 있다.&lt;/p&gt;
&lt;h2 id=&quot;8-사례-연구-간단한-ide-디스크-드라이버&quot;&gt;8. 사례 연구: 간단한 IDE 디스크 드라이버&lt;/h2&gt;
&lt;p&gt;IDE 디스크는 시스템에 Control, Command block, Status, Error 4개의 레지스터로 이루어진 단순한 인터페이스를 제공한다.&lt;/p&gt;
&lt;p&gt;이 레지스터들은 x86의 &lt;code&gt;in&lt;/code&gt;, &lt;code&gt;out&lt;/code&gt; I/O 명령어를 사용하여 &lt;strong&gt;특정 I/O의 주소들&lt;/strong&gt;을 읽거나 씀으로써 접근 가능하다.
그림에 보이는 &lt;code&gt;0x3F6&lt;/code&gt;과 같은 주소를 읽는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 36 IO Devices-1696876731194.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1378&quot; height=&quot;900&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2036%20IO%20Devices-1696876731194.DuWB2LN9_1d6vms.webp&quot; &gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;장치가 준비될 때까지 대기 -&gt; 드라이브가 사용 중이지 않고 READY 상태가 될 때까지 Status 레지스터 &lt;code&gt;0x1F7&lt;/code&gt;을 읽는다.&lt;/li&gt;
&lt;li&gt;Command 레지스터에 인자 값 쓰기 -&gt; 섹터의 수와 접근해야 할 섹터들의 논리 블럭 주소 (LBA), 그리고 드라이브 번호를 Command 레지스터 &lt;code&gt;0x1F2&lt;/code&gt; ~ &lt;code&gt;0x1F6&lt;/code&gt;에 기록한다.&lt;/li&gt;
&lt;li&gt;I/O 시작 -&gt; Command 레지스터에 읽기, 쓰기를 전달한다. &lt;code&gt;READ&lt;/code&gt;-&lt;code&gt;WRITE&lt;/code&gt; 명령어를 Command 레지스터에 기록한다. &lt;code&gt;0x1F7&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;데이터 전송 (쓰기) -&gt; 드라이브의 상태가 READY이고 DRQ(Drive Request for Data)일 때까지 기다린다. 데이터 포트에 데이터를 기록한다.&lt;/li&gt;
&lt;li&gt;인터럽트 처리 -&gt; 간단하게는 각 섹터가 전송되었을 때마다 인터럽트를 처리하게 하고, 복잡하게는 일괄처리가 가능하도록 만들어서 모든 전송이 완료되었을 때 최종적으로 한 번만 인터럽트를 발생시키도록 한다.&lt;/li&gt;
&lt;li&gt;에러 처리 -&gt; 각 동작 이후에 Status 레지스터를 읽는다. 만약 ERROR 비트가 설정되어 있다면 Error 레지스터를 읽어서 상세 정보를 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 시작 요청 루틴은 이 함수를 사용하여 요청을 명령하기 전에 드라이브가 준비되었는지 확인한다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ide_wait_ready&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (((&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; r &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; inb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; IDE_BSY) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ( r &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; IDE_DRDY))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 드라이버가 바쁘지 않을 때까지 반복문 수행&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 요청을 디스크로 내려 보낸다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// x86의 in, out 명령어가 장치 레지스터를 읽거나 쓰는데 사용된다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ide_start_request&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buf &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;b) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	ide_wait_ready()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;3f6&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 인터럽트 발생&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 섹터 몇개?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sector &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; 0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;ff&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // LBA 기록&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; (b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sector &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 8&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; 0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;ff&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // LBA 기록&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; (b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sector &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 16&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; 0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;ff&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // LBA 기록&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f6&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; 0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;e0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ((b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ((b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0f&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flags &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; B_DIRTY) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; IDE_CMD_WRITE)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // WRITE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			outsl(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 512&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 데이터 전송&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			outb(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; IDE_CMD_READ)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // READ&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 대기 중인 다른 요청들이 있다면 요청을 큐에 삽입하거나 디스크에 직접 명령한다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 어느 경우건 요청이 처리 완료되기를 기다리며, 호출한 프로세스는 재운다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ide_rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buf &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;b) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	acquire(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ide_lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buf &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ide_queue; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pp; pp&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pp)−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;qnext)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 큐를 순회&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 요청을 맨 뒤에 추가&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (ide_queue &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 큐가 비었다면&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		ide_start_request(b)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 디스크에 request 보냄&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ((b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flags &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (B_VALID&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;B_DIRTY)) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; B_VALID)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sleep(b&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ide_lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 완료 대기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	release(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ide_lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 인터럽트가 발생했을 때 호출된다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 장치에서 데이터를 읽고, I/O가 종료되기를 기다리는 프로세스를 깨운다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 그리고 요청이 더 큐에 있다면 ide_start_request를 이용하여 다음 요청 처리를 시작한다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ide_intr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buf &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	acquire(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ide_lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flags &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; B_DIRTY) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ide_wait_ready()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		insl(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1f0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 512&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // READ인 경우 데이터 가져오기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flags &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; B_VALID;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flags &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; .B_DIRTY;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	wakeup(b)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 대기 중인 프로세스 깨우기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ((ide_queue &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;qnext) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 다음 요청이 존재하는 경우 요청 시작&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		ide_start_request(ide_queue)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	release(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ide_lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 4개의 기본 함수를 통하여 동작한다.&lt;/p&gt;
&lt;h2 id=&quot;9-요약&quot;&gt;9. 요약&lt;/h2&gt;
&lt;p&gt;두 가지 기술인 인터럽트와 DMA는 장치의 효율을 높이기 위해 도입되었으며 명시적 I/O 명령어와 메모리 맵 I/O를 사용하여 장치의 레지스터에 접근할 수 있다는 것을 알게 되었다.&lt;/p&gt;
&lt;p&gt;마지막으로 디바이스 드라이버의 개념을 소개하면서 하위 계층의 세부적인 내용을 운영체제가 캡슐화 할 수 있으며, 이를 활용하여 운영체제의 나머지를 장치 중립적으로 구현할 수 있다는 것을 알게 되었다.&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 32 Concurrency Bugs</title><link>https://ks1ksi.io/blog/ostep-32-concurrency-bugs/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-32-concurrency-bugs/</guid><description>OSTEP Concurrency Bugs 정리. deadlock과 non-deadlock bug의 유형, 발생 조건, 예방과 회피 방법을 설명한다.</description><pubDate>Mon, 25 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;병행성 버그는 몇 개의 전형적인 패턴을 가지고 있다. 어떤 경우를 피해야 올바른 병행 코드를 작성할 수 있는지 알아보자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-오류의-종류&quot;&gt;1. 오류의 종류&lt;/h2&gt;
&lt;p&gt;현대 응용 프로그램에는 어떤 병행성 오류가 있을까? 다음은 Lu의 연구 결과이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 32 Concurrency Bugs-1695629446329.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1094&quot; height=&quot;618&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2032%20Concurrency%20Bugs-1695629446329.BHvcAxZ3_ZQmDBI.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이런 종류의 오류 (비 교착 상태와 교착 상태) 들에 대해 좀 더 자세히 알아보자.&lt;/p&gt;
&lt;h2 id=&quot;2-비-교착-상태-오류&quot;&gt;2. 비 교착 상태 오류&lt;/h2&gt;
&lt;p&gt;Lu의 연구 결과에 따르면, 비 교착 상태 오류가 병행성 관련 오류의 과반수를 차지한다. 비 교착 상태 오류의 분류 중 대표적인 &lt;strong&gt;원자성 위반&lt;/strong&gt; 오류와 &lt;strong&gt;순서 위반&lt;/strong&gt; 오류를 살펴보자.&lt;/p&gt;
&lt;h3 id=&quot;원자성-위반-오류-atomicity-violation&quot;&gt;원자성 위반 오류 (atomicity violation)&lt;/h3&gt;
&lt;p&gt;첫 번째로 만나게 되는 문제는 원자성 위반 오류이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 1::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (thd−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	fputs(thd−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;proc_info&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; . . . )&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 2::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;thd−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 예제에서 &lt;code&gt;thd&lt;/code&gt; 자료 구조의 &lt;code&gt;proc_info&lt;/code&gt; 필드를 두 개의 다른 쓰레드가 접근한다. 첫 번째 쓰레드는 그 값이 &lt;code&gt;NULL&lt;/code&gt;인지 검사하고 값을 출력한다. 두 번째 쓰레드는 값을 &lt;code&gt;NULL&lt;/code&gt;으로 설정한다.&lt;/p&gt;
&lt;p&gt;첫 번째 쓰레드가 검사를 완료한 후, &lt;code&gt;fputs()&lt;/code&gt;를 호출하기 직전에 인터럽트로 인해 두 번째 쓰레드가 실행되어 값이 &lt;code&gt;NULL&lt;/code&gt;로 설정될 수 있다. 때문에 &lt;code&gt;fputs()&lt;/code&gt; 함수는 &lt;code&gt;NULL&lt;/code&gt; 포인터 역참조를 하게 되어 프로그램은 크래시될 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;다수의 메모리 참조 연산들 간에 있어 예상했던 직렬성(serializability)이 보장되지 않았다. 즉 코드의 일부에 원자성이 요구되었으나, 실행 시에 그 원자성이 위반되었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;현재 예제 코드는 &lt;code&gt;proc_info&lt;/code&gt; 필드의 &lt;code&gt;NULL&lt;/code&gt; 값 검사와 &lt;code&gt;fputs()&lt;/code&gt; 호출 시 &lt;code&gt;proc_info&lt;/code&gt;를 인자로 사용하는 동작이 원자적으로 실행되는 것 (atomicity assumption)을 가정했다. 이 가정이 깨지면, 코드는 의도한 대로 작동하지 않는다.&lt;/p&gt;
&lt;p&gt;코드를 어떻게 수정하면 작동할까? 락을 추가하여 어느 쓰레드든 &lt;code&gt;proc_info&lt;/code&gt; 필드 접근 시 &lt;code&gt;proc_info_lock&lt;/code&gt; 이라는 락 변수를 획득하도록 한다. 이 자료 구조를 사용하는 다른 모든 코드들도 락으로 보호해야 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; proc_info_lock &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_MUTEX_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 1::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info_lock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (thd−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	fputs(thd−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;proc_info&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; . . . )&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info_lock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 2::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info_lock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;thd−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;proc_info_lock);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;순서-위반-오류-order-violation&quot;&gt;순서 위반 오류 (order violation)&lt;/h3&gt;
&lt;p&gt;다음은 순서 위반 오류이다. 아래 예시 코드에서 어떤 부분에 오류가 있는지 한번 찾아보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 1::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mThread &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; PR_CreateThread(mMain&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; . . . )&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 2::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mMain&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ( . . . ) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mState &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mThread−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;State;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 코드에서 쓰레드 2의 코드는 &lt;code&gt;mThread&lt;/code&gt; 변수가 이미 초기화 + &lt;code&gt;NULL&lt;/code&gt;이 아님을 가정하고 있다. 하지만 만약 쓰레드 1이 먼저 실행되지 않았다면, 쓰레드 2는 &lt;code&gt;NULL&lt;/code&gt; 포인터를 사용하기 때문에 크래쉬될 것이다. 초기화되지 않아 &lt;code&gt;NULL&lt;/code&gt;이 아닌 임의의 메모리 주소를 접근하게 되면 더 이상한 일이 발상할 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;두 개의 (그룹의) 메모리 참조 간의 순서가 바뀌었다. 즉, A가 항상 B보다 먼저 실행되어야 하지만 실행 중에 그 순서가 지켜지지 않았다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이러한 오류를 수정하는 방법은 순서를 강제하는 것이다. 앞에서 논의했던, &lt;strong&gt;컨디션 변수&lt;/strong&gt;를 도입해서 순서를 강제해보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mtLock &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_MUTEX_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mtCond &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_COND_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mtInit &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 1::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mThread &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; PR_CreateThread(mMain&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; . . . )&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 쓰레드가 생성되었다는 것을 알리는 시그널 전달&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mtLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mtInit &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mtCond)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mtLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Thread 2::&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mMain&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ( . . . ) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 쓰레드가 초기화되기를 기다린다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mtLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (mtInit &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mtCond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mtLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mtLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mState &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mThread−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;State;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;mtLock&lt;/code&gt;라는 락, 그에 대한 컨디션 변수 &lt;code&gt;mtCond&lt;/code&gt;, 그리고 상태 변수 &lt;code&gt;mtInit&lt;/code&gt;을 추가했다. 초기화 코드가 실행되면 &lt;code&gt;mtInit&lt;/code&gt;의 상태를 1로 설정하고 초기화를 완료했다고 시그널을 발생시킨다. 만약 쓰레드 2가 이 시점 전에 실행된다면 상태가 변경되기를 대기한다. 이후에 다시 쓰레드 2가 실행되면 상태 값 초기화 여부를 검사한 후, (&lt;code&gt;mtInit&lt;/code&gt;이 1로 설정되었는지 검사한 후) 올바르게 계속 진행한다.&lt;/p&gt;
&lt;p&gt;이렇게 쓰레드 간의 순서가 문제가 되는 경우는 컨디션 변수 (또는 세마포어) 를 사용하여 해결할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;정리&quot;&gt;정리&lt;/h3&gt;
&lt;p&gt;비 교착 상태 오류의 대부분(97%)은 원자성 또는 순서 위반에 대한 것이었다. 이러한 오류 패턴들을 유의하면 관련 오류들을 좀 더 줄일 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;3-교착-상태-오류&quot;&gt;3. 교착 상태 오류&lt;/h2&gt;
&lt;p&gt;복잡한 락 프로토콜을 사용하는 다수의 병행 시스템에서 &lt;strong&gt;교착 상태(deadlock)&lt;/strong&gt; 라는 고전적 문제가 발생한다. 예를 들어 락 L1을 갖고 있는 쓰레드 2가 락 L1이 해제되기를 기다리고 있을 때 교착 상태가 발생한다. 교착 상태가 발생할 가능성이 있는 코드를 다음에 나타내었다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;Thread &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;:     Thread &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L1);     &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L2);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L2);     &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L1);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;쓰레드 1이 락 L1을 획득한 후에 문맥 교환이 발생하여 쓰레드 2가 실행되고, 이 때 쓰레드 2가 락 L2를 획득하고 락 L1을 획득하려고 시도하면 교착 상태가 발생한다.&lt;/p&gt;
&lt;p&gt;각 쓰레드가 상대방이 소유하고 있는 락을 대기하고 있기 때문에 누구도 실행할 수 없게 된다.
&lt;img alt=&quot;OSTEP 32 Concurrency Bugs-1695639772958.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;976&quot; height=&quot;954&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2032%20Concurrency%20Bugs-1695639772958.DNYkMvgW_1B1Q7b.webp&quot; &gt;&lt;/p&gt;
&lt;h3 id=&quot;교착-상태는-왜-발생하는가&quot;&gt;교착 상태는 왜 발생하는가&lt;/h3&gt;
&lt;p&gt;쓰레드 1과 2가 락을 같은 순서로 획득하도록 코드를 작성하면 교착 상태는 절대 발생하지 않는다. 이렇게 간단하게 해결할 수 있는데 교착 상태는 왜 발생할까?&lt;/p&gt;
&lt;p&gt;코드가 많아지면서 구성 요소 간에 복잡한 의존성이 발생하기 때문이다. 운영체제를 예로 들면, 가상 메모리 시스템이 디스크 블럭을 가져오기 위해 파일 시스템에 접근한다. 파일 시스템은 디스크 블럭을 메모리에 탑재하기 위해 메모리 페이지를 확보해야 하고, 이를 위해 가상 메모리 시스템에 접근한다.&lt;/p&gt;
&lt;p&gt;또 다른 이유는 &lt;strong&gt;캡슐화&lt;/strong&gt;이다. 소프트웨어 모듈화가 개발을 쉽게 하기 때문에 상세한 구현 내용은 감추도록 구현한다. 하지만 이런 모듈화 때문에 교착 상태가 일어날 수 있다.&lt;/p&gt;
&lt;p&gt;자바의 &lt;code&gt;Vector&lt;/code&gt; 클래스를 예로 들면,&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;Vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v2;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;addAll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(v2);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 메소드는 &lt;code&gt;v1&lt;/code&gt;에 대한 락 뿐만 아니라 &lt;code&gt;v2&lt;/code&gt;에 대한 락도 획득해야 한다. 하지만 어떤 쓰레드가 &lt;code&gt;v2.addAll(v1)&lt;/code&gt;을 호출하면 교착 상태가 일어날 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;교착-상태-발생-조건&quot;&gt;교착 상태 발생 조건&lt;/h3&gt;
&lt;p&gt;교착 상태가 발생하기 위해서는 네 가지 조건이 충족되어야 한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;상호 배제 (Mutual Exclusion)&lt;/strong&gt;: 쓰레드가 자신이 필요로 하는 자원에 대한 독자적인 제어권을 주장한다 (예, 쓰레드가 락을 획득함).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;점유 및 대기 (Hold-and-wait)&lt;/strong&gt;: 쓰레드가 자신에게 할당된 자원 (예 : 이미 획득한 락)을 점유한 채로 다른 자원 (예 : 획득하고자 하는 락)을 대기한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;비 선점 (No preemption)&lt;/strong&gt;: 자원 (락)을 점유하고 있는 쓰레드로부터 자원을 강제적 으로 빼앗을 수 없다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;순환 대기 (Circular wait)&lt;/strong&gt;: 각 쓰레드는 다음 쓰레드가 요청한 하나 또는 그 이상의 자원 (락)을 갖고 있는 쓰레드들의 순환 고리가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 네 조건 중 하나라도 만족시키지 않는다면, 교착 상태는 발생하지 않는다.&lt;/p&gt;
&lt;h3 id=&quot;교착-상태의-예방&quot;&gt;교착 상태의 예방&lt;/h3&gt;
&lt;h4 id=&quot;순환-대기&quot;&gt;순환 대기&lt;/h4&gt;
&lt;p&gt;가장 실용적인 방법이면서 자주 사용되는 방법은 순환 대가기 절대 발생하지 않도록 락 코드를 작성하는 것이다.&lt;/p&gt;
&lt;p&gt;락 획득을 하는 전체 순서 (total ordering) 을 정할 수 있다. L1과 L2라는 두개의 락만이 시스템에 존재하면, L1을 &lt;strong&gt;무조건&lt;/strong&gt; L2 전에 획득하도록 하면 교착 상태를 피할 수 있다.&lt;/p&gt;
&lt;p&gt;이 순서를 따르면 순환 대기는 발생하지 않고, 따라서 교착 상태도 발생하지 않는다.&lt;/p&gt;
&lt;p&gt;복잡한 시스템의 경우 락이 여러 개 존재할 것이고, 전체 락의 요청 순서를 정의하는 것이 어려울 수 있다. (불필요하기도 하다) 때문에 부분 순서 (partial ordering) 을 제공하는 것이 락 획득 구조를 만드는 데 유용하다.&lt;/p&gt;
&lt;p&gt;락의 순서를 정의하기 위해서는 코드와 다양한 루틴 간의 상호 호출 관계를 이해해야 한다. 조금만 실수해도 교착 상태가 발생하게 된다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;락 주소를 사용하여 락 요청 순서를 강제하는 방법도 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (m1 &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m2) {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 락을 주소의 내림차순으로 획득&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(m1)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(m2)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(m2)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(m1)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// m1 != m2를 가정&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;점유-및-대기&quot;&gt;점유 및 대기&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;원자적으로 모든 락을 한번에 획득하도록&lt;/strong&gt; 하면 이를 예방할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(prevention);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L2);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;. . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(prevention);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;제일 먼저 &lt;code&gt;prevention&lt;/code&gt; 락을 획득하여 락을 획득하는 과정 중에 쓰레드의 문맥 교환이 발생하는 것을 방지하고, 결과적으로 교착 상태의 발생 가능성을 차단한다. 다른 쓰레드가 L1과 L2를 다른 순서로 획득하려고 해도 상관 없다. &lt;code&gt;prevention&lt;/code&gt; 락을 이미 획득한 후에 나머지 락을 요청하기 때문이다.&lt;/p&gt;
&lt;p&gt;이 해법은 문제점이 많다. &lt;strong&gt;캡슐화&lt;/strong&gt;가 어렵다. 필요한 락을 정확히 파악해야 하고, 그 락들을 미리 획득해야 하기 때문이다. 락이 실제 필요할 때 요청하는 것이 아니라 미리 모든 락을 한번에 획득하기 때문에 병행성이 저하되는 문제도 있다.&lt;/p&gt;
&lt;h4 id=&quot;비선점&quot;&gt;비선점&lt;/h4&gt;
&lt;p&gt;일반적으로 락을 해제하기 전까지는 락을 보유하고 있는 것으로 보기 때문에 여러 락을 획득하는 것에는 문제의 소지가 많다. 왜냐하면 락을 이미 보유하고 있는 채로 다른 락을 대기하기 때문이다. 때문에 많은 쓰레드 라이브러리들은 이러한 상황을 피할 수 있도록 유연한 인터페이스 집합을 제공한다. &lt;code&gt;trylock()&lt;/code&gt; 루틴의 경우 획득 가능하다면 락을 획득하거나 현재 락이 점유된 상태이니 나중에 다시 시도라하라는 것을 알리는 &lt;code&gt;-1&lt;/code&gt;을 리턴한다.&lt;/p&gt;
&lt;p&gt;이 &lt;code&gt;trylock()&lt;/code&gt; 인터페이스를 이용하면 교착 상태 가능성이 없고 획득 순서에 영향을 받지 않는 락 획득 방법을 만들 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;top:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;trylock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(L2) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	unlock(L1)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	goto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; top;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다른 쓰레드가 같은 프로토콜을 사용하면서 락을 다른 순서로 획득하려고 해도 교착 상태는 발생하지 않는다. 하지만 &lt;strong&gt;무한반복(livelock)&lt;/strong&gt; 문제가 생긴다.&lt;/p&gt;
&lt;p&gt;두 쓰레드가 이 순서로 계속 시도하면서 락 획득에 실패하는 것도 가능하긴 하다. 확률은 낮지만. 반복문에 지연 시간을 무작위로 조절해서 경쟁하는 쓰레드 간의 반복 간섭 확률을 줄일 수 있다.&lt;/p&gt;
&lt;h4 id=&quot;상호-배제&quot;&gt;상호 배제&lt;/h4&gt;
&lt;p&gt;마지막 예방 기법은 상호 배제 자체를 없애는 방법이다. 일반적인 코드는 모두 임계 영역을 포함하고 있기 때문에 이는 어려운 일이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;wait free&lt;/strong&gt; 자료 구조를 만들어서 이를 해결했다. 명시적 락이 필요 없는 강력한 하드웨어 명령어를 사용하여 자료 구조를 만들면 되지 않을까?&lt;/p&gt;
&lt;p&gt;간단한 예제로 Compare-And-Swap이 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; CompareAndSwap&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;address&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; expected&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;address &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; expected) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;address &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 성공&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 실패&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;어떤 한 값을 원자적으로 임의의 크기만큼 증가시키는 경우를 구현해보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; AtomicIncrement&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; amount) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	do&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; old &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;CompareAndSwap(value&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; old&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; old &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; amount)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;락을 획득하여 값을 갱신한 후에 락을 해제하는 대신, Compare-And-Swap 명령어로 값에 새로운 값을 갱신하도록 반복적으로 시도한다. 이와 같은 방식을 사용하면 락을 획득할 필요가 없으며 교착 상태가 발생할 수도 없다. 물론 무한 반복은 발생할 여지가 있다.&lt;/p&gt;
&lt;p&gt;좀 더 복잡한 예제를 보자. 리스트 해드에 개체를 삽입하는 코드이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; insert&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	assert(n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	do&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;		n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;CompareAndSwap(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; n)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;next&lt;/code&gt; 포인터가 현재의 헤드를 가리키도록 갱신하고, 새로 생성된 노드는 리스트의 헤드가 되도록 동작한다. 이 코드를 처리하는 도중 다른 쓰레드가 새로운 헤드를 추가했다면, Compare-And-Swap은 실패하고 삽입 과정을 다시 시도한다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.baeldung.com/lock-free-programming&quot;&gt;참고&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;스케줄링으로-교착-상태-회피하기&quot;&gt;스케줄링으로 교착 상태 회피하기&lt;/h3&gt;
&lt;p&gt;예방보다 회피가 더 유용할 때가 있다. 교착 상태를 회피하기 위해서는 여러 쓰레드가 어떤 락을 획득하게 될 것인지에 대해 전반적으로 파악하고 있어야 하며, 그것을 바탕으로 쓰레드들을 스케줄링하여 교착 상태가 발생하지 않도록 그때그때 보장한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 32 Concurrency Bugs-1695644612328.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;744&quot; height=&quot;272&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2032%20Concurrency%20Bugs-1695644612328.C-vkzNiN_10dMTh.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;4개의 쓰레드가 프로세서 2개에서 실행되고, 락 2개가 존재한다고 가정하자. 똑똑한 스케줄러라면 T1과 T2가 동시에 실행되지 않도록 하여 교착 상태를 회피할 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 32 Concurrency Bugs-1695644689116.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;696&quot; height=&quot;284&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2032%20Concurrency%20Bugs-1695644689116.Bktu7bkx_ZezhfC.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;다른 예시도 한 번 살펴보자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 32 Concurrency Bugs-1695644714303.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;686&quot; height=&quot;288&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2032%20Concurrency%20Bugs-1695644714303.DNhu6V9w_qIzDl.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 경우는 T1, T2, T3이 동시에 실행되면 안 된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 32 Concurrency Bugs-1695644733954.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;858&quot; height=&quot;262&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2032%20Concurrency%20Bugs-1695644733954.DKPGj_sx_11Hevv.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;T1, T2, T3이 모두 한 프로세서에서 실행되도록 보수적인 방법을 택하기 때문에 전체 작업이 끝나기까지 오랜 시간이 걸린다. 때문에 스케줄링으로 교착 상태를 회피하는 것은 보편적으로 사용되는 방법은 아니다.&lt;/p&gt;
&lt;h3 id=&quot;발견-및-복구&quot;&gt;발견 및 복구&lt;/h3&gt;
&lt;p&gt;마지막 전략은 교착 상태 발생을 허용하고, 발견하면 복구하도록 하는 방법이다. 예를 들어 운영체제가 1년에 한 번 멈춘다고 했을 때 시원하게 재부팅을 하는 방법이 있다. 교착 상태가 아주 가끔 발생한다면 꽤 유용한 방법이다.&lt;/p&gt;
&lt;p&gt;많은 데이터베이스 시스템들이 교착 상태를 발견하고 회복하는 기술을 사용한다. 이는 주기적으로 실행되며 자원 할당 그래프를 그려서 사이클이 생겼는지를 검사한다. 사이클이 발생하는 경우, 시스템은 재부팅되어야 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;항상 완벽을 추구하지는 말자. 안 좋은 일이 아주 가끔 발생한다면, 그 일을 방지하기 위해서 아주 많은 시간을 들일 필요는 없다.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><category>os</category><category>cs</category></item><item><title>OSTEP 33 Event-based Concurrency</title><link>https://ks1ksi.io/blog/ostep-33-event-based-concurrency/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-33-event-based-concurrency/</guid><description>OSTEP Event-based Concurrency 정리. thread 대신 event loop와 non-blocking I/O로 동시성을 처리하는 방식과 한계를 요약한다.</description><pubDate>Mon, 25 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;node.js로 백엔드를 만들어 봤으면 node.js가 어떻게 작동하는지 알 수 있을 것이다. 이벤트 기반의 병행성은 서버 프레임워크에서 사용되지만, 그 시작점은 C와 유닉스 시스템이다.&lt;/p&gt;
&lt;p&gt;이벤트 기반의 병행성은 두 개의 문제점을 가지고 있다.&lt;/p&gt;
&lt;p&gt;우선 멀티 쓰레드 프로그램에서 이벤트 기반 병행성을 올바르게 사용하는 것이 매우 어렵다는 것이다. 락을 누락시키거나, 교착 상태 또는 다른 문제가 발생할 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;또, 멀티 쓰레드 프로그램에서는 개발자가 쓰레드 스케줄링에 대한 제어권을 전혀 가지고 있지 않다는 것이다. 개발자는 운영체제가 합리적으로 스케줄링해주기를 기대할 수밖에 없다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;어떻게 쓰레드 없이 병행 서버를 개발하고, 각종 문제들을 피할 수 있을까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-이벤트-루프&quot;&gt;1. 이벤트 루프&lt;/h2&gt;
&lt;p&gt;우리가 다룰 방법은 &lt;strong&gt;이벤트 기반의 병행성&lt;/strong&gt;이다. 접근 방법은 다음과 같다.&lt;/p&gt;
&lt;p&gt;특정 사건 (이벤트) 의 발생을 대기한다. 사건이 발생하면, 사건의 종류를 파악한 후, I/O를 요청하거나 추후 처리를 위하여 다른 이벤트를 발생시키거나 하는 등의 작업을 한다.&lt;/p&gt;
&lt;p&gt;자세한 설명 전에 고전적인 이벤트 기반의 서버가 어떻게 생겼는지 살펴보자. 이 응용 프로그램은 &lt;strong&gt;이벤트 루프 (event loop)&lt;/strong&gt; 라는 단순한 구조를 기반으로 짜여 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	events &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; getEvents()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (e in events) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		processEvent(e)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;매우 간단하다. 루프 내에서 사건 발생을 대기한다. 이벤트가 발생하면 하나씩 처리한다. 이 때 각 이벤트를 처리하는 코드를 &lt;strong&gt;이벤트 핸들러 (event handler)&lt;/strong&gt; 라고 부른다.&lt;/p&gt;
&lt;p&gt;중요한 것은 이벤트의 처리가 시스템의 유일한 작업이기 때문에, 다음에 처리할 이벤트를 결정하는 것이 &lt;strong&gt;스케줄링&lt;/strong&gt;과 동일한 효과를 갖는다. &lt;strong&gt;스케줄링을 제어할 수 있는 기능&lt;/strong&gt;이 이벤트 기반 방법의 큰 장점 중 하나이다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;strong&gt;발생한 이벤트가 무슨 이벤트인지&lt;/strong&gt; 어떻게 판단하지?&lt;/p&gt;
&lt;p&gt;네트워크나 디스크 I/O의 경우는 더 어렵다. 디스크 I/O가 완료되었다는 이벤트가 도착했을 때 어떤 디스크 요청이 완료된걸까? 도착한 메시지가 자신을 위한 것인지 어떻게 알 수 있을까?&lt;/p&gt;
&lt;h2 id=&quot;2-중요-api-select-또는-poll&quot;&gt;2. 중요 API: &lt;code&gt;select()&lt;/code&gt; (또는 &lt;code&gt;poll()&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;이벤트를 어떻게 받을까? 대부분의 시스템은 &lt;code&gt;select()&lt;/code&gt; 또는 &lt;code&gt;poll()&lt;/code&gt; 시스템 콜을 기본 API로서 제공한다. 인터페이스의 기능은 도착한 I/O들 중 주목할 만한 것이 있는지를 검사하는 것이다.&lt;/p&gt;
&lt;p&gt;예를 들어, 웹 서버같은 네트워크 응용 프로그램이 자신이 처리할 패킷의 도착 여부를 검사하는 것이다. 이 시스템 콜들이 정확히 해당 역할을 한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;select()&lt;/code&gt;를 예로 살펴보자. Mac OS X가 제공하는 메뉴얼은 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; nfds&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		   fd_set &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*restrict&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; readfds&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		   fd_set &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*restrict&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; writefds&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		   fd_set &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*restrict&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; errorfds&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		   struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; timeval &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*restrict&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; timeout);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;select()&lt;/code&gt;는 &lt;code&gt;readfds&lt;/code&gt;, &lt;code&gt;writefds&lt;/code&gt;, &lt;code&gt;errorfds&lt;/code&gt;를 통해 전달된 I/O 디스크립터 집합들을 검사해서 각 디스크립터들에 해당하는 입출력 디바이스가 읽을 준비가 되었는지, 쓸 준비가 되었는지, 처리해야 할 예외 조건이 발생했는지 등을 파악한다. 각 집합의 첫 번째 &lt;code&gt;nfds&lt;/code&gt;개의 디스크립터들을 검사한다. &lt;code&gt;select()&lt;/code&gt;는 집합을 가리키는 각 포인터들을 준비된 디스크립터들의 집합으로 교체한다. &lt;code&gt;select()&lt;/code&gt;는 전체 집합에서 준비된 디스크립터들의 총 개수를 반환한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;select()&lt;/code&gt;에 대해 알아두어야 할 사항이 두 가지 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;select()&lt;/code&gt;를 이요하면 디스크립터에 대한 읽기 가능 여부, 쓰기 가능 여부를 검사할 수 있다.
전자(읽기 가능 여부)는 처리해야 할 패킷의 도착 여부를 알 수 있도록 한다. 후자(쓰기 가능 여부)는 서비스가 응답 전송이 가능한 시점을 파악할 수 있도록 한다. (예를 들어, outbound queue가 가득 차지 않은 상태)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;timeout&lt;/code&gt; 존재
일반적으로는 &lt;code&gt;NULL&lt;/code&gt;로 설정하여 무한정 대기하지만 오류에 대비하도록 설계된 서버는 값을 설정하기도 한다. 널리 사용되는 방법으로는, &lt;code&gt;timeout = 0&lt;/code&gt;으로 설정하여 &lt;code&gt;select()&lt;/code&gt;가 대기하지 않고 즉시 리턴하도록 하는 것이다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;poll()&lt;/code&gt; 시스템 콜도 유사하게 작동한다.&lt;/p&gt;
&lt;p&gt;이런 기본 함수로 &lt;em&gt;&lt;strong&gt;non blocking event loop&lt;/strong&gt;&lt;/em&gt;를 만들어, 패킷 도착을 확인하고, 소켓에서 메시지를 읽고 필요에 응답할 수 있도록 해준다.&lt;/p&gt;
&lt;h2 id=&quot;3-select의-사용&quot;&gt;3. &lt;code&gt;select()&lt;/code&gt;의 사용&lt;/h2&gt;
&lt;p&gt;확실한 이해를 위해, 어떤 네트워크 디스크립터에 메시지가 도착했는지를 파악하는 경우를 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;stdlib.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;sys/time.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;sys/types.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;unistd.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 여러 개의 소켓을 열고 설정 (여기에는 안써있음)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 주 반복문&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;		// fd_set을 모두 0으로 초기화&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		fd_set readFDs;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		FD_ZERO(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;readFDs)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;		// 이제 이 서버가 관심을 가지는 디스크립터들의 bit 설정&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;		// (min ~ max)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fd;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (fd &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; minFD; fd &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; maxFD; fd&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			FD_SET(fd&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;readFDs)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;		// select&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; select(maxFD&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;readFDs&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;		// FD_ISSET()을 사용하여 실제 데이터 사용 여부 검사&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fd;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (fd &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; minFD; fd &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; maxFD; fd&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;FD_ISSET(fd&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;readFDs)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		processFD(fd)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;맨 처음 초기화 후, 서버는 무한 루프에 들어간다. 그 루프 내에서 &lt;code&gt;FD_ZERO()&lt;/code&gt; 매크로를 통해 파일 디스크립터들을 초기화한 후, &lt;code&gt;FD_SET()&lt;/code&gt;을 사용하여 &lt;code&gt;minFD&lt;/code&gt; ~ &lt;code&gt;maxFD&lt;/code&gt;까지의 파일 디스크립터 집합에 포함시킨다. 이 집합은 &lt;strong&gt;서버가 보고 있는 모든 네트워크 소켓&lt;/strong&gt;같은 것들을 나타낼 수 있다.&lt;/p&gt;
&lt;p&gt;마지막으로 서버는 &lt;code&gt;select()&lt;/code&gt;를 호출하여 데이터가 도착한 소켓이 있는지를 검사한다. 반복문 내의 &lt;code&gt;FD_ISSET()&lt;/code&gt;을 사용하여 이벤트 서버는 어떤 디스크립터들이 &lt;strong&gt;준비된&lt;/strong&gt; 데이터를 가지고 있는지를 알 수 있고, 도착하는 데이터를 처리할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;실제 서버는 디스크 작업, 메시지를 보내는 시점, 등 세부 사항들을 결정하는 로직이 필요하다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;팁: 이벤트 기반의 서버 내에서는 블럭을 하지 말자.
이벤트 기반 서버는 작업의 스케줄링을 정밀하게 제어할 수 있다. 하지만, 정밀한 제어를 위해서는 호출자가 실행한 것을 차단할 수 있는 어떠한 호출도 있어서는 안 된다. 이 디자인 팁을 지키지 않는다면 이벤트 기반 서버가 멈추게 될 것이고 사용자는 불만을 가질 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;4-왜-간단한가---락이-필요-없음&quot;&gt;4. 왜 간단한가? -&gt; 락이 필요 없음&lt;/h2&gt;
&lt;p&gt;단일 CPU를 사용하는 이벤트 기반의 응용 프로그램에서는, 병행 프로그램을 다룰 때 나타났던 문제들이 더 이상 보이지 않는다.&lt;/p&gt;
&lt;p&gt;그 이유는 &lt;strong&gt;매 순간에 단 하나의 이벤트만 다루기 때문&lt;/strong&gt;에 락을 획득하거나 해제할 필요가 없기 때문이다. 이벤트 기반의 서버는 단 하나의 쓰레드만 가지고 있기 때문에 다른 쓰레드에 의해 인터럽트에 걸릴 수가 없다. 그렇기 때문에 멀티쓰레드 프로그램의 병행성 버그는 기본적인 이벤트 기반 접근법에서는 나타나지 않는다.&lt;/p&gt;
&lt;h2 id=&quot;5-문제-블로킹-시스템-콜-blocking-system-call&quot;&gt;5. 문제: 블로킹 시스템 콜 (Blocking System Call)&lt;/h2&gt;
&lt;p&gt;블로킹을 유발하는 시스템 콜이 호출되는 이벤트가 발생하면 어떡하지?&lt;/p&gt;
&lt;p&gt;예를 들어, 디스크에서 데이터를 읽어서 그 내용을 사용자에게 전달하는 요청을 생각해 보자. 이 요청을 처리하려면 핸들러가 &lt;code&gt;open()&lt;/code&gt; 시스템 콜을 호출하여 파일을 열고, &lt;code&gt;read()&lt;/code&gt;로 파일을 읽어야 한다. 파일을 읽어서 메모리에 탑재한 후에 서버는 그 결과를 사용자에게 전달할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;open()&lt;/code&gt;, &lt;code&gt;read()&lt;/code&gt; 둘 다 저장 장치에 I/O 요청을 보내야 한다면, 이 요청을 처리하기 위해 오랜 시간ㄴ이 필요하다. 쓰레드 기반 서버는 이런 것이 문제가 되지 않는다. 한 쓰레드가 I/O 대기를 하는 동안, 다른 쓰레드가 실행이 되며 서버는 계속 동작할 수 있다. I/O 처리와 다른 연산이 자연스럽게 겹쳐지는 현상이 쓰레드 기반 프로그래밍의 장점이다.&lt;/p&gt;
&lt;p&gt;반면 이벤트 기반 접근법에서는 쓰레드가 없고 이벤트 루프만 존재한다. 즉, 이벤트 핸들러가 블로킹 시스템 콜을 호출하면 서버 전체가 오직 그 일을 처리하기 위해 명령어가 끝날 때까지 모든 것을 차단한다. &lt;strong&gt;이벤트 기반 시스템의 기본 원칙은 블로킹 호출을 허용하면 안 된다는 것이다.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;6-해법-비동기-io&quot;&gt;6. 해법: 비동기 I/O&lt;/h2&gt;
&lt;p&gt;여러 현대의 운영체제들이 I/O 요청을 디스크로 내려 보낼 수 있는, 일반적으로 &lt;strong&gt;비동기 I/O (asynchronous I/O)&lt;/strong&gt; 라고 부르는 새로운 방법을 개발하였다.&lt;/p&gt;
&lt;p&gt;이 인터페이스는 프로그램이 I/O 요청을 하면, I/O 요청이 끝나기 전에 제어권을 즉시 다시 호출자에게 돌려주는 것을 가능하게 했으며, 추가적으로 여러 종류의 I/O들이 완료되었는지 판단할 수 있도록 하였다.&lt;/p&gt;
&lt;p&gt;Mac OS X가 제공하는 인터페이스를 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; aiocb {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            aio_fildes;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; /* File descriptor */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	off_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;          aio_offset;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; /* File offset */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	volatile&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;aio_buf;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; /* Location of buffer */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	size_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;         aio_nbytes;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; /* Length of transfer */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 API는 &lt;code&gt;struct aiocb&lt;/code&gt;, &lt;strong&gt;AIO 제어 블럭(AIO Control block)&lt;/strong&gt; 이라고 불리는 구조를 사용하고 있다.&lt;/p&gt;
&lt;p&gt;파일에 대한 비동기 읽기 요청을 하려면, 응용 프로그램은 먼저 이 자료 구조에 읽고자 하는 파일 디스크립터 (&lt;code&gt;aio_fildes&lt;/code&gt;), 파일 내에서의 위치 (&lt;code&gt;aio_offset&lt;/code&gt;), 요청의 길이 (&lt;code&gt;aio_nbytes&lt;/code&gt;), 읽기 결과로 얻는 데이터를 저장할 메모리의 위치 (&lt;code&gt;aio_buf&lt;/code&gt;)와 같은 정보가 필요하다.&lt;/p&gt;
&lt;p&gt;Mac OS X에서는 간단한 &lt;strong&gt;비동기 읽기 (asynchronous read)&lt;/strong&gt; API를 사용한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; aio_read&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; aiocb &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;aiocbp);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 명령어를 통해 I/O 호출을 성공하면, &lt;strong&gt;즉시 리턴&lt;/strong&gt;을 하며 응용 프로그램 (이벤트 기반의 서버 등) 은 하던 일을 계속 진행할 수 있다.&lt;/p&gt;
&lt;p&gt;그러면 I/O가 종료되었다는 것을 어떻게 알 수 있을까?, 그리고 &lt;code&gt;aio_buf&lt;/code&gt;가 가리키는 버퍼에 요청했던 데이터가 있다는 것을 어떻게 알 수 있을까?&lt;/p&gt;
&lt;p&gt;API가 하나가 필요하다. Mac OS X 에서는 이 API를 &lt;code&gt;aio_error()&lt;/code&gt;라고 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; aio_error&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; aiocb &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;aiocbp);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 시스템 콜은 &lt;code&gt;aiocbp&lt;/code&gt;에 의해 참조된 요청이 완료되었는지를 검사한다. 완료되었다면 성공했다고 리턴을 하고 (0으로 표시) 실패했다면 &lt;code&gt;EINPROGRESS&lt;/code&gt;를 반환한다. 모든 대기 중인 비동기 I/O는 &lt;strong&gt;주기적으로 &lt;code&gt;aio_error()&lt;/code&gt; 시스템 콜로 시스템에 폴링(polling)하여 해당 I/O가 완료되었는지 확인할 수 있다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;어떤 I/O가 완료되었는지 확인하는 것이 귀찮을 수도 있다. 동시에 수백개의 I/O를 요청하는 프로그램의 경우, 이 모든 요청을 다 폴링하면서 검사해야 할까? 아니면 일정 시간 기다려야 할까?&lt;/p&gt;
&lt;p&gt;이 문제를 해결하기 위해 &lt;strong&gt;인터럽트&lt;/strong&gt; 기반의 접근법을 제공하는 시스템들이 있다. 유닉스의 &lt;strong&gt;시그널 (signal)&lt;/strong&gt; 을 사용하여 비동기 I/O가 완료되었다는 것을 응용 프로그램에게 알려주기 때문에 반복적으로 완료 여부를 확인할 필요가 없다. 폴링 대 인터럽트 문제는 I/O 장치들을 다룰 때에도 나타난다.&lt;/p&gt;
&lt;p&gt;비동기 I/O가 없는 시스템에서는 제대로 된 이벤트 기반 접근법을 구현할 수 없다. 대신 네트워크 패킷을 처리하기 위해 이벤트를 사용하고, 대기 중인 I/O들을 처리하기 위해 쓰레드 풀을 사용하는 등의 하이브리드 기법을 사용할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;7-또-다른-문제점-상태-관리&quot;&gt;7. 또 다른 문제점: 상태 관리&lt;/h2&gt;
&lt;p&gt;이벤트 기반 접근법의 또 다른 문제점은 &lt;strong&gt;전통적인 쓰레드 기반 코드보다 일반적으로 더 작성하기 복잡하다&lt;/strong&gt;는 것이다. 이벤트 핸들러가 비동기 I/O를 발생시킬 때, I/O 완료 시 사용할 프로그램 상태를 정리해 놓아야 한다. 이 작업은 쓰레드 기반 프로그램에서는 불필요하다. &lt;strong&gt;쓰레드 스택&lt;/strong&gt;에 그 정보들이 이미 들어 있기 때문이다. 이벤트 기반 접근법에서는 &lt;strong&gt;수동 스택 관리 (manual stack management)&lt;/strong&gt; 가 필요하다.&lt;/p&gt;
&lt;p&gt;쓰레드 기반 서버를 예로 들면, 이 서버는 파일 디스크립터 (&lt;code&gt;fd&lt;/code&gt;) 로 명시된 파일에서 데이터를 읽어들여, 해당 데이터들을 네트워크 소켓 디스크립터 (&lt;code&gt;sd&lt;/code&gt;)로 전송한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; read&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(fd&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; write&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(sd&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;멀티 쓰레드 프로그램에서는, &lt;code&gt;read()&lt;/code&gt;가 리턴되면 전송할 네트워크 소켓에 관한 정보가 같은 스택에 존재한다. 하지만 이벤트 기반의 시스템에서는 그렇지 않다.&lt;/p&gt;
&lt;p&gt;이벤트 기반의 시스템에서 같은 일을 하려면, 앞서 명시한 AIO 호출들을 사용하여 &lt;code&gt;read()&lt;/code&gt;를 비동기로 요청해야 한다. &lt;code&gt;aio_error()&lt;/code&gt;를 사용하여 주기적으로 읽기가 종료되었는지 확인한다고 가정해보자. 읽기가 종료되었다고 알려주면 이벤트 기반 서버는 다음으로 무슨 일을 해야 하는지 어떻게 알 수 있을까?&lt;/p&gt;
&lt;p&gt;그 해법은 &lt;strong&gt;continuation&lt;/strong&gt;을 사용하는 것이다.&lt;/p&gt;
&lt;p&gt;이벤트를 종료하는 데에 필요한 자료들을 한곳에 저장해 둔다. 이벤트가 발생하면 (디스크 I/O가 완료되면), 저장해 놓은 정보들을 활용하여 이벤트를 처리한다.&lt;/p&gt;
&lt;p&gt;앞서 사용한 예시의 해법은 &lt;strong&gt;소켓 디스크립터 (&lt;code&gt;sd&lt;/code&gt;)를 파일 디스크립터 (&lt;code&gt;fd&lt;/code&gt;)가 사용하는 자료 구조 (예: 해시 테이블)에 저장&lt;/strong&gt;해 놓는 것이다. 디스크 I/O가 완료되면 &lt;strong&gt;이벤트 핸들러가 파일 디스크립터에서 다음 할 일을 파악&lt;/strong&gt;하여 &lt;strong&gt;호출자에게 소켓 디스크립터의 값을 반환&lt;/strong&gt;하도록 한다. 이 시점에서 &lt;strong&gt;서버는 소켓에 데이터를 기록하는 마지막 동작을 할 수 있게 된다.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;8-이벤트-사용의-어려움&quot;&gt;8. 이벤트 사용의 어려움&lt;/h2&gt;
&lt;p&gt;이벤트 기반 접근법에서는 다른 어려운 점이 몇 가지 존재한다.&lt;/p&gt;
&lt;p&gt;단일 CPU에서 멀티 CPU로 변경되면, 이벤트 기반 접근법의 단순함이 없어진다. &lt;strong&gt;하나 이상의 CPU를 활용하기 위해서는, 다수의 이벤트 핸들러를 병렬적으로 실행해야 한다.&lt;/strong&gt; 그렇게 되면 동기화 문제 (임계 영역 등) 이 발생하게 되며, 이것을 해결하는데 필요한 락 등을 사용할 수밖에 없다. 때문에 최근의 멀티코어 시스템은 락이 없는 이벤트 처리 방식을 더 이상 사용할 수 없게 된다.&lt;/p&gt;
&lt;p&gt;또 다른 문제는, &lt;strong&gt;페이징 (paging)&lt;/strong&gt; 과 같은 특정 종류의 시스템과 잘 맞지 않는다. 이벤트 핸들러에서 페이지 폴트가 발생하면 동작이 중단되기 때문에 &lt;strong&gt;서버는 페이지 폴트가 처리 완료되기 전까지는 진행을 할 수 없다.&lt;/strong&gt; 서버가 논블로킹 방식으로 설계되었다 해도, 페이지 폴트로 인한 블로킹은 피하기 어렵다. 이런 상황이 자주 발생하면 심각한 성능 저하가 일어날 것이다.&lt;/p&gt;
&lt;p&gt;세 번째 문제는 루틴의 작동 방식이 계속 변한다는 것이다. 루틴 동작이 논블로킹 방식에서 블로킹 방식으로 변경된다면, 그 루틴을 호출하는 이벤트 핸들러도 새로운 방식과 맞도록 변경해야 한다. 이에 적합하게 루틴을 두 버전으로 나누어야 한다. 이벤트 기반 서버에서 블로킹은 치명적이다. &lt;strong&gt;개발자는 각 이벤트가 사용하는 API 명세가 바뀌는지 주의 깊게 살펴야 한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;마지막으로, 비동기 디스크 I/O가 대부분의 플랫폼에서 사용되기까지는 매우 오래 걸렸으며, 아직까지도 비동기 네트워크 I/O는 일관성 있게 적용되어 있지 않다. 예를 들면, 모든 입출력 처리에 &lt;code&gt;select()&lt;/code&gt;를 사용하는 것이 이상적이지만, 일반적으로 네트워크 요청의 처리에는 &lt;code&gt;select()&lt;/code&gt;, 디스크 I/O에는 AIO가 사용되고 있다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.org/en/docs/guides/dont-block-the-event-loop&quot;&gt;node.js - dont block event loop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://black7375.tistory.com/90&quot;&gt;동시성, 병렬, 비동기, 논블럭킹과 컨셉들&lt;/a&gt;&lt;/p&gt;</content:encoded><category>os</category><category>cs</category></item><item><title>2023 SKKU AI 교육 해커톤 후기</title><link>https://ks1ksi.io/blog/2023-skku-ai-%EA%B5%90%EC%9C%A1-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9B%84%EA%B8%B0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2023-skku-ai-%EA%B5%90%EC%9C%A1-%ED%95%B4%EC%BB%A4%ED%86%A4-%ED%9B%84%EA%B8%B0/</guid><description>2023 SKKU AI 교육 해커톤 후기. 팀 구성, 프로젝트 진행, 결과와 해커톤에서 느낀 점을 짧게 정리한 글.</description><pubDate>Sun, 24 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;포스터&quot;&gt;포스터&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;2023 SKKU AI 교육 해커톤 후기-1695546579346.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1701&quot; height=&quot;2343&quot; src=&quot;https://ks1ksi.io/_astro/2023%20SKKU%20AI%20%EA%B5%90%EC%9C%A1%20%ED%95%B4%EC%BB%A4%ED%86%A4%20%ED%9B%84%EA%B8%B0-1695546579346.BkvXR074_Z1on8S5.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;군대에 박혀있는동안 1회, 2회 하는거 보고 해보고싶었는데 민간인이 되어서 참가해 보았다.&lt;/p&gt;
&lt;h2 id=&quot;주제&quot;&gt;주제&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;2023 SKKU AI 교육 해커톤 후기-1695546648309.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;874&quot; height=&quot;576&quot; src=&quot;https://ks1ksi.io/_astro/2023%20SKKU%20AI%20%EA%B5%90%EC%9C%A1%20%ED%95%B4%EC%BB%A4%ED%86%A4%20%ED%9B%84%EA%B8%B0-1695546648309.D4W8cSq7_lFRDE.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;나는 당연히 1번 골랐다. 유료 서비스? 사업화? 못참지.
저녁 도시락 먹으면서 뭐할지 고민했는데 교수님 아캠 강의 받아서 퀴즈 만들고, 바로바로 풀 수 있도록 실시간으로 띄워주는 서비스 만들기로 했다. OpenAI는 신이다.&lt;/p&gt;
&lt;h2 id=&quot;개발-내용&quot;&gt;개발 내용&lt;/h2&gt;
&lt;p&gt;교수님 수업하시는 내용은 Whisper로 따고, 변환한 텍스트 + 예쁘게 만들어둔 프롬프트로 GPT-4와 함께 퀴즈를 만들었다. 와! 진짜 별거 없긴 한데 굉장히 있어보이게 발표함. 결과물은 이런 느낌으로 나왔다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 SKKU AI 교육 해커톤 후기-1695546943246.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2662&quot; height=&quot;1334&quot; src=&quot;https://ks1ksi.io/_astro/2023%20SKKU%20AI%20%EA%B5%90%EC%9C%A1%20%ED%95%B4%EC%BB%A4%ED%86%A4%20%ED%9B%84%EA%B8%B0-1695546943246.RSJeVYz-_ZvcsvH.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2023 SKKU AI 교육 해커톤 후기-1695546954555.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2654&quot; height=&quot;1334&quot; src=&quot;https://ks1ksi.io/_astro/2023%20SKKU%20AI%20%EA%B5%90%EC%9C%A1%20%ED%95%B4%EC%BB%A4%ED%86%A4%20%ED%9B%84%EA%B8%B0-1695546954555.CfkibGt4_ZprEUi.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;모델이 z랑 g를 구분을 못한다. 둘다 한글로 ‘지’ 라고 써있어서 그런듯.&lt;/p&gt;
&lt;p&gt;만들고 발표는 대충 하려고 했는데 야무지게 시장조사 + BM + 추가 개발 분량까지 써서 발표했다.
교수님들이 좋아하시길래 그래도 세손가락 안에 들지 않을까? 했는데&lt;/p&gt;
&lt;h2 id=&quot;결과&quot;&gt;결과&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;2023 SKKU AI 교육 해커톤 후기-1695547167527.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1792&quot; height=&quot;1344&quot; src=&quot;https://ks1ksi.io/_astro/2023%20SKKU%20AI%20%EA%B5%90%EC%9C%A1%20%ED%95%B4%EC%BB%A4%ED%86%A4%20%ED%9B%84%EA%B8%B0-1695547167527.DXMLF92K_2g0FtD.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;1등했다~~
상금 300에서 200으로 줄었던데 상당히 아쉬운 부분이다.
내년에도 참가해서 1등 타먹고 졸업하고 싶다. 맛있겠다 ~&lt;/p&gt;
&lt;p&gt;그리고 야식으로 황올, 푸라닭, 피자 줬는데 너무 맛있었다. 레드불도 4캔은 마시고, 6캔은 집에 가져갔다. 이 귀한걸 왜 다들 남길까? 이해할 수 없다.&lt;/p&gt;</content:encoded><category>dev</category><category>skku</category></item><item><title>OSTEP 30 Condition Variables</title><link>https://ks1ksi.io/blog/ostep-30-condition-variables/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-30-condition-variables/</guid><description>OSTEP Condition Variables 정리. 조건이 만족될 때까지 스레드를 재우고 깨우는 wait, signal, producer-consumer 패턴을 설명한다.</description><pubDate>Mon, 18 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;우리가 배운 ‘락’ 하나만 가지고는 제대로 병행 프로그램을 작성할 수 없다. 쓰레드가 계속 진행하기 전에 &lt;strong&gt;특정 조건&lt;/strong&gt;이 만족되었는지 검사가 필요한 경우가 있다. 예를 들면 자식 쓰레드가 작업을 끝냈는지 여부를 알 필요가 있다. 이런 걸 어떻게 구현할 수 있을까?&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;volatile&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;child&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“child\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“parent: begin\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; child&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // spin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“parent: end\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 공유 변수로 구현할 수 있다 하지만 부모 쓰레드가 &lt;code&gt;spin&lt;/code&gt; 하면서 자원을 낭비하고 있다. 이 방법 대신 부모 쓰레드가 특정 조건이 만족될때까지 &lt;strong&gt;잠자면서 기다리는 것&lt;/strong&gt;이 더 좋다.&lt;/p&gt;
&lt;h2 id=&quot;1-정의와-루틴들&quot;&gt;1. 정의와 루틴들&lt;/h2&gt;
&lt;p&gt;조건이 참이 될 때까지 기다리기 위해 &lt;strong&gt;컨디션 변수&lt;/strong&gt;를 활용할 수 있다. 컨디션 변수는 일종으 &lt;strong&gt;큐&lt;/strong&gt; 자료 구조로서, 어떤 실행의 상태 (또는 어떤 조건) 가 원하는 것과 다를 때 참이 되기를 기다리며 &lt;strong&gt;스레드가 대기&lt;/strong&gt;할 수 있는 큐이다. 다른 쓰레드가 상태를 변경시켰을 때, 대기 중이던 쓰레드를 깨우고, 계속 진행할 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pthread_cond_t c;&lt;/code&gt; 라고 써서 &lt;code&gt;c&lt;/code&gt;가 컨디션 변수가 되도록 선언하고 초기화한다. 컨디션 변수에는 &lt;code&gt;wait()&lt;/code&gt; 과 &lt;code&gt;signal()&lt;/code&gt; 이라는 두 가지 연산이 존재한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wait()&lt;/code&gt; 은 &lt;strong&gt;쓰레드가 스스로를 잠재우기 위해 호출&lt;/strong&gt;하는 것이고, &lt;code&gt;signal()&lt;/code&gt;은 쓰레드가 무엇인가를 변경했기 때문에 &lt;strong&gt;조건이 참이 되기를 기다리며 잠자고 있던 쓰레드를 깨울 때 호출&lt;/strong&gt;한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_cond_wait&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;m);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_cond_signal&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;wait()&lt;/code&gt;에서 유의할 점은 &lt;code&gt;mutex&lt;/code&gt;를 매개변수로 사용한다는 것이다. 호출될 때 &lt;code&gt;mutex&lt;/code&gt;는 잠겨있었다고 가정하자. &lt;code&gt;wait()&lt;/code&gt;의 역할은 &lt;strong&gt;락을 해제하고 호출한 쓰레드를 재우는 것&lt;/strong&gt;이다. &lt;strong&gt;어떤 다른 쓰레드가 시그널을 보내서 쓰레드가 깨어나면, &lt;code&gt;wait()&lt;/code&gt;에서 리턴하기 전에 락을 재획득해야 한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;즉, 조건이 만족되어 잠에서 깨어났더라고 락을 획득하지 못하면 다시 잠에 드는 것이다. 이렇게 복잡한 이유는 쓰레드가 스스로를 재우려고 할 때, 경쟁 조건의 발생을 방지하기 위해서이다.&lt;/p&gt;
&lt;p&gt;이해를 돕기 위해 예제를 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_MUTEX_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_COND_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; thr_exit&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;child&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“child\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	thr_exit()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; thr_join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“parent: begin\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; child&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	thr_join()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“parent: end\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;부모 쓰레드가 조건을 검사할 때 &lt;code&gt;if&lt;/code&gt;문이 아니라 &lt;code&gt;while&lt;/code&gt;문을 사용한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;첫-번째-케이스&quot;&gt;첫 번째 케이스&lt;/h3&gt;
&lt;p&gt;부모 쓰레드가 자식 쓰레드를 생성하고, 계속 실행하며 &lt;code&gt;thr_join()&lt;/code&gt;을 호출하고, 자식 쓰레드가 끝나기를 기다리는 경우이다. 이 경우 부모 쓰레드가 락을 획득하고 자식이 끝났는지 검사한 후에 자식이 끝나지 않았으므로 &lt;code&gt;wait()&lt;/code&gt;을 호출하여 스스로를 잠재우고, 락을 해제한다. 자식 쓰레드가 추후 실행되어 &lt;code&gt;thr_exit()&lt;/code&gt;을 호출하여 부모 쓰레드를 깨운다. 호출했던 &lt;code&gt;wait()&lt;/code&gt;에서 락을 획득한 채로 리턴하여 부모 쓰레드가 실행되고, 락을 해제한 후 종료된다.&lt;/p&gt;
&lt;h3 id=&quot;두-번째-케이스&quot;&gt;두 번째 케이스&lt;/h3&gt;
&lt;p&gt;자식 쓰레드가 생성되면서 즉시 실행되고, &lt;code&gt;done&lt;/code&gt; 을 1로 설정하고, 자고 있는 쓰레드를 깨우기 위해 시그널을 보낸다. 하지만 자고 있는 쓰레드가 없기 때문에 그냥 리턴한다.
그 후 부모 쓰레드가 실행되고 &lt;code&gt;thr_join()&lt;/code&gt;을 호출하고 &lt;code&gt;done&lt;/code&gt;이 1이므로 바로 리턴한다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;code&gt;thr_exit()&lt;/code&gt;, &lt;code&gt;thr_join()&lt;/code&gt;의 중요성을 이해할 수 있도록 몇 가지 구현의 방식을 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; thr_exit&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; thr_join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이런 식으로 작성된 경우는 두 번째 케이스, 자식 쓰레드가 생성된 즉시 실행되어 &lt;code&gt;thr_exit()&lt;/code&gt;을 호출하는 경우에 제대로 작동하지 않는다. 자식 프로세스가 시그널을 보내지만, 깨울 쓰레드가 없어 리턴된다. 부모 쓰레드는 &lt;code&gt;wait()&lt;/code&gt;을 호출하고 거기서 멈춰있게 된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; thr_exit&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; thr_join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (done &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이런 식으로 작성된 경우, 경쟁 조건이 발생한다. 부모 쓰레드가 &lt;code&gt;thr_join()&lt;/code&gt;을 호출하고 나서 &lt;code&gt;done&lt;/code&gt;이 0인 것을 확인하고 &lt;code&gt;wait()&lt;/code&gt;을 호출하기 직전에 인터럽트에 걸려 자식 쓰레드가 실행되었다고 해보자. 자식 쓰레드는 &lt;code&gt;done&lt;/code&gt;을 1로 변경하고 시그널을 보내지만 대기 중인 쓰레드가 없다. 다시 부모 쓰레드가 실행되면, &lt;code&gt;wait()&lt;/code&gt;을 호출하고 잠에 들지만 아무도 깨워 줄 수 없다.&lt;/p&gt;
&lt;p&gt;두 가지 간단한 예제를 통해 컨디션 변수를 제대로 활용하기 위한 기본 요건을 알 수 있었다. 이번에는 좀 더 복잡한 예제를 다루어보자.&lt;/p&gt;
&lt;h2 id=&quot;2-생산자--소비자-유한-버퍼-문제&quot;&gt;2. 생산자 / 소비자 (유한 버퍼) 문제&lt;/h2&gt;
&lt;p&gt;다음으로 살펴볼 동기화 문제는 Dijkstra가 처음 제시한 생산자/소비자(producer/consumer) 문제이다. 유한 버퍼(bounded 버퍼) 문제로도 알려져 있다. &lt;code&gt;lock&lt;/code&gt; 대신 일반화된 세마포어를 발명하게 된 이유가 이 문제 때문이다.&lt;/p&gt;
&lt;p&gt;여러 개의 생산자 쓰레드와 소비자 쓰레드가 있다고 하자. 생산자는 데이터를 만들어 버퍼에 넣고, 소비자는 버퍼에서 데이터를 꺼내어 사용한다. 이러한 관계는 실제로 시스템에서 자주 일어난다. 예를 들어 멀티 쓰레드 웹 서버의 경우 생산자는 HTTP 요청을 작업 큐 (유한 버퍼) 에 넣고, 소비자 쓰레드는 이 큐에서 요청을 꺼내어 처리한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grep foo file.txt | wc -l&lt;/code&gt;와 같은 문장처럼 파이프 명령으로 한 프로그램의 결과를 다른 프로그램에게 전달할 때도  유한 버퍼를 사용한다. UNIX 쉘은 출력 결과를 &lt;strong&gt;UNIX 파이프&lt;/strong&gt; 라는 곳으로 전송한다. 파이프의 한쪽 끝에는 &lt;code&gt;wc&lt;/code&gt; 프로세스의 표준 입력과 연결되어 있다. &lt;code&gt;grep&lt;/code&gt; 프로세스가 생산자가 되고 &lt;code&gt;wc&lt;/code&gt; 프로세스가 소비자가 된다.&lt;/p&gt;
&lt;p&gt;유한 버퍼는 공유 자원이고, 경쟁 조건의 발생을 방지하기 위해 동기화가 필요하다. 한 개의 정수를 사용하고, 공유 버퍼에 값을 넣는 함수, 값을 꺼내는 함수 두 개가 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	assert(count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	buffer &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	assert(count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cond;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mutex;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;producer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		put(i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;consumer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		printf(“&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;d\n ”&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;컨디션 변수 하나와 그것과 연결된 &lt;code&gt;mutex&lt;/code&gt; 락을 사용하는 방식을 먼저 시도해보자.&lt;/p&gt;
&lt;p&gt;생산자는 버퍼가 빌 때까지 기다린다. 소비자도 버퍼가 차기를 기다린다. 생산자와 소비자가 각 하나씩인 경우에 위의 코드는 정상적으로 동작한다. 하지만 생산자, 소비자가 두 개 이상씩 존재하는 경우에는 문제가 있다.&lt;/p&gt;
&lt;h3 id=&quot;첫-번째-문제&quot;&gt;첫 번째 문제&lt;/h3&gt;
&lt;p&gt;대기 명령 전의 &lt;code&gt;if&lt;/code&gt; 문과 관련이 있다.&lt;/p&gt;
&lt;p&gt;Tc1 과 Tc2 라는 두 개의 소비자가 있고 Tp 라는 생산자가 하나 있다고 가정하자. 소비자 (Tc1)가 먼저 실행된다. 락 (c1) 을 획득하고 버퍼를 소비할 수 있는지 검사한다 (c2). 그리고 비어있음을 확인한 후에 대기하며 (c3) 락을 해제한다. 그리고 생산자 (Tp)가 실행된다. 락을 획득하고 (p1) 버퍼가 비었는지 확인한다 (p2). 비었음을 발견하고, 버퍼를 채운다 (p4). 생산자는 버퍼가 가득 찼다는 시그널을 보낸다 (p5). 대기 중인 첫째 소비자 (Tc1)는 깨어나 준비 큐 (ready queue)로 이동한다. Tc1 은 이제 실행할 수 있는 상태이지만 아직 실행 상태는 아니다. 생산자는 실행을 계속한다. 버퍼가 차 있으므로 대기 상태로 전이한다 (p6, p1-p3).&lt;/p&gt;
&lt;p&gt;여기에서 문제가 발생한다. 다른 소비자 (Tc2)가 끼어들어서 실행하면서 버퍼 값을 소비한다 (c1, c2, c4, c5, c6을 수행, c3은 버퍼가 가득 찼기 때문에 건너뜀). Tc1 이 실행된다고 해보자. 대기에서 리턴하기 전에 락을 획득한다. 그리고 get()을 호출하지만 (c4) 버퍼는 비었다! 코드는 의도한 대로 기능하지 못했다. 생산자가 버퍼에 넣어 둔 값을 Tc2 가 끼어들어서 소비하였기 때문에 Tc1 이 비어 있는 버퍼를 읽는 행위를 막았어야 했다.&lt;/p&gt;
&lt;p&gt;문제의 원인은 &lt;strong&gt;Tc1이 깨어나서 실행되기까지의 사이에 유한 버퍼의 상태가 변경되었기 때문&lt;/strong&gt;이다.
시그널은 쓰레드를 깨우기만 하고, 깨어난 쓰레드가 실제 싱행되는 시점에 그 상태가 유지된다는 보장은 없다. 이런 식으로 시그널을 정의하는 것을 Mesa Semantic이라 한다. 대비되는 개념은 Hoare Semantic인데 구현하기는 더 어렵지만 깨어난 즉시 쓰레드가 실행되는 것을 보장한다.&lt;/p&gt;
&lt;h3 id=&quot;해결-방법-if---while&quot;&gt;해결 방법: &lt;code&gt;if&lt;/code&gt; -&gt; &lt;code&gt;while&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;if&lt;/code&gt; 문을 &lt;code&gt;while&lt;/code&gt; 문으로 변경하면 이 문제를 해결할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cond;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mutex;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;producer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		put(i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;consumer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		printf(“&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;d\n ”&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;소비자 Tc1 이 깨어나서 (락을 획득한 상태), 즉시 공유 변수의 상태를 재확인한다 (c2). 만약 이 시점에 버퍼가 비어 있다면, 소비자는 대기 상태로 돌아간다 (c3). 문제가 해결되었다.
Mesa semantic의 컨디션 변수에서 가장 기본적인 법칙은 언제나 while 문을 사용하라는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;두-번째-문제&quot;&gt;두 번째 문제&lt;/h3&gt;
&lt;p&gt;이 문제는 소비자 쓰레드 Tc1 과 Tc2 가 먼저 실행한 후에 둘 다 대기 상태에 있을 때 발생한다 (c3).&lt;/p&gt;
&lt;p&gt;생산자가 실행되어 버퍼에 값을 넣고 대기 중인 쓰레드 하나를 깨우고 (Tc1 을 깨웠다고 하자), 자신은 대기한다. 이제 하나의 소비자 (Tc1)가 실행할 준비가 되었고 조건에 의해 Tc2 와 Tp 는 대기 중이다. 이제 문제가 발생하도록 만들 것이다.&lt;/p&gt;
&lt;p&gt;소비자 Tc1이 wait()에서 리턴을 받아 깨어나고 (c3) 조건을 재확인한다 (c2). 버퍼가 차있다는 것을 발견하고 값을 소비한다 (c4). 이 소비자는 시그널을 전송하여 (c5) 대기중인 쓰레드 중 하나를 깨운다. 이때 &lt;strong&gt;어떤 쓰레드를 깨울 것인가?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;소비자가 버퍼를 비웠기 때문에 생산자를 당연히 깨워야 한다. 하지만, 만약 소비자 Tc2 를 깨운다면 (대기 큐가 어떻게 관리되느냐에 따라 당연히 발생할 수 있다), 문제가 발생한다. 소비자 Tc2 가 깨어나면 버퍼가 비어 있다는 것을 발견한 후에 (c2) 다시 대기 상태로 들어간다 (c3). 버퍼에 값을 넣어야 하는 생산자 Tp 는 대기 중이다. 다른 소비자 쓰레드 Tc1 역시 대기 상태에 들어간다. &lt;strong&gt;세 개의 쓰레드가 모두 대기 상태다.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;시그널을 보내는 것은 꼭 필요하지만 대상이 명확해야 한다. 소비자는 다른 소비자를 깨울 수 없고 생산자만 깨워야 하며, 반대로 생산자의 경우도 마찬가지다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;단일-버퍼-생산자소비자-해법&quot;&gt;단일 버퍼 생산자/소비자 해법&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;두 개의 컨디션 변수를 사용&lt;/strong&gt;하여 시스템의 상태가 변경되었을 때 깨워야 하는 쓰레드에게만 시그널을 제대로 전달한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fill;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mutex;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;producer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		put(i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;fill)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;consumer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;fill&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		printf(“&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;d\n ”&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;최종적인-생산자소비자-해법&quot;&gt;최종적인 생산자/소비자 해법&lt;/h3&gt;
&lt;p&gt;마지막 변경을 통해 병행성을 증가시키고 효율적으로 만들어 보자. 버퍼 공간을 추가하여 대기 상태에 들어가기 전에 여러 값들이 생산될 수 있도록 하는 것, 그리고 마찬가지로 여러 개의 값이 대기 상태 전에 생산될 수 있도록 하는 것이다.&lt;/p&gt;
&lt;p&gt;우선 다음과 같이 버퍼 구조와 &lt;code&gt;put()&lt;/code&gt;, &lt;code&gt;get()&lt;/code&gt; 함수를 변경하였다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer[MAX];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fill &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; use &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	buffer[fill] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	fill &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (fill &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; MAX;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	count&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer[use];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	use &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (use &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; MAX;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	count−−;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;생산자와 소비자의 대기 상태 로직도 변경하였다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fill;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mutex;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;producer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; MAX)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		put(i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;fill)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;consumer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (count &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;fill&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		printf(“&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;d\n ”&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;생산자는 모든 버퍼가 현재 가득 차 있다면 대기 상태에 들어가고, 소비자도 모든 버퍼가 비어 있다면 대기에 들어간다.&lt;/p&gt;
&lt;h2 id=&quot;3-컨디션-변수-사용-시-주의점&quot;&gt;3. 컨디션 변수 사용 시 주의점&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;팁 : 조건에 while 문을 사용하자 (if 문은 아니다)
멀티 쓰레드 프로그램에서 조건을 검사할 때에는 항상 while 문을 사용하는 것이 옳다. 시그널 전달의 의미에 따라 if 문을 사용하는 것은 맞을 수도 있을 뿐이다. 그러 므로 항상 while 문을 사용하자, 그러면 작성한 코드가 의도한 대로 동작할 것이다. 조건 검사에 while 문을 사용하는 것은 거짓으로 깨운 경우 (spurious wakeup) 에 대처할 수 있도록 해 준다. 어떤 쓰레드 패키지는 구현상의 문제로 하나의 시그널에 의해서 두 개의 쓰레드가 깨어나는 경우도 가능하다. 쓰레드가 조건을 재검사해야 하는 이유는 거짓으로 깨운 경우가 있기 때문이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 몇 byte나 힙이 비었는가?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; bytesLeft &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; MAX_HEAP_SIZE;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;allocate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (bytesLeft &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; . . . ;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 힙에서 메모리를 할당 받음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	bytesLeft −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ptr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	bytesLeft &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 시그널 전달 대상은?..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;멀티 쓰레드 기반 미모리 할당 라이브러리 예제이다. 메모리 할당 코드를 호출하면, 공간이 생길 때까지 기다려야 할 수 있다. 또 쓰레드가 메모리 반납시 사용 가능한 메모리 공간의 발생을 알리는 시그널을 생성할 수 있다. 하지만 이 코드에는 문제가 있다 어떤 쓰레드가 깨어나야 할까?&lt;/p&gt;
&lt;p&gt;쓰레드 Ta는 100을 할당받길 원하고, 쓰레드 Tb는 10을 할당받길 원하는 상태에서, 어떤 쓰레드가 50만큼 메모리를 반환한 경우, Ta가 깨어나면 안 되고 Tb가 깨어나야 한다. 이런 문제는 두 개의 컨디션 변수를 사용해도 해결할 수 없다.&lt;/p&gt;
&lt;p&gt;Lampson과 Redell이 제시한 해법은 단순하다. &lt;code&gt;pthread_cond_signal()&lt;/code&gt;을 대기 중인 모든 쓰레드를 깨우는 &lt;code&gt;pthread_cond_broadcast()&lt;/code&gt;로 바꿔서 사용하면 된다. 그렇게 함으로써 깨어나야 할 쓰레드가 있다면 깨어날 수 있도록 한다. 그렇게 깨어난 쓰레드들은 깨어나서 조건을 재검사하고, 즉시 대기 상태로 다시 들어간다.&lt;/p&gt;
&lt;p&gt;Lampson과 Redell은 이런 경우를 &lt;strong&gt;포함 조건&lt;/strong&gt;(covering condition)이라고 했다. 왜냐하면 (보수적으로) 쓰레드가 깨어나야 하는 모든 경우를 다 포함하기 때문이다. 불필요하게 많은 쓰레드가 깨어나는 단점이 있다. 문맥 전환 오버헤드가 크다. 예리한 독자라면 이 방법을 앞에서 사용했을 수도 있다는 것을 알 것이다 (컨디션 변수를 하나만 사용하는 생산자/소비자 문제를 보자). 하지만 그 경우에는 더 좋은 해법이 있었기 때문에 그 방법을 택했ᨩ다. 일반적으로 시그널을 브로드캐스트 (broadcast)로 바꿨을 때만 프로그램이 동작한다면 아마도 버그가 존재하는 것일 거다. 앞서 다룬 메모리 할당 문제의 경우 브로드캐스트를 적용하는 것이 가장 자명한 해법이다.&lt;/p&gt;</content:encoded><category>os</category><category>cs</category></item><item><title>OSTEP 31 Semaphores</title><link>https://ks1ksi.io/blog/ostep-31-semaphores/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-31-semaphores/</guid><description>OSTEP Semaphores 정리. 세마포어의 wait/post 연산으로 lock, condition variable, 생산자-소비자 문제를 표현하는 방법을 요약한다.</description><pubDate>Mon, 18 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;다양한 범주의 병행성 문제 해결을 위해서는 락과 조건 변수 둘 다 필요하다. 이번 장에서 다룰 &lt;em&gt;&lt;strong&gt;세마포어는 락과 컨디션 변수로 모두 사용할 수 있다.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;핵심 질문 : 세마포어를 어떻게 사용하는가
락과 컨디션 변수 대신에 세마포어를 사용하는 방법은 무엇인가? 세마포어의 정의는 무엇인가? 이진 세마포어는 무엇인가? 락과 컨디션 변수를 사용하여 세마포어를 만드는 것이 가능한가? 그 반대로 세마포어를 사용하여 락과 조건 변수를 만드는 것이 가능한가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-세마포어-정의&quot;&gt;1. 세마포어: 정의&lt;/h2&gt;
&lt;p&gt;세마포어는 정수 값을 갖는 객체로서 두 개의 루틴으로 조작할 수 있다. POSIX 표준에서 이 두 개의 루틴은 &lt;code&gt;sem_wait()&lt;/code&gt;, &lt;code&gt;sem_post()&lt;/code&gt;이다. 세마포어는 초깃값에 의해 동작이 결정되기 때문에 사용 전에 초기화를 해야 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;semaphore.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sem_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;세마포어 &lt;code&gt;s&lt;/code&gt;를 선언 후 3번째 인자로 1을 전달하여 세마포어의 값을 1로 초기화한다. &lt;code&gt;sem_init()&lt;/code&gt;의 두 번째 인자는 모든 예제에서 0이다. 이 값은 같은 프로세스 내의 쓰레드 간에 세마포어를 공유한다는 뜻이다. 다른 값을 사용하는 예시 (다른 프로세스간 동기화 제공) 는 docs를 읽어보자.&lt;/p&gt;
&lt;p&gt;초기화된 후에는 &lt;code&gt;sem_wait()&lt;/code&gt;, &lt;code&gt;sem_post()&lt;/code&gt;라는 함수를 호출하여 세마포어를 다룰 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; sem_wait&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;s) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	decrement the value of semaphore s by one;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	wait &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value of semaphore s is negative;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; sem_post&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;s) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	increment the value of semaphore s by one;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; there are one or more threads waiting&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; wake one;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;sem_wait()&lt;/code&gt; 함수는 즉시 리턴하거나 (세마포어의 값이 1 이상이면), 아니면 해당 세마포어 값이 1 이상이 될 때까지 호출자를 대기시킨다. 다수의 쓰레드들이 &lt;code&gt;sem_wait()&lt;/code&gt;을 호출할 수 있기 때문에, 대기큐에는 다수의 쓰레드가 존재할 수 있다. 대기하는 법에는 회전과 재우기 두 가지가 있다는 것을 기억하자.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sem_post()&lt;/code&gt; 함수는 대기하지 않는다. 세마포어 값을 증가시키고 대기 중인 쓰레드 중 하나를 깨운다.&lt;/li&gt;
&lt;li&gt;세마포어가 음수라면 그 값은 현재 대기 중인 쓰레드의 개수와 같다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 두 개의 함수는 atomic하게 실행된다고 가정한다.&lt;/p&gt;
&lt;h2 id=&quot;2-이진-세마포어-락&quot;&gt;2. 이진 세마포어 (락)&lt;/h2&gt;
&lt;p&gt;우리가 처음으로 세마포어를 적용할 곳은 ‘락’이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sem_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; X);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // X로 세마포어 초기화하기.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sem_wait&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;m);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 임계 영역&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sem_post&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;m);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;X&lt;/code&gt;는 어떤 값이 되어야 할까? 조금만 생각해봐도 1이 되어야 한다는 사실을 알 수 있다.&lt;/p&gt;
&lt;p&gt;쓰레드가 2개라고 가정해보자. 첫 번째 쓰레드가 세마포어 값을 1 감소시켜 0으로 만든다. 세마포어의 값이 음수가 아니므로 리턴하고 진행한다. 첫 번째 쓰레드가 임계 영역에 있을 때 두 번째 쓰레드가 &lt;code&gt;sem_wait()&lt;/code&gt;을 호출하여 임계 영역 진임을 시도한다면 어떻게 될까?&lt;/p&gt;
&lt;p&gt;이 경우 두 번째 쓰레드가 세마포어 값을 -1로 감소시키고, 대기에 들어간다. 첫 번째 쓰레드가 다시 실행되면 &lt;code&gt;sem_post()&lt;/code&gt;를 호출하고 세마포어 값을 0으로 증가시키고, 잠자던 두 번째 쓰레드를 깨운다. 그러면 두 번째 쓰레드가 락을 획득할 수 있다.&lt;/p&gt;
&lt;p&gt;락은 두 개의 상태 (사용 가능, 사용 중) 만 존재하므로 &lt;em&gt;&lt;strong&gt;이진 세마포어 (binary semaphore)&lt;/strong&gt;&lt;/em&gt; 라고도 불린다.&lt;/p&gt;
&lt;h2 id=&quot;3-컨디션-변수로서의-세마포어&quot;&gt;3. 컨디션 변수로서의 세마포어&lt;/h2&gt;
&lt;p&gt;어떤 조건이 참이 되기를 기다리기 위해 현재 쓰레드를 멈출 때에도 세마포어는 유용하게 사용된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;child&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“child\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 시그널 전달: 동작 끝&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; X)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // X의 값은 무엇이 되어야 할까?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“parent: begin\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_create(c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; child&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 자식을 여기서 대기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(“parent: end\n ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다음과 같은 실행 결과를 얻고자 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;parent:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;child&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;parent:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;세마포어를 이용하여 어떻게 이 효과를 만들 수 있을까? 답은 의외로 간단하다. 코드에서 볼 수 있듯이, 부모 프로세스는 자식 프로세스 생성 후 &lt;code&gt;sem_wait()&lt;/code&gt;를 호출하여 자식의 종료를 대기한다. 자식은 &lt;code&gt;sem_post()&lt;/code&gt;를 호출하여 종료되었음을 알린다.&lt;/p&gt;
&lt;p&gt;중요한 질문이 있다. 세마포어 값을 무엇으로 초기화할까?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;정답은 0이다.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;다음과 같은 두 가지 경우를 통해 그 이유를 알아보자.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;자식 프로세스 생성 후, 아직 자식 프로세스가 실행을 시작하지 않은 경우다 (준비 큐에만 들어 있고 실행 중이 아니다). 이 경우 자식이 &lt;code&gt;sem_post()&lt;/code&gt;를 호출하기 전에 부모가 &lt;code&gt;sem_wait()&lt;/code&gt;를 호출할 것이다. 부모 프로세스는 자식이 실행될 때까지 대기해야 한다. 이를 위해서는 &lt;code&gt;wait()&lt;/code&gt; 호출 전에 세마포어 값이 0보다 같거나 작아야 한다. 때문에 0이 초기값이 되어야 한다. 부모가 실행되면 세마포어 값을 감소시키고 (-1로) 대기한다. 자식이 실행되었을 때 &lt;code&gt;sem_post()&lt;/code&gt;를 호출하여 세마포어의 값을 0으로 증가시킨 후 부모를 깨운다. 그러면 부모는 &lt;code&gt;sem_wait()&lt;/code&gt;에서 리턴을 하여 프로그램을 종료시킨다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;부모 프로세스가 &lt;code&gt;sem_wait()&lt;/code&gt;를 호출하기 전에 자식 프로세스의 실행이 종료된 경우이다. 이 경우, 자식이 먼저 &lt;code&gt;sem_post()&lt;/code&gt;를 호출하여 세마포어의 값을 0에서 1로 증가시킨다. 부모가 실행할 수 있는 상황이 되면 &lt;code&gt;sem_wait()&lt;/code&gt; 를 호출한다. 세마포어 값이 1인 것을 발견할 것이다. 부모는 세마포어 값을 0으로 감소시키고 &lt;code&gt;sem_wait()&lt;/code&gt;에서 대기 없이 리턴한다. 이 방법 역시 의도한 결과를 만들어낸다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;4-생산자소비자-유한-버퍼-문제&quot;&gt;4. 생산자/소비자 (유한 버퍼) 문제&lt;/h2&gt;
&lt;p&gt;이 문제는 이전 장 &lt;a href=&quot;https://ks1ksi.io/blog/ostep-30-condition-variables/&quot;&gt;OSTEP 30 Condition Variables&lt;/a&gt;에서 상세히 설명했다. 이 문제를 해결하기 위해 &lt;code&gt;empty&lt;/code&gt;와 &lt;code&gt;full&lt;/code&gt;이라는 두 개의 세마포어를 사용한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer[MAX];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fill &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; use &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; put&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	buffer[fill] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // f1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	fill &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (fill &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; MAX;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // f2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; buffer[use];&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // g1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	use &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (use &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; MAX;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // g2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; empty;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; full;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;producer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		put(i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;consumer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		printf(“&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;d\n ”&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// . . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; MAX)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // empty는 MAX&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // full은 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// . . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;생산자와 소비자 쓰레드가 각 하나씩 있고 CPU도 하나인 상황에 대해 살펴보자. 소비자가 먼저 실행했다고 가정하면 소비자 쓰레드가 그림에서 C1 라인에 먼저 도달하여 &lt;code&gt;sem_wait(&amp;#x26;full)&lt;/code&gt;을 호출한다. 변수full의 값은 0으로 초기화되었기 때문에 해당 명령으로 인해 full의 값은 -1로 감소되고, 소비자는 대기한다. 다른 쓰레드가 &lt;code&gt;sem_post()&lt;/code&gt;를 호출해서 full 변수가 증가하기를 기다려야 한다.&lt;/p&gt;
&lt;p&gt;그런 이후에 생산자 쓰레드가 실행하여 P1 라인에서 &lt;code&gt;sem_wait(&amp;#x26;empty)&lt;/code&gt; 루틴을 호출한다. &lt;code&gt;empty&lt;/code&gt; 변수가 MAX (이 경우에는 1)로 설정되었기 때문에 소비자와 다르게 생산자는 &lt;strong&gt;다음 문장을 계속 실행&lt;/strong&gt;한다. empty 변수는 감소하여 0이 되고 생산자가 데이터 값을 버퍼의 첫 번째 공간에 넣는다 (P2 라인). 그런 후에 생산자는 P3 라인의 &lt;code&gt;sem_post(&amp;#x26;full)&lt;/code&gt;를 호출하여 &lt;code&gt;full&lt;/code&gt; 세마포어의 값을 -1에서 0으로 변경하고 소비자 쓰레드를 깨운다 (대기 상태에서 준비 상태로 바뀐다).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;만약 &lt;code&gt;MAX&lt;/code&gt; 값이 1보다 크고 생산자와 소비자 쓰레드들이 여러 개 있다면? &lt;strong&gt;경쟁 조건&lt;/strong&gt;이 발생할 것이다. &lt;code&gt;put()&lt;/code&gt;, &lt;code&gt;get()&lt;/code&gt;에서 경쟁 조건이 발생한다.&lt;/p&gt;
&lt;p&gt;두 개의 생산자 Pa와 Pb가 있는데, 두 쓰레드가 &lt;code&gt;put()&lt;/code&gt; 을 거의 동시에 호출하였다고 해 보자. Pa가 먼저 실행되어서 버퍼에 첫 공간에 값을 넣기 시작한다 (f1 라인에서 &lt;code&gt;fill = 0&lt;/code&gt;이다). Pa 쓰레드가 &lt;code&gt;fill&lt;/code&gt; 카운터 변수를 1로 변경하기 전에 인터럽트가 걸렸다. 생산자 Pb가 실행되고 f1 라인에서 마찬가지로 버퍼의 &lt;strong&gt;첫 번째 공간에 데이터를 삽입&lt;/strong&gt;한다. Pa가 기록한 이전의 값은 새로운 값으로 대체된다.&lt;/p&gt;
&lt;h3 id=&quot;상호-배제-추가&quot;&gt;상호 배제 추가&lt;/h3&gt;
&lt;p&gt;버퍼를 채우고 버퍼에 대한 인덱스를 증가하는 동작은 임계 영역이기 때문에 신중하게 처리해야 한다. 지금까지 배운 이진 세마포어와 몇 개의 락을 추가하여 해결해보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; empty;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; full;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mutex;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;producer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		put(i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // P4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;consumer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // C4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		printf(“&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;d\n ”&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// . . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; MAX)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // empty는 MAX&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // full은 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt; ,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // lock은 1로 초기화&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// . . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 하면 교착 상태가 발생한다.&lt;/p&gt;
&lt;p&gt;생산자와 소비자 쓰레드가 각 하나씩 있다고 하자. 소비자가 먼저 실행이 되었다. &lt;code&gt;mutex&lt;/code&gt;(c0 라인)를 획득하고 &lt;code&gt;full&lt;/code&gt; 변수에 대하여 &lt;code&gt;sem_wait()&lt;/code&gt;(c1 라인)를 호출한다. 아직 데이터가 없기 때문에 소비자는 대기해야 하고 CPU를 양보해야 한다.&lt;/p&gt;
&lt;p&gt;여기서 중요한 것은 &lt;strong&gt;소비자가 아직도 락을 획득하고 있다는 것&lt;/strong&gt;이다. 생산자가 실행된다. 실행이 가능하면 데이터를 생성하고 소비자 쓰레드를 깨울 것이다. 불행하게도 이 쓰레드는 먼저 mutex 세마포어에 대해서 &lt;code&gt;sem_wait()&lt;/code&gt;를 실행한다(p0 라인). &lt;strong&gt;이미 락은 소비자가 획득한 상태이기 때문에 생산자 역시 대기에 들어간다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;순환 고리가 생겼다. 소비자는 &lt;code&gt;mutex&lt;/code&gt;를 갖고 있으면서 다른 &lt;code&gt;full&lt;/code&gt; 시그널을 발생시키기를 대기하고 있다. full 시그널을 발생시켜야 하는 생산자는 &lt;code&gt;mutex&lt;/code&gt;에서 대기중이다. 생산자와 소비자가 서로를 기다린다. 전형적인 &lt;em&gt;&lt;strong&gt;교착 상태&lt;/strong&gt;&lt;/em&gt;이다.&lt;/p&gt;
&lt;h3 id=&quot;제대로-된-해법&quot;&gt;제대로 된 해법&lt;/h3&gt;
&lt;p&gt;이렇게 락의 범위를 줄여야 한다. 뮤텍스가 임계 영역만 감싸도록 바꿔보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; empty;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; full;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mutex;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;producer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p1.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		put(i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p2.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // p3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;consumer&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; loops; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c1.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c2.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // c3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		printf(“&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;d\n ”&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// . . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; MAX)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;full&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mutex&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// . . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;멀티 쓰레드 프로그램에서 사용 가능한 유한 버퍼를 만들었다!&lt;/p&gt;
&lt;h2 id=&quot;5-reader-writer-락&quot;&gt;5. Reader-Writer 락&lt;/h2&gt;
&lt;p&gt;삽입 연산은 리스트의 상태를 변경하고 (전통적인 임계 영역 보호 방식으로 해결 가능하다), 검색은 자료 구조를 단순히 읽기만 한다. 삽입 연산이 없다는 보장만 된다면 다수의 검색 작업을 동시에 수행할 수 있다. 이와 같은 경우를 위해 만들어진 락이 &lt;strong&gt;reader-writer 락&lt;/strong&gt;이다&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; _rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 이진 세마포어 (기본 락)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; writelock;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 하나의 쓰기 또는 다수의 읽기 락을 위한 락&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; readers;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 임계 영역 내에 읽기를 수행중인 reader의 수&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_acquire_readlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // readers를 변경하기 위해 이진 세마포어 사용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 읽기용 락이 writelock 획득&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_release_readlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers−−;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 마지막으로 읽기용 락이 writelock 해제&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_acquire_writelock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_release_writelock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rw−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 코드는 간단하다. 자료 구조를 “&lt;strong&gt;갱신&lt;/strong&gt;”하려면 새로운 동기화 연산 쌍을 사용한다. 락을 획득하기 위해서는 &lt;code&gt;rwlock_acquire_writelock()&lt;/code&gt;을 사용하고 해제하기 위해서 &lt;code&gt;rwlock_release_writelock()&lt;/code&gt;을 사용한다. 내부적으로는 &lt;code&gt;writelock&lt;/code&gt; 세마포어를 사용하여 하나의 쓰기 쓰레드만이 락을 획득할 수 있도록 하여, 임계 영역 진임 후에 자료 구조를 갱신한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;읽기 락&lt;/strong&gt;을 획득시 읽기 쓰레드(&lt;code&gt;reader&lt;/code&gt;)가 먼저 락을 획득하고 읽기 중인 쓰레드의 수를 표현하는 &lt;code&gt;reader&lt;/code&gt; 변수를 증가시킨다. 첫 번째 읽기 쓰레드가 읽기 락을 획득할 때 중요한 과정이 있다. &lt;strong&gt;읽기 락을 획득시 &lt;code&gt;writelock&lt;/code&gt; 세마포어에 대해 &lt;code&gt;sem_wait()&lt;/code&gt;을 호출하여 쓰기 락을 함께 획득한다.&lt;/strong&gt; 획득한 쓰기 락은 읽기 락을 해제할 때 &lt;code&gt;sem_post()&lt;/code&gt;로 다시 해제한다.&lt;/p&gt;
&lt;p&gt;이 과정을 통해서 읽기 락을 획득하고 난 후, 다른 읽기 쓰레드들이 읽기 락을 획득할 수 있도록 한다. 다만, 쓰기 락을 획득하려는 쓰기 쓰레드 (writer)들은 모든 읽기 쓰레드가 끝날 때까지 대기하여야 한다. 임계 영역을 빠져나오는 마지막 읽기 쓰레드가 “&lt;code&gt;writelock&lt;/code&gt;”에 대한 &lt;code&gt;sem_post()&lt;/code&gt;를 호출하여 대기 중인 쓰기 쓰레드가 락을 획득할 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;이 방식은 몇가지 단점이 존재한다.&lt;/p&gt;
&lt;p&gt;쓰기 쓰레드에게 불리한 방식이다. &lt;strong&gt;쓰기 쓰레드에게 기아 현상이 발생&lt;/strong&gt;할 수 있다.
쓰기 우선 정책 등을 사용해서 기아 현상을 줄일 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; _rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 기본 락&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; writelock;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 쓰기 또는 읽기 락&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    sem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; writer_sem;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 쓰기 작업을 위한 세마포어&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; readers;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 읽기 작업 수&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; waiting_writers;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 대기 중인 쓰기 작업 수&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;waiting_writers &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writer_sem&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_acquire_readlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writer_sem)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 쓰기 작업이 대기 중일 경우 차단&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;        sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writer_sem)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_release_readlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;readers &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;        sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_acquire_writelock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writer_sem)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;waiting_writers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writer_sem)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writer_sem)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;waiting_writers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writer_sem)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; rwlock_release_writelock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rwlock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rw) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sem_post(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;writelock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 구현하면, 쓰기 작업이 대기 중일 때 새로운 읽기 작업이 락을 획득하지 못하게 된다. 이는 &lt;code&gt;writer_sem&lt;/code&gt; 세마포어를 통해 관리된다. 이렇게 하면 쓰기 작업이 대기 중일 때 읽기 작업이 쌓이는 것을 방지할 수 있으므로 쓰기 작업의 기아 현상을 줄일 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;6-식사하는-철학자&quot;&gt;6. 식사하는 철학자&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 31 Semaphores-1694985025028.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;760&quot; height=&quot;672&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2031%20Semaphores-1694985025028.C3iFqosG_Z1D0Hmk.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;다섯 명의 “철학자”가 식탁 주위를 둘러앉았다. 총 다섯 개의 포크가 철학자와 철학자 사이에 하나씩 놓여 있다. 철학자는 식사하는 때가 있고 생각하는 때가 있다. 생각 중일 때는 포크가 필요 없다. 자신의 왼쪽과 오른쪽에 있는 포크를 들어야 식사를 할 수 있다. 이 포크를 잡기 위한 경쟁과 그에 따른 동기화 문제가 병행 프로그래밍에서 다루려는 식사하는 철학자 문제이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	think()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	getforks()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	eat()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	putforks()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;주요 쟁점은 &lt;code&gt;getfork()&lt;/code&gt;와 &lt;code&gt;putfork()&lt;/code&gt;의 루틴을 작성하되 교착 상태의 발생을 방지해야 하고, 어떤 철학자도 못 먹어서 굶주리면 안되며 병행성이 높아야 한다. 이 문제를 해결해보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; left&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p) { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; right&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p) { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (p &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 문제를 해결하기 위해서 세마포어가 필요하다. 각 포크마다 한 개씩 총 다섯 개가 있고 &lt;code&gt;sem_t fork[5]&lt;/code&gt;로 정의한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; getforks&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_wait(forks[left(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_wait(forks[right(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; putforks&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_post(forks[left(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	sem_post(forks[right(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;포크가 필요할 때 하나의 락을 획득한다. 그리고 식사가 끝나면 순서대로 놓는다.
이렇게 하면 &lt;strong&gt;교착 상태&lt;/strong&gt;가 발생한다. &lt;em&gt;&lt;strong&gt;각 철학자가 동시에 자기 왼쪽에 있는 포크를 집으면 평생 기다려야 한다&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;해답-의존성-제거&quot;&gt;해답: 의존성 제거&lt;/h3&gt;
&lt;p&gt;간단한 해법 중 하나는 최소한 하나의 철학자가 다른 순서로 포크를 집도록 하는 것이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; getforks&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (p &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(forks[right(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 오른쪽 포크 먼저 집도록&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(forks[left(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(forks[left(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		sem_wait(forks[right(p)])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 해서 &lt;strong&gt;환형 대기 상태&lt;/strong&gt;를 끊을 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;7-쓰레드-쓰로틀링&quot;&gt;7. 쓰레드 쓰로틀링&lt;/h2&gt;
&lt;p&gt;너무 많은 쓰레드가 동시에 작업을 수행하지 않도록, 세마포어를 사용하여 동시에 실행되는 쓰레드 수를 제한한다.&lt;/p&gt;
&lt;h3 id=&quot;문제-상황-예시&quot;&gt;문제 상황 예시&lt;/h3&gt;
&lt;p&gt;예를 들어, 수백 개의 쓰레드를 만들어 병렬 작업을 수행한다고 가정하자. 코드의 특정 부분에서는 각 쓰레드가 많은 양의 메모리를 점유해 계산을 수행하는데, 이 부분을 ‘메모리 집중 구역’이라고 칭하자. 만약 모든 쓰레드가 동시에 이 메모리 집중 구역에 진입하게 되면, 물리 메모리의 총량을 초과하는 메모리 할당 요청이 발생할 것이다. 이로 인해 시스템은 &lt;strong&gt;스래싱(thrashing)&lt;/strong&gt; 을 시작하여, 디스크와의 페이지 교환이 빈번하게 일어나고 전체 계산 성능이 급격히 저하될 것이다.&lt;/p&gt;
&lt;h3 id=&quot;세마포어를-이용한-해결-방안&quot;&gt;세마포어를 이용한 해결 방안&lt;/h3&gt;
&lt;p&gt;이 문제를 해결하는 간단한 방법은 세마포어를 사용하는 것이다. &lt;strong&gt;세마포어의 초기 값은 메모리 집중 구역에 동시에 진입할 수 있는 최대 쓰레드 수로 설정&lt;/strong&gt;한다. 그 다음, 이 구역에 &lt;code&gt;sem_wait()&lt;/code&gt;와 &lt;code&gt;sem_post()&lt;/code&gt; 함수 호출을 감싸서 세마포어를 적용한다. 이렇게 하면, &lt;strong&gt;세마포어가 자연스럽게 메모리 집중 구역에서 동시에 실행될 수 있는 쓰레드 수를 제한하게 된다.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;8-세마포어-구현&quot;&gt;8. 세마포어 구현&lt;/h2&gt;
&lt;p&gt;저수준 동기화 기법인 락과 컨디션 변수를 사용하여 우리만의 세마포어를 만들어 보자. &lt;strong&gt;(Zemaphore)&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __Zem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cond;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;Zem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 오직 하나의 쓰레드만 이 문장을 호출할 수 있다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Zem_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;Zem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Cond_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Zem_wait&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;Zem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;s) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		Cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value−−;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Zem_post&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;Zem_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;s) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Cond_signal(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;s−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dijkstra가 정의한 세마포어와 여기서 정의한 제마포어 간의 중요한 차이 중 하나는 세마포어의 음수 값이 대기 중인 쓰레드의 수를 나타낸다는 부분이다. 사실 제마포어에서는 이 값이 0 보다 작을 수가 없다. 이 방식이 구현하기도 쉽고 현재 Linux에 구현된 방식이기도 하다.&lt;/p&gt;
&lt;p&gt;세마포어를 사용하여 락과 컨디션 변수를 만드는 것은 매우 까다로운 문제이다. 세마포어로 컨디션 변수 구현에 성공한다면, 당신은 뛰어난 개발자의 소양을 가지고 있는 것이다.&lt;/p&gt;</content:encoded><category>os</category><category>cs</category></item><item><title>Beanstalk 환경변수 추출</title><link>https://ks1ksi.io/blog/beanstalk-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%B6%94%EC%B6%9C/</link><guid isPermaLink="true">https://ks1ksi.io/blog/beanstalk-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%B6%94%EC%B6%9C/</guid><description>Beanstalk 환경변수 추출 기록. AWS Elastic Beanstalk에서 설정된 환경변수를 확인하고 필요한 값을 추출하는 과정을 정리한다.</description><pubDate>Tue, 12 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;prisma db 설정 문제로 EC2에 접속하여 직접 npm run start를 하려고 했는데 환경 변수가 주입되어 있지 않았다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Beanstalk 환경변수 추출-1694451989390.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;958&quot; height=&quot;836&quot; src=&quot;https://ks1ksi.io/_astro/Beanstalk%20%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98%20%EC%B6%94%EC%B6%9C-1694451989390.BKUeEYSp_159URv.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;AWS Elastic Beanstalk를 통해 배포된 애플리케이션의 경우, 환경 변수는 일반적으로 EC2 인스턴스 내에서 &lt;code&gt;/opt/elasticbeanstalk/bin/get-config&lt;/code&gt; 스크립트를 사용하여 조회할 수 있다고 한다.&lt;/p&gt;
&lt;p&gt;기본 포맷은 &lt;code&gt;JSON&lt;/code&gt;이다. &lt;code&gt;--output YAML&lt;/code&gt; 옵션으로 YAML 형태로 출력하도록 하고, 이걸 .env에 넣고 실행하면 된다.&lt;/p&gt;
&lt;p&gt;배포한 애플리케이션은 &lt;code&gt;/var/app/current&lt;/code&gt;에 위치한다. 해당 경로로 이동한 후에&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; /opt/elasticbeanstalk/bin/get-config&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; --output&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; YAML&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; environment&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; .env&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;Beanstalk 환경변수 추출-1694452040551.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1934&quot; height=&quot;298&quot; src=&quot;https://ks1ksi.io/_astro/Beanstalk%20%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98%20%EC%B6%94%EC%B6%9C-1694452040551.hM97g7md_pUcfF.webp&quot; &gt;
성공…!&lt;/p&gt;</content:encoded><category>aws</category></item><item><title>OSTEP 26 Concurrency and Threads</title><link>https://ks1ksi.io/blog/ostep-26-concurrency-and-threads/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-26-concurrency-and-threads/</guid><description>OSTEP Concurrency and Threads 정리. thread의 개념, 공유 주소 공간, race condition과 critical section이 필요한 이유를 설명한다.</description><pubDate>Mon, 11 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;이번 장에서는 프로세스를 위한 새로운 개념인 &lt;strong&gt;쓰레드 (Thread) 를 소개한다.&lt;/strong&gt;
프로그램에서 한 순간에 하나의 명령어만을 실행하는 (단일 Program Counter) 고전적인 관점에서 벗어나, 멀티 쓰레드 프로그램은 &lt;strong&gt;하나 이상의 실행 지점 (독립적으로 불러들여지고 실행될 수 있는 여러 개의 Program Counter 값)&lt;/strong&gt; 을 가지고 있다.&lt;/p&gt;
&lt;p&gt;각 쓰레드는 프로세스와 유사하지만 &lt;strong&gt;쓰레드끼리 주소 공간을 공유하기 때문에 동일한 값에 접근할 수 있다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;하나의 쓰레드의 상태는 프로세스와 유사하게 어디서 명령어들을 불러올지 추적하는 PC와 연산을 위한 레지스터를 가지고 있다. 두 개의 쓰레드가 하나의 프로세서에서 실행 중이라면 두 번째 쓰레드는 &lt;strong&gt;문맥 교환&lt;/strong&gt;을 통해 첫 번째 쓰레드와 교체되어야 한다. 첫 번째 쓰레드가 사용하던 레지스터를 저장하고, 두 번째 쓰레드가 사용하던 레지스터의 내용으로 돌려놓는다는 점에서 프로세스의 문맥 교환과 유사하다.&lt;/p&gt;
&lt;p&gt;프로세스가 &lt;strong&gt;프로세스 제어 블럭 (PCB)&lt;/strong&gt; 에 저장하듯, 프로세스의 쓰레드들의 상태를 저장하기 위해 &lt;strong&gt;쓰레드 제어 블럭 (TCB)&lt;/strong&gt; 가 필요하다. 가장 큰 차이점은 &lt;strong&gt;쓰레드 간 문맥 교환에서는 주소 공간을 그대로 사용한다&lt;/strong&gt;는 점이다.&lt;/p&gt;
&lt;p&gt;쓰레드와 프로세스의 또 다른 차이는 &lt;strong&gt;스택&lt;/strong&gt;에 있다. 멀티 쓰레드 프로세스의 경우에는, 각 쓰레드가 독립적으로 실행되며, 주소 공간에는 &lt;strong&gt;쓰레드마다 스택이 할당되어 있다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 26 Concurrency and Threads-1694363175880.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1330&quot; height=&quot;956&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2026%20Concurrency%20and%20Threads-1694363175880.Dg1JVDA3_1WxvIt.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;오른쪽 주소 공간에는 두 개의 스택이 존재한다. 스택에서 할당되는 변수들이나 매개변수, 리턴값 등은 &lt;strong&gt;해당 쓰레드의 스택인 쓰레드-로컬 저장소(Thread-local storage)&lt;/strong&gt; 에 저장된다.&lt;/p&gt;
&lt;p&gt;쓰레드-로컬 저장소로 인해 정교한 주소 공간의 배치가 무너져버렸다. 스택 사이에 빈 공간이 생겨버렸다. 스택의 크기가 아주 크지 않아도 되기 때문에 대부분의 경우는 문제가 되지 않는다. 재귀 호출을 많이 하면 문제가 생길 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;예제-쓰레드-생성&quot;&gt;예제: 쓰레드 생성&lt;/h2&gt;
&lt;p&gt;“A”, “B”를 출력하는 독립적인 두 개의 쓰레드를 만들어보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;assert.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;pthread.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;common.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;common_threads.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;) arg)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p2;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rc;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;main: begin\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;A&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;B&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// join waits for the threads to finish&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_join(p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_join(p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;main: end\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;mythread()&lt;/code&gt; 함수를 실행할 두 개의 쓰레드를 생성한다. 스케줄러가 어떻게 하느냐에 달려있긴 하지만, 쓰레드가 생성되면 즉시 실행될 수도 있고, 준비 상태에서 실행은 되지 않을 수도 있다.&lt;/p&gt;
&lt;p&gt;두 개의 쓰레드를 생성한 후에 메인 쓰레드는 &lt;code&gt;pthread_join()&lt;/code&gt;을 호출하여 특정 쓰레드의 동작의 종료를 대기한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 26 Concurrency and Threads-1694363842948.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1336&quot; height=&quot;928&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2026%20Concurrency%20and%20Threads-1694363842948.C-ymEMyE_iGgTP.webp&quot; &gt;
&lt;img alt=&quot;OSTEP 26 Concurrency and Threads-1694363849892.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1358&quot; height=&quot;1032&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2026%20Concurrency%20and%20Threads-1694363849892.DhnhjF5W_18GNdW.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 실행 순서는 여러 가지로 나올 수 있다. 쓰레드 1이 쓰레드 2보다 먼저 생성된 경우라도, 스케줄러가 쓰레드 2를 먼저 실행하면 “B”가 “A”보다 먼저 출력될 수도 있다.&lt;/p&gt;
&lt;p&gt;쓰레드의 생성이 함수의 호출과 유사하게 보인다. 함수 호출에서는 함수 실행 후에 호출자 (caller) 에게 리턴하는 반면, 쓰레드의 생성에서는 실행할 명령어들을 갖고 있는 새로운 쓰레드가 생성되고, 생성된 쓰레드는 caller와는 별개로 실행된다. 쓰레드 생성 함수가 리턴되기 전에 쓰레드가 실행될 수도 있고, 리턴된 이후에 쓰레드가 실행될 수도 있다.&lt;/p&gt;
&lt;p&gt;이렇게 쓰레드는 &lt;strong&gt;언제 실행되는지 알기 어렵다.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;2-훨씬-더-어려운-이유-데이터의-공유&quot;&gt;2. 훨씬 더 어려운 이유: 데이터의 공유&lt;/h2&gt;
&lt;p&gt;전역 공유 변수를 갱신하는 두 개의 쓰레드에 대한 예제를 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;pthread.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;ommon.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;common_threads.h&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; volatile&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// mythread()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Simply adds 1 to counter repeatedly, in a loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// No, this is not how you would add 10,000,000 to&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// a counter, but it shows the problem nicely.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;: begin\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;) arg)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;: done\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;) arg)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// main()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Just launches two threads (pthread_create)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// and then waits for them (pthread_join)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p2;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;main: begin (counter = &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;)\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; counter)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;A&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;B&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// join waits for the threads to finish&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_join(p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_join(p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;main: done with both (counter = &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;)\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; counter)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다음과 같은 결과를 기대할 것이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; promp&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; gcc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; −o&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main.c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; −Wall&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; −pthread&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; promp&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; ./main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; A:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; B:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; A:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; B:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; both&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 20000000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;하지만 이 코드를 실행하면 기대한 대로 결과가 출력되지 않는다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; promp&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; ./main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; A:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; B:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; A:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; B:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; both&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 19345221&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다시 한 번 실행해보면, 또 다른 결과가 나온다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; promp&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; ./main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; A:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; B:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; A:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; B:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; done&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; both&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (counter &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 19221041&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;왜 이런 일이 일어나는 걸까?&lt;/p&gt;
&lt;h2 id=&quot;3-제어-없는-스케줄링&quot;&gt;3. 제어 없는 스케줄링&lt;/h2&gt;
&lt;p&gt;왜 이런 일이 일어나는지 알기 위해, 컴파일러가 생성한 코드의 실행 순서를 이해할 필요가 있다.
x86에서 &lt;code&gt;counter&lt;/code&gt;를 증가하는 코드의 순서는 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;mov&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x8049a1c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; $0x1, %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;mov&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0x8049a1c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;counter&lt;/code&gt; 변수의 주소가 &lt;code&gt;0x8049a1c&lt;/code&gt;이라고 하자. &lt;code&gt;mov&lt;/code&gt; 명령어가 명시한 주소의 값을 읽어들인 후, &lt;code&gt;eax&lt;/code&gt; 레지스터에 넣는다. 그리고 1을 (&lt;code&gt;0x1&lt;/code&gt;) &lt;code&gt;eax&lt;/code&gt; 레지스터의 값에 더하는 연산을 한 후, &lt;code&gt;eax&lt;/code&gt; 레지스터에 저장된 그 값을 메모리의 원래 주소에 다시 저장한다.&lt;/p&gt;
&lt;p&gt;무슨 문제가 생길지 예상할 수 있다.&lt;/p&gt;
&lt;p&gt;1번 쓰레드가 &lt;code&gt;counter&lt;/code&gt;를 1 증가시키려고 한다. &lt;code&gt;counter&lt;/code&gt;에 50이 저장되어 있었기 때문에, &lt;code&gt;eax&lt;/code&gt; 레지스터에 넣는다. &lt;code&gt;eax&lt;/code&gt; 레지스터에 1을 더해서 &lt;code&gt;eax&lt;/code&gt; 레지스터의 값이 51이 된다.&lt;/p&gt;
&lt;p&gt;이 때 타이머 인터럽트가 발생하여 운영체제가 1번 쓰레드의 PC와 레지스터 등의 상태를 쓰레드의 TCB에 저장한다.&lt;/p&gt;
&lt;p&gt;그리고 2번 쓰레드가 선택되고 &lt;code&gt;counter&lt;/code&gt;를 증가시키는 코드 영역에 진입한다. 아직 &lt;code&gt;counter&lt;/code&gt;에는 50이 저장되어 있기 때문에 똑같이 50을 읽고, &lt;code&gt;eax&lt;/code&gt; 레지스터에 저장하고, 1 증가시키고, 그 값을 &lt;code&gt;counter&lt;/code&gt;의 주소 &lt;code&gt;0x8049a1c&lt;/code&gt;에 저장한다.
쓰레드는 개별적으로 쓰레드 전용 레지스터를 가지고 있다. 사용 중이던 레지스터들을 저장하고 복구하는 기능 덕분에 이 레지스터들은 가상화되어 각 쓰레드가 개별적으로 사용할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;마지막으로 문맥 교환이 한번 더 일어나서 1번 쓰레드가 실행된다. &lt;code&gt;counter&lt;/code&gt;의 주소 &lt;code&gt;0x8049a1c&lt;/code&gt;에 &lt;code&gt;eax&lt;/code&gt; 레지스터의 값 51을 저장한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 26 Concurrency and Threads-1694368241373.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1430&quot; height=&quot;910&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2026%20Concurrency%20and%20Threads-1694368241373.YnBuUdOg_13I2CP.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 예시처럼 명령어의 실행 순서에 따라 결과가 달라지는 상황을 &lt;em&gt;&lt;strong&gt;경쟁 조건 (race condition)&lt;/strong&gt;&lt;/em&gt; 이라고 한다. 경쟁 조건에 처한 경우 실행할 때마다 다른 결과를 얻는다. 즉, **비결정적(indeterminate)**이다.&lt;/p&gt;
&lt;p&gt;멀티 쓰레드가 같은 코드를 실행할 때 경쟁 조건이 발생하기 때문에 이러한 코드 부분을 &lt;em&gt;&lt;strong&gt;임계 영역 (critical section)&lt;/strong&gt;&lt;/em&gt; 이라고 부른다. 공유 변수를 접근하고, 하나 이상의 쓰레드에서 동시에 실행되면 안 되는 코드를 임계 영역이라 부른다.&lt;/p&gt;
&lt;p&gt;이 때 필요한 것은 &lt;em&gt;&lt;strong&gt;상호 배제 (mutual exclusion)&lt;/strong&gt;&lt;/em&gt; 이다. 이 속성은 하나의 쓰레드가 임계 영역 내의 코드를 실행 중일 때는 다른 쓰레드가 임계 영역에 진입하는 것을 막아 실행할 수 없도록 보장해 준다.&lt;/p&gt;
&lt;h2 id=&quot;4-원자성에-대한-바람&quot;&gt;4. 원자성에 대한 바람&lt;/h2&gt;
&lt;p&gt;강력한 명령어 한 개로 의도한 동작을 수행하여 인터럽트 발생 가능성을 원천 차단할 수 있을까?&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;memory−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x8049a1c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, $0x1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;메모리 상의 위치에 어떤 값을 더하는, 아주 강력한 명령어다. 이 명령어가 &lt;strong&gt;원자적&lt;/strong&gt;으로 실행되는 것을 보장한다고 하자.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“원자적(atomic)“이라는 용어는 여러 개의 작업이나 명령이 있을 때 그 중 하나의 작업 또는 명령이 중간에 인터럽트되거나 중단되지 않고 한 번에 완전히 실행되는 것을 의미합니다. 즉, 원자적인 연산은 “분할 불가능”하다고 볼 수 있습니다. 이는 특히 병렬 처리나 멀티 스레딩 환경에서 중요한 개념입니다. 여러 스레드 또는 프로세스가 동시에 같은 메모리 위치에 접근하는 경우, 원자적 연산은 데이터의 일관성을 유지하기 위해 중요합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;어떻게 하면&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;mov&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x8049a1c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; $0x1, %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;mov&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0x8049a1c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이녀석을 원자적으로 실행할 수 있을까? 하나의 명령어로 해결된다면 좋겠지만 일반적으로는 불가능하다. B-tree의 값을 원자적으로 갱신하는 어셈블리 명령어같은게 있을까? 그런 건 없다.&lt;/p&gt;
&lt;p&gt;하드웨어 동기화 명령어와 운영체제의 지원을 통해 한 번에 하나의 쓰레드만 임계 영역에서 실행하도록 구성된, 제대로 잘 작동하는 멀티 쓰레드 프로그램을 작성할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;5-또-다른-문제-상대-기다리기&quot;&gt;5. 또 다른 문제: 상대 기다리기&lt;/h2&gt;
&lt;p&gt;지금까지는 병행성 문제를 공유 변수 접근에 관련된 쓰레드 간의 상호 작용 문제로 정의하였지만, 실제로는 &lt;strong&gt;하나의 쓰레드가 다른 쓰레드가 동작을 전부 끝낼 때까지 대기해야 하는 상황&lt;/strong&gt;도 일어난다.
프로세스가 디스크 I/O를 요청하고 응답이 올 때까지 기다리는 경우 등이 있다.&lt;/p&gt;
&lt;h2 id=&quot;6-정리-왜-운영체제에서&quot;&gt;6. 정리: 왜 운영체제에서?&lt;/h2&gt;
&lt;p&gt;왜 이런걸 운영체제에서 다루는걸까? 이것이 &lt;em&gt;&lt;strong&gt;“역사”&lt;/strong&gt;&lt;/em&gt; 이기 때문이다. 운영체제는 최초의 병행 프로그램이었고 운영체제 내에서 사용을 목적으로 다양한 기법들이 개발되었다. 나중에는 멀티 쓰레드 프로그램이 등장하면서 응용 프로그래머들도 이 문제를 고민하게 되었다.&lt;/p&gt;
&lt;p&gt;시도 때도 없이 발생하는 인터럽트가 앞서 언급한 모든 문제들의 원인이다. 페이지 테이블, 프로세스 리스트, 파일 시스템 구조 그리고 대부분의 커널 자료 구조들이 올바르게 동작하기 위해서는 적절한 동기화 함수들을 사용해야 한다.&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 27 Thread API</title><link>https://ks1ksi.io/blog/ostep-27-thread-api/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-27-thread-api/</guid><description>OSTEP Thread API 정리. pthread_create, pthread_join, lock, condition variable 등 스레드 프로그래밍 API 사용법을 요약한다.</description><pubDate>Mon, 11 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;앞서 소개한 쓰레드를 다루는 방법에 대해 알아보자.&lt;/p&gt;
&lt;h2 id=&quot;1-쓰레드-생성&quot;&gt;1. 쓰레드 생성&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;POSIX&lt;/strong&gt;에서는 쉽게 쓰레드를 생성할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;pthread.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_create&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;			pthread_t*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;      thread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	  const&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; pthread_attr_t*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; attr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;			void*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;           (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;start_routine)(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;			void*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;           arg);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;POSIX(Portable Operating System Interface)는 운영체제 간에 이식성(Portability)을 높이기 위한 API(Application Programming Interface)와 명령어 셋 등을 정의하는 표준입니다. 이 표준은 IEEE(Institute of Electrical and Electronics Engineers)에 의해 IEEE 1003 시리즈라고 불리는 명세로 정의되어 있습니다. POSIX는 주로 UNIX와 UNIX-like 시스템(예: Linux, macOS)에서 사용되며, 이 표준을 따르는 운영체제에서는 동일한 또는 유사한 프로그래밍 인터페이스를 제공함으로써, 소프트웨어의 이식성을 높입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;POSIX 표준에는 파일 시스템, 프로세스 관리, 스레드 관리, 입출력, 메모리 관리 등 다양한 부분이 포함되어 있습니다. 여기서 &lt;code&gt;pthread_create&lt;/code&gt; 함수는 POSIX 스레드(POSIX Threads, 또는 Pthreads)를 생성하기 위한 C 라이브러리 함수 중 하나입니다. 이 함수를 사용하면 운영체제가 지원하는 스레드를 생성하고 관리할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;thread&lt;/code&gt;는 &lt;code&gt;pthread_t&lt;/code&gt; 타입 구조체를 가리키는 포인터이다. 이 구조체가 쓰레드와 상호작용하는데 사용된다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;attr&lt;/code&gt;은 쓰레드의 속성을 지정한다. 스택의 크기, 스케줄링 우선순위 같은 정보를 지정하기 위해서 사용한다. 대부분은 &lt;code&gt;NULL&lt;/code&gt;을 전달해서 디폴트 값으로 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;start_routine&lt;/code&gt;은 이 쓰레드가 실행할 &lt;strong&gt;함수&lt;/strong&gt;를 나타낸다. C언어의 함수 포인터를 통해 전달한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;C 언어의 함수 포인터는 함수의 주소를 저장하는 변수입니다. 함수 포인터를 사용하면 함수를 다른 함수의 인수로 전달하거나, 배열의 원소로 저장하고, 런타임에 어떤 함수를 호출할지 결정할 수 있습니다. 이런 유연성 덕분에 콜백, 테이블 기반의 점프, 라이브러리 함수의 인터페이스 등 다양한 상황에서 활용됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;func_ptr)(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;func_ptr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; add;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; func_ptr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;  // 결과는 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;operation)(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;i) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        arr[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; operation(arr[i])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; square&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 사용 예&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; numbers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;apply&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(numbers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; square);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b) { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; subtract&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b) { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 함수 포인터 배열&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;operations&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {add&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; subtract};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 사용 예&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; result1 &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; operations[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;  // add 함수 호출, 결과는 15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; result2 &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; operations[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;](&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;  // subtract 함수 호출, 결과는 5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;void*&lt;/code&gt; 타입의 인자를 받고, &lt;code&gt;void*&lt;/code&gt; 타입의 값을 반환한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;arg&lt;/code&gt;는 실행할 함수에게 전달할 인자를 나타낸다. &lt;strong&gt;왜 &lt;code&gt;void*&lt;/code&gt; 타입인가? 어떤 데이터 타입도 인자로 전달할 수 있고, 어떤 타입의 결과도 반환할 수 있기 때문이다.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;pthread.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;args &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) arg;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; %d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;b)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; args &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 20&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;args)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;2-쓰레드-종료&quot;&gt;2. 쓰레드 종료&lt;/h2&gt;
&lt;p&gt;다른 쓰레드가 작업을 완료할 때가지 기다려야 한다면 어떻게 해야 할까? POSIX 쓰레드에서는 &lt;code&gt;pthread_join()&lt;/code&gt;을 호출하면 된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; thread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; **&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value_ptr);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;두 개의 인자를 받는다. 첫 번째는 어떤 쓰레드를 기다리려고 하는지 명시한다. 이 변수는 아까 쓰레드를 생성할 때 초기화되었다. 두 번째 인자는 반환 값에 대한 포인터이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;pthread.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;assert.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;stdlib.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b; } &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; y; } &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;myret_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	myret_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rvals &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;myret_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	rvals&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	rvals&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) rvals;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; argc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	myret_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;rvals;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; args &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 20&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_create(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;args)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_join(p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; **&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;rvals)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;returned &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; %d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; rvals&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; rvals&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;y)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	free(rvals)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;mythread&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;arg) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;args &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;myarg_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) arg;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	printf(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; %d&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;\n&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;b)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	myret_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; oops;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // ALLOCATED ON STACK: BAD!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	oops&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	oops&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;oops;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;pthread_join()&lt;/code&gt;에서 반환 값을 받을 때, 동적 메모리 할당을 사용하지 않고, 스택에 할당하면 안된다. 쓰레드가 종료되면, &lt;code&gt;oops&lt;/code&gt; 값은 쓰레드가 리턴할 때 자동으로 해제된다. 현재 해제된 변수를 가리키는 포인터를 반환하는 것은 좋지 않다.&lt;/p&gt;
&lt;p&gt;사실 &lt;code&gt;pthread_create()&lt;/code&gt;를 사용하여 생성하고, 직후에 &lt;code&gt;pthread_join()&lt;/code&gt;해서 기다리는 것 보다는, 여러 개의 쓰레드를 생성해 놓고, 쓰레드가 끝나기를 기다리는 것이 보통이다.&lt;/p&gt;
&lt;p&gt;하지만 모든 멀티 쓰레드 코드가 조인 루틴을 사용하는 것은 아니다. 예를 들어 웹서버의 경우, 여러 개의 작업자 쓰레드를 생성하고 메인 쓰레드를 이용하여 사용자 요청을 받아 작업자에게 전달하는 작업을 무한히 할 것이다. 이런 프로그램은 &lt;code&gt;join&lt;/code&gt;을 할 필요가 없다. 하지만, 특정 작업을 병렬적으로 실행하기 위해 쓰레드를 생성하는 병렬 프로그램의 경우에는, 종료 전 혹은 계산의 다음 단계로 넘어가기 전에 병렬 수행이 모두 완료되었다는 것을 확인하기 위해 &lt;code&gt;join&lt;/code&gt;을 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/apache/tomcat&quot;&gt;Apache Tomcat&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;3-락&quot;&gt;3. 락&lt;/h2&gt;
&lt;p&gt;쓰레드의 생성과 조인 다음으로 가장 유용한 함수는 락(lock)을 통한 임계 영역에 대한 상호 배제 기법이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다음과 같이 쉽게 사용할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;사실 이 코드는 올바르지 않다. 우선 초기화를 하지 않았다.&lt;/p&gt;
&lt;p&gt;POSIX 쓰레드를 사용할 때 락을 초기화하는 방법은 두 가지이다. 한 가지 방법은 다음과 같이 &lt;code&gt;PTHREAD_MUTEX_INITIALIZER&lt;/code&gt;를 사용하는 것이다.
&lt;code&gt;pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;&lt;/code&gt;
위 연산은 락을 디폴트 값으로 설정한다. 동적으로 초기화하는 방법은 (즉, 실행 중에) 다음과 같이 &lt;code&gt;pthread_mutex_init()&lt;/code&gt;을 호출하는 것이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_mutex_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;assert&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(rc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 성공했는지 확인해야 한다.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;또 이렇게 성공했는지 확인해줘야 한다. 락 사용이 끝났다면 &lt;code&gt;pthread_mutex_destroy()&lt;/code&gt;도 호출해야 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;간단히 말해서, &lt;code&gt;pthread_mutex_init(&amp;#x26;lock, NULL);&lt;/code&gt;은 &lt;code&gt;lock&lt;/code&gt;이라는 이름의 뮤텍스를 초기화하는 명령입니다. 이후에는 이 &lt;code&gt;lock&lt;/code&gt; 변수를 사용하여 &lt;code&gt;pthread_mutex_lock(&amp;#x26;lock)&lt;/code&gt; 또는 &lt;code&gt;pthread_mutex_unlock(&amp;#x26;lock)&lt;/code&gt; 등의 뮤텍스 관련 함수를 호출할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;락과 언락 외에도 락 관련 루틴들이 더 존재한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_mutex_trylock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_mutex_timedlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;							struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; timespec &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;abs_timeout);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;trylock&lt;/code&gt;은 락이 이미 사용 중이라면 실패 코드를 반환한다. &lt;code&gt;timedlock&lt;/code&gt;은 타임아웃이 끝나거나 락을 획득하거나 둘 중 하나가 발생하면 리턴한다. 이 두 함수는 사용하지 않는 것이 좋지만, 락 획득 루틴에서 무한정 대기하는 상황을 피하기 위해 사용하기도 한다.&lt;/p&gt;
&lt;h2 id=&quot;4-컨디션-변수&quot;&gt;4. 컨디션 변수&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_cond_wait&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;cond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pthread_cond_signal&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;cond);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;컨디션 변수는 멀티스레딩 환경에서 특정 조건이 충족되었을 때 스레드들에게 알려주는 메커니즘입니다. POSIX (Portable Operating System Interface) 표준에 따라, C언어에서는 &lt;code&gt;pthread_cond_wait&lt;/code&gt;, &lt;code&gt;pthread_cond_signal&lt;/code&gt; 등의 함수를 사용하여 컨디션 변수를 구현할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_MUTEX_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_cond_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cond &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_COND_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 스레드 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (ready &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_cond_wait(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;cond&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 스레드 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ready &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // while (ready == 0) 탈출&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_cond_signal&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;cond);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;컨디션 변수 사용을 위해서는 이 컨디션 변수와 연결된 락이 &lt;em&gt;&lt;strong&gt;반드시&lt;/strong&gt;&lt;/em&gt; 존재해야 한다. 즉, 위에 두 함수 중 하나를 호출하기 위해서는 그 락을 가지고 있어야 한다.&lt;/p&gt;
&lt;p&gt;첫 번째 루틴 &lt;code&gt;pthread_cond_wait()&lt;/code&gt;는 호출 쓰레드를 수면 (sleep) 상태로 만들고 다른 쓰레드로부터의 시그널을 대기한다. 현재 수면 중인 쓰레드가 관심 있는 무언가가 변경되면 시그널을 보낸다.&lt;/p&gt;
&lt;p&gt;시그널 대기 함수에서는 락을 두 번째 인자로 받고 있지만, 시그널 보내기 함수에서는 조건만을 인자로 받는 것에 유의해야 한다. 이런 차이의 이유는 시그널 대기 함수는 호출 쓰레드를 재우는 것 외에 락도 반납 (release)해야 하기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pthread_cond_wait()&lt;/code&gt;는 깨어나서 리턴하기 직전에 락을 다시 획득한다. 처음 락을 획득한 때부터 마지막에 락을 반납할 때까지 &lt;code&gt;pthread_cond_wait()&lt;/code&gt;를 실행한 쓰레드들은 항상 락을 획득한 상태로 실행된다는 것을 보장한다.&lt;/p&gt;
&lt;p&gt;두 쓰레드 간에 시그널을 주고 받아야 할 때, 락과 컨디션 변수를 사용하는 대신 간단한 플래그를 사용하여 구현할 수도 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 스레드 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (ready &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // spinlock&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 스레드 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ready &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이런 방법은 좋은 방법이 아니다. 조건 검사를 위해 오랫동안 반복문을 실행하여 검사하는 것은 효율적이지 못하다. 또 이렇게 코드를 작성하면 실수하기 매우 쉽다.&lt;/p&gt;
&lt;p&gt;컨디션 변수가 아직 잘 이해가 되지 않아도, 이후 장에서 자세히 다룰 것이다.&lt;/p&gt;
&lt;h2 id=&quot;5-컴파일과-실행&quot;&gt;5. 컴파일과 실행&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;-pthread&lt;/code&gt;플래그를 명령어 링크 옵션 부분에 추가하여 사용하여 &lt;code&gt;pthread&lt;/code&gt; 라이브러리와 링크할 수 있도록 명시해야 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;prompt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;gcc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; −o&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; main.c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; −Wall&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; −pthread&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 28 Locks</title><link>https://ks1ksi.io/blog/ostep-28-locks/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-28-locks/</guid><description>OSTEP Locks 정리. 상호 배제를 위한 lock의 필요성과 spin lock, test-and-set, compare-and-swap, OS 지원 방식의 특징을 설명한다.</description><pubDate>Mon, 11 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;여러 개의 명령어들을 &lt;strong&gt;atomic&lt;/strong&gt;하게 실행하고 싶지만 단일 프로세스의 인터럽트로 인해 그렇게 할 수 없었다. 이 문제를 &lt;strong&gt;lock&lt;/strong&gt;을 통해 직접적으로 다뤄보자. 프로그래머는 소스 코드의 임계 영역을 lock으로 둘러, 그 임계 영역이 마치 하나의 원자 단위 명령어인 것 처럼 실행되도록 한다.&lt;/p&gt;
&lt;h2 id=&quot;1-락-기본-개념&quot;&gt;1. 락: 기본 개념&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;balance &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다음과 같은 임계 영역이 있다고 하자.&lt;/p&gt;
&lt;p&gt;락으로 임계 영역을 다음과 같이 감쌌다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mutex;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 전역 변수로 선언된 락&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;balance &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;락은 하나의 변수이므로, 락을 사용하기 위해 먼저 선언해야 한다. 이 &lt;strong&gt;락 변수&lt;/strong&gt;는 사용 가능 상태, 즉 어느 쓰레드도 락을 가지고 있지 않거나, 사용 중, 즉 임계 영역에서 정확히 하나의 쓰레드가 락을 획득한 상태이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lock()&lt;/code&gt;과 &lt;code&gt;unlock()&lt;/code&gt;의 의미는 간단하다. &lt;code&gt;lock()&lt;/code&gt;을 호출하여 락 획득을 시도한다. 만약 어떤 쓰레드도 락을 가지고 있지 않다면 그 쓰레드는 락을 획득하여 임계 영역으로 진입한다. 이렇게 진입한 쓰레드를 락 소유자 (owner) 라고 부른다. 만약 다른 쓰레드가 &lt;code&gt;lock()&lt;/code&gt;을 호출한다면, 사용 중인 동안에는 &lt;code&gt;lock()&lt;/code&gt; 함수가 리턴하지 않는다.&lt;/p&gt;
&lt;p&gt;락 소유자가 &lt;code&gt;unlock()&lt;/code&gt;을 호출한다면 락은 이제 다시 사용 가능한 상태가 된다. 어떤 쓰레드도 이 락을 대기하고 있지 않다면 (어떤 쓰레드도 &lt;code&gt;lock()&lt;/code&gt;을 호출하여 멈춰 있던 상태가 아니라면) 락의 상태는 사용 가능으로 유지된다.&lt;/p&gt;
&lt;p&gt;락은 프로그래머에게 스케줄링에 대한 최소한의 제어권을 제공한다. &lt;strong&gt;쓰레드에 대한 제어권&lt;/strong&gt;을 일부 받을 수 있다. 이를 통해 프로그래머는 그 코드 내에서 &lt;strong&gt;하나의 쓰레드만 동작&lt;/strong&gt;하도록 보장한다. 혼란스런 실행 순서에 어느 정도 질서를 부여할 수 있는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;2-pthread-락&quot;&gt;2. Pthread 락&lt;/h2&gt;
&lt;p&gt;쓰레드 간 상호 배제 (mutual exclusion) 기능을 제공하기 때문에 POSIX 라이브러리는 락을 &lt;strong&gt;mutex&lt;/strong&gt; 라고 부른다. 상호 배제는 &lt;strong&gt;한 쓰레드&lt;/strong&gt;가 임계 영역 내에 있다면, 이 쓰레드의 동작이 끝날 때까지 다른 쓰레드가 임계 영역에 들어올 수 없도록 제한한다고 해서 붙여진 이름이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;래퍼를 사용하여 락과 언락시에 에러를 확인하도록 함&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PTHREAD_MUTEX_INITIALIZER;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;Pthread_mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // pthread_mutex_lock()을 위한 래퍼.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;balance &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;Pthread_mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;POSIX 방식은 변수명을 지정하여 락과 언락 함수에 전달한다. 다른 변수를 보호하기 위해 다른 락을 사용할수도 있기 때문이다. 이를 통해 여러가지 방식으로 락을 구현할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;세밀한-락과-거친-락-전략&quot;&gt;세밀한 락과 거친 락 전략&lt;/h3&gt;
&lt;h4 id=&quot;거친-락-coarse-grained-locking&quot;&gt;거친 락 (Coarse-Grained Locking)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;하나의 락이 큰 임계 영역을 제어함.&lt;/li&gt;
&lt;li&gt;쉽게 구현할 수 있지만, 병렬성이 제한됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;세밀한-락-fine-grained-locking&quot;&gt;세밀한 락 (Fine-Grained Locking)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;여러 락이 서로 다른 데이터나 자료구조를 보호함.&lt;/li&gt;
&lt;li&gt;한 번에 여러 쓰레드가 서로 다른 락으로 보호된 코드 내에 진입 가능.&lt;/li&gt;
&lt;li&gt;병렬성은 향상되지만, 데드락 등의 복잡한 이슈에 대처해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-락-구현&quot;&gt;3. 락 구현&lt;/h2&gt;
&lt;p&gt;이번 장에서 어떻게 락을 만들어야 하는지, 어떤 종류의 &lt;em&gt;&lt;strong&gt;하드웨어 지원&lt;/strong&gt;&lt;/em&gt;이 필요한지, 운영체제는 무엇을 지원해야 하는지에 대해 다룰 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;효율적인 락은 어떻게 만들어야 하는가? 효율적인 락은 낮은 비용으로 상호 배제 기법을 제공하고 다음에 다룰 몇 가지 속성들을 추가로 가져야 한다. 어떤 하드웨어 지원이 필요한가? 어떤 운영체제 지원이 필요한가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;4-락의-평가&quot;&gt;4. 락의 평가&lt;/h2&gt;
&lt;h3 id=&quot;상호-배제-mutual-exclusion&quot;&gt;상호 배제 (mutual exclusion)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;가장 기본 역할.&lt;/li&gt;
&lt;li&gt;임계 영역 내로 다수의 쓰레드가 진입하는 것을 막을 수 있는지 검사해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;공정성-fairness&quot;&gt;공정성 (fairness)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;여러 쓰레드들이 락을 번갈아가면서 획득할 수 있어야 함.&lt;/li&gt;
&lt;li&gt;락을 전혀 얻지 못해 굶주리는 경우가 발생하면 안 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;성능-performance&quot;&gt;성능 (performance)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;락 사용에 대한 시간적 오버헤드를 평가해야 한다.&lt;/li&gt;
&lt;li&gt;하나의 쓰레드가 실행 중에 락을 획득하고 해제하는 과정에서 발생하는 부하가 얼마나 되는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;5-인터럽트-제어&quot;&gt;5. 인터럽트 제어&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;초창기 단일 프로세서 시스템&lt;/strong&gt;에서는 상호 배제 지원을 위해 임계 영역 내에서 인터럽트를 비활성화 하는 방법을 사용했다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	DisableInterrupts()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	EnableInterrupts()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 방법의 장점은 단순하다는 것이고, 단점은 많다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;먼저, 이 요청을 하는 쓰레드가 인터럽트를 활성화/비활성화 하는 커널 모드 특권 연산을 실행할 수 있도록 허가해야 한다. 만약 어떤 프로그램이 시작과 동시에 &lt;code&gt;lock()&lt;/code&gt;을 호출하고 무한 반복문에 들어간다면, 운영체제는 시스템의 제어권을 다시 얻을 수 없다.&lt;/li&gt;
&lt;li&gt;또, 멀티프로세서에서는 적용을 할 수 없다. 여러 쓰레드가 여러 CPU에서 실행 중이라면, 각 쓰레드가 동일한 임계 영역에 진입하려고 할 수 있다. 이 떄 인터럽트를 비활성화하는 것은 다른 프로세서에서 실행중인 프로그램에는 전혀 영향을 주지 않는다. 즉, 임계 영역에 진입하는 것을 막을 수 없다.&lt;/li&gt;
&lt;li&gt;장시간 인터럽트를 중지시키는 것은 중요한 인터럽트 시점을 놓치게 할 수 있다. CPU가 저장 장치에서 읽기 요청을 마친 사실을 모르고 지나갔다고 해보자. 운영체제는 읽기 결과를 기다리는 프로세스를 깨울 수 없을 것이다.&lt;/li&gt;
&lt;li&gt;마지막으로, 비효율적이다. 일반적인 명령어에 비해 인터럽트를 비활성화시키는 코드들은 최신 CPU에서는 느리게 실행된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;따라서, 인터럽트 비활성화는 제한된 범위에서만 사용되어야 한다. 예를 들어, 운영체제가 내부 자료 구조에 atomic 연산을 하기 위해 등등..&lt;/p&gt;
&lt;h2 id=&quot;6-test-and-set-atomic-exchange&quot;&gt;6. Test-And-Set (Atomic Exchange)&lt;/h2&gt;
&lt;p&gt;멀티 프로세서 시스템에서는 인터럽트를 중지시키는 것이 의미가 없기 때문에 시스템 설계자들은 락 지원을 위한 하드웨어를 설계하기 시작했다. 오늘날에는 모든 시스템이 이러한 지원 기능을 가지고 있다.&lt;/p&gt;
&lt;p&gt;하드웨어 기법 중 가장 기본은 &lt;em&gt;&lt;strong&gt;Test-And-Set&lt;/strong&gt;&lt;/em&gt; 명령어 또는 &lt;em&gt;&lt;strong&gt;원자적 교체 (atomic exchange)&lt;/strong&gt;&lt;/em&gt; 라고 불리는 기법이다. 이를 이해하기 위해 간단한 플래그 변수로 락을 구현해보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; flag; } &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 0: 락 사용 가능&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 1: 락 사용 중&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mutex−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (mutex−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // flag 변수를 검사 (test) 한다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // spin−wait (do nothing)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mutex−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 이제 설정 (set) 한다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	mutex−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;간단한 변수를 사용해 쓰레드가 락을 획득했는지 나타낸다. 임계 영역에 진입하는 첫 쓰레드가 &lt;code&gt;lock()&lt;/code&gt;을 호출하여 플래그가 1인지 &lt;em&gt;&lt;strong&gt;검사(test)&lt;/strong&gt;&lt;/em&gt; 하고 플래그의 값을 1로 &lt;em&gt;&lt;strong&gt;설정(set)&lt;/strong&gt;&lt;/em&gt; 하여 이 쓰레드가 락을 &lt;em&gt;&lt;strong&gt;보유(hold)&lt;/strong&gt;&lt;/em&gt; 하고 있다고 표시한다. 임계 영역에서 나오면 쓰레드가 &lt;code&gt;unlock()&lt;/code&gt;을 호출하여 플래그 값을 초기화하고, 락을 더 이상 보유하고 있지 않다고 표시한다.&lt;/p&gt;
&lt;p&gt;만약 첫 번째 쓰레드가 임계 영역 내에 있을 때 다른 쓰레드가 &lt;code&gt;lock()&lt;/code&gt;을 호출하면 그 쓰레드는 &lt;code&gt;while&lt;/code&gt;문으로 spin-wait을 하며 처음 쓰레드가 &lt;code&gt;unlock()&lt;/code&gt;을 호출하여 플래그를 초기화하기를 기다린다. 처음 쓰레드가 플래그를 초기화하면 대기하던 쓰레드는 &lt;code&gt;while&lt;/code&gt; 문에서 빠져나와 플래그를 1로 설정하고 임계 영역 내로 진입한다.&lt;/p&gt;
&lt;p&gt;이 코드에는 두 가지 문제가 있다.&lt;/p&gt;
&lt;h3 id=&quot;정확성&quot;&gt;정확성&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 28 Locks-1694380377043.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1082&quot; height=&quot;566&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2028%20Locks-1694380377043.CBChIiVq_22UMWC.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;시작할 때 &lt;code&gt;flag = 0&lt;/code&gt;이라 하자. 쓰레드 1이 &lt;code&gt;flag = 1&lt;/code&gt;을 실행하기 직전에 인터럽트가 일어난다면?
두 쓰레드 모두 플래그를 1로 설정하도록 하는 인터럽트 타이밍이 존재한다. &lt;strong&gt;두 쓰레드 모두 임계 영역에 진입&lt;/strong&gt;하게 된다. 잘못 만들었다.&lt;/p&gt;
&lt;h3 id=&quot;성능&quot;&gt;성능&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;spin wait&lt;/strong&gt;&lt;/em&gt;을 통해 플래그의 값을 무한히 검사하는데, 이는 성능상 좋지 못하다. 특히 단일 프로세서에서. 락을 소유한 쓰레드조차 실행하기 힘들도록 한다.&lt;/p&gt;
&lt;h2 id=&quot;7-진짜-돌아가는-스핀-락의-구현&quot;&gt;7. 진짜 돌아가는 스핀 락의 구현&lt;/h2&gt;
&lt;p&gt;앞서 다룬 예제는 하드웨어 지원 없이는 동작이 불가능했다. 다행히도 어떤 시스템은 이 개념에 근간한 락 구현을 위한 어셈블리 명령어를 제공한다. SPARC에서는 &lt;code&gt;ldstub&lt;/code&gt;, x86에서는 원자적 교체 명령어인 &lt;code&gt;xchg&lt;/code&gt;이다. 기본적으로 동일한 일을 수행한다. 일반적으로 &lt;em&gt;&lt;strong&gt;Test-And-Set&lt;/strong&gt;&lt;/em&gt; 이라고 불린다.
&lt;code&gt;TestAndSet&lt;/code&gt; 동작을 정의해보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; TestAndSet&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;old_ptr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; old &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;old_ptr;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // old_ptr의 이전 값을 가져옴&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;old_ptr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // old_ptr 에 new 값을 저장함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; old;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // old의 값을 반환함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;TestAndSet&lt;/code&gt; 명령어가 하는 동작은 다음과 같다. &lt;code&gt;ptr&lt;/code&gt;이 가리키고 있던 예전의 값을 반환하고, &lt;strong&gt;동시에&lt;/strong&gt; &lt;code&gt;new&lt;/code&gt; 값을 &lt;code&gt;ptr&lt;/code&gt;에 저장한다. 여기서의 핵심은 이 동작들이 &lt;strong&gt;원자적&lt;/strong&gt;으로 수행된다는 것이다. 이전 값을 검사 (test -&gt; 반환되는 값) 하는 동시에 메모리에 새로운 값을 설정 (set) 한다.&lt;/p&gt;
&lt;p&gt;이 명령어만으로 간단한 spin lock을 만들 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; flag;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 0은 락이 획득 가능한 상태&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 1은 락을 획득했음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;TestAndSet(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;flag&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // spin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;작동 원리를 파악해보도록 하자.&lt;/p&gt;
&lt;p&gt;처음 쓰레드가 &lt;code&gt;lock()&lt;/code&gt;을 호출하고, 다른 어떤 쓰레드도 현재 락을 보유하고 있지 않다고 하자. 그럼 현재 &lt;code&gt;flag&lt;/code&gt;의 값은 0이다. &lt;code&gt;TestAndSet(flag, 1)&lt;/code&gt;을 호출하면 &lt;em&gt;&lt;strong&gt;반환 값은 0&lt;/strong&gt;&lt;/em&gt; 이라 &lt;code&gt;while&lt;/code&gt;문을 탈출할 수 있다. 그리고 &lt;code&gt;flag&lt;/code&gt;는 1이 된다. 이후 이 쓰레드가 동작을 끝마치면 &lt;code&gt;unlock()&lt;/code&gt;을 호출하여 &lt;code&gt;flag&lt;/code&gt; 값을 다시 0으로 변경한다.&lt;/p&gt;
&lt;p&gt;처음 쓰레드가 락을 획득하여 &lt;code&gt;flag&lt;/code&gt;가 1인 상태에서, 두 번째 쓰레드가 &lt;code&gt;lock()&lt;/code&gt;을 호출한다고 해보자. &lt;code&gt;TestAndSet(flag, 1)&lt;/code&gt;을 호출하면 &lt;em&gt;&lt;strong&gt;반환 값이 1&lt;/strong&gt;&lt;/em&gt; 이라 &lt;code&gt;while&lt;/code&gt;문을 탈출할 수 없다. 락을 보유하고 있는 쓰레드가 존재하는 한 &lt;code&gt;TestAndSet(flag, 1)&lt;/code&gt;은 계속 &lt;em&gt;&lt;strong&gt;1을 반환&lt;/strong&gt;&lt;/em&gt;한다.&lt;/p&gt;
&lt;p&gt;락을 보유하고 있는 처음 쓰레드가 &lt;code&gt;flag&lt;/code&gt; 값을 0으로 변경하면, 두 번째 쓰레드가 &lt;code&gt;TestAndSet(flag, 1)&lt;/code&gt;을 호출했을 때 &lt;em&gt;&lt;strong&gt;반환 값이 0&lt;/strong&gt;&lt;/em&gt;이 되어 &lt;code&gt;while&lt;/code&gt;문을 탈출할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;드디어 제대로 동작하는 상호 배제 함수를 만드는 방법을 배웠다. 이것이 가장 기초적인 형태의 락으로써, 락을 획득할 때까지 CPU 사이클을 소모하면서 회전한다. 단일 프로세서에서 이 방식을 제대로 사용하려면 &lt;strong&gt;선점형 스케줄러&lt;/strong&gt;를 사용해야 한다. 다른 쓰레드가 실행될 수 있도록 타이머를 통해 인터럽트를 발생시킬 수 있기 때문이다. 선점형이 아니면 &lt;code&gt;while&lt;/code&gt;문을 돌리며 대기하는 쓰레드가 CPU를 영원히 독점하게 될 것이다.&lt;/p&gt;
&lt;h2 id=&quot;8-스핀-락-평가&quot;&gt;8. 스핀 락 평가&lt;/h2&gt;
&lt;p&gt;락에서 가장 중요한 측면은 &lt;em&gt;&lt;strong&gt;상호 배제의 정확성&lt;/strong&gt;&lt;/em&gt; 이다. 상호 배제가 가능하다면 스핀 락은 임의의 시간에 단 하나의 쓰레드만이 임계 영역에 진입할 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;그 다음의 항목은 &lt;em&gt;&lt;strong&gt;공정성&lt;/strong&gt;&lt;/em&gt;이다. 대기 중인 쓰레드들에 있어서 스핀 락은 얼마나 공정할까?
스핀 락은 어떠한 공정성도 보장해줄 수 없다. &lt;code&gt;while&lt;/code&gt;문을 돌리는 쓰레드가 경쟁에 밀려서 굶주릴 가능성이 존재한다.&lt;/p&gt;
&lt;p&gt;마지막 항목은 &lt;em&gt;&lt;strong&gt;성능&lt;/strong&gt;&lt;/em&gt;이다. 스핀 락을 사용할 때 얼마나 비용을 지불해야 할까?
단일 CPU의 경우 스핀 락이 갖는 성능 오버헤드는 상당히 클 수 있다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개 중 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 다른 쓰레드가 락을 획득하려고 할 때, 스케줄러가 이들을 한 번씩 깨울 수도 있다.
CPU가 여러 개인 경우 (쓰레드의 개수와 CPU의 개수가 비슷하다면) 스핀 락은 꽤 합리적으로 동작한다. CPU 1에서 실행중인 A가 락을 획득한 후 B가 락을 획득하려고 한다면 CPU 2에서 기다리기 때문에 금방 락을 획득할 수 있을 것이다.&lt;/p&gt;
&lt;h2 id=&quot;9-compare-and-swap&quot;&gt;9. Compare-And-Swap&lt;/h2&gt;
&lt;p&gt;또 다른 하드웨어 기법은 SPARC의 &lt;strong&gt;Compare-And-Swap&lt;/strong&gt;, x86의 &lt;strong&gt;Compare-And-Exchange&lt;/strong&gt;가 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; CompareAndSwap&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; expected&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; actual &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (actual &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; expected)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; actual;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compare-And-Swap 기법의 기본 개념은 &lt;code&gt;ptr&lt;/code&gt;이 가리키고 있는 주소의 값이 &lt;code&gt;expected&lt;/code&gt; 변수와 일치하는지 검사하는 것이다. 만약 일치한다면 &lt;code&gt;ptr&lt;/code&gt;이 가리키는 주소의 값을 새로운 값으로 변경한다. 불일치한다면 변경하지 않는다. 원래의 메모리 값을 반환하여 &lt;code&gt;CompareAndSwap&lt;/code&gt;을 호출한 코드가 락 획득의 성공 여부를 알 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;앞서 작성한 Test-And-Set 방법을 사용했을 때와 같은 방법으로 락을 만들 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; flag;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 0은 락이 획득 가능한 상태&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 1은 락을 획득했음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;CompareAndSwap(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;flag&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // spin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;맨 처음 락을 획득하는 쓰레드는, 0을 1로 바꾸는데 성공해서 &lt;em&gt;&lt;strong&gt;0을 반환받고 (actual == 0)&lt;/strong&gt;&lt;/em&gt; 루프를 탈출한다. 그 이후 접근하는 쓰레드는 &lt;code&gt;expected&lt;/code&gt;는 0, &lt;code&gt;flag&lt;/code&gt;는 1이라 &lt;em&gt;&lt;strong&gt;1을 반환받고 (actual == 1)&lt;/strong&gt;&lt;/em&gt; 루프를 탈출할 수 없다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CompareAndSwap&lt;/code&gt; 명령어는 &lt;code&gt;TestAndSet&lt;/code&gt; 명령어보다 더 강력하다. &lt;strong&gt;대기없는 동기화 (wait-free synchronization)&lt;/strong&gt; 을 다룰 때 강력함을 알게 될 것이다.&lt;/p&gt;
&lt;h2 id=&quot;10-load-linked-그리고-store-conditional&quot;&gt;10. Load-Linked 그리고 Store-Conditional&lt;/h2&gt;
&lt;p&gt;어떤 플랫폼은 임계 영역 진입 제어 함수를 제작하기 위한 명령어 쌍을 제공한다. MIPS 구조에서는 &lt;strong&gt;load-linked&lt;/strong&gt;와 &lt;strong&gt;store-conditional&lt;/strong&gt; 명령어를 앞뒤로 사용하여 락이나 기타 병행 연산을 위한 자료 구조를 만들 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; LoadLinked&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; StoreConditional&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (no one has updated &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr since the LoadLinked to this address) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 갱신 성공&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 갱신 실패&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;LoadLinked&lt;/code&gt;는 일반 로드 명령어와 같이 메모리 값을 레지스터에 저장한다.
&lt;code&gt;StoreConditional&lt;/code&gt; 명령어는 동일한 주소에 다른 &lt;code&gt;store&lt;/code&gt;가 없었던 경우에만 저장을 성공한다. 성공한 경우 &lt;code&gt;LoadLinked&lt;/code&gt;가 탑재했던 값을 갱신하고 1을 반환한다. 실패하면 갱신하지 않고 0을 반환한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;LoadLinked(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;flag)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 0이 될 때까지 spin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;StoreConditional(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;flag&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 1로 변경하는 것을 성공한 경우 완료&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;		// 아니라면 처음부터 다시 시도&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;쓰레드가 &lt;code&gt;while&lt;/code&gt;문을 돌며 &lt;code&gt;flag&lt;/code&gt;가 0이 되기를 기다린다. 0이 되면 락이 해제된 것이다.
락이 획득 가능 상태가 되면 쓰레드는 &lt;code&gt;StoredConditional&lt;/code&gt; 명령어로 락 획득을 시도하고 성공한다면 &lt;code&gt;flag&lt;/code&gt; 값을 1로 변경하고, 임계 영역으로 진입한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;StoredConditional&lt;/code&gt;&lt;/strong&gt; 이 실패할 수도 있다. 이 점이 중요하다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;쓰레드가 &lt;code&gt;lock()&lt;/code&gt;을 호출하여 &lt;code&gt;LoadLinked&lt;/code&gt;를 실행. 락이 사용 가능한 상태이므로 0을 반환. 루프 탈출&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StoredConditional&lt;/code&gt; 명령어를 시도하기 전에 인터럽트&lt;/li&gt;
&lt;li&gt;다른 쓰레드가 &lt;code&gt;lock()&lt;/code&gt;을 호출. &lt;code&gt;LoadLinked&lt;/code&gt;를 실행. 락이 사용 가능한 상태이므로 0을 반환. 루프 탈출&lt;/li&gt;
&lt;li&gt;이 시점에 두 쓰레드는 모두 &lt;code&gt;LoadLinked&lt;/code&gt; 명령어를 실행하였고 각자가 &lt;code&gt;StoredConditional&lt;/code&gt;을 호출하려는 상황&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 명령어의 주요 기능은 오직 하나의 쓰레드만 &lt;code&gt;flag&lt;/code&gt;값을 1로 설정한 후에 락을 획득할 수 있도록 하는 것이다. 두 번째로 &lt;code&gt;StoredConditional&lt;/code&gt;을 실행한 쓰레드는 락 획득에 실패하고 다음 기회를 기다려야 한다.&lt;/p&gt;
&lt;p&gt;이렇게 쓰면 더 짧아진다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;LoadLinked(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;flag)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;||!&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;StoreConditional(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;flag&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // spin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;11-fetch-and-add&quot;&gt;11. Fetch-And-Add&lt;/h2&gt;
&lt;p&gt;마지막 하드웨어 기법은 &lt;strong&gt;Fetch-And-Add&lt;/strong&gt; 명령어로, 원자적으로 특정 주소의 예전 값을 반환하면서 값을 증가시킨다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; FetchAndAdd&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; old &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; old &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; old;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;FetchAndAdd&lt;/code&gt; 명령어를 사용하여 &lt;strong&gt;티켓 락&lt;/strong&gt; 이라는 재미있는 것을 만들어보자!&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ticket;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; turn;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ticket &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;turn &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; myturn &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; FetchAndAdd(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ticket)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;turn &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; myturn)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // spin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;lock) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	FetchAndAdd(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;turn)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ticket&lt;/code&gt;과 &lt;code&gt;turn&lt;/code&gt; 조합을 사용해 락을 만든다. 하나의 쓰레드가 락 획득을 원하면, &lt;code&gt;ticket&lt;/code&gt; 변수에 atomic 연산인 &lt;code&gt;FetchAndAdd&lt;/code&gt; 명령어를 실행한다. 결과 값은 해당 쓰레드의 차례를 나타낸다.&lt;/p&gt;
&lt;p&gt;전역 공유 변수인 &lt;code&gt;lock-&gt;turn&lt;/code&gt;을 사용하여 어느 쓰레드의 차례인지 판단한다. 만약 한 쓰레드가 &lt;code&gt;myturn == lock-&gt;turn&lt;/code&gt;조건에 부합하면, &lt;code&gt;while&lt;/code&gt; 문을 벗어나 락을 획득한다. &lt;code&gt;unlock()&lt;/code&gt;은 &lt;code&gt;turn&lt;/code&gt; 변수의 값을 증가시켜서 대기 중인 다음 쓰레드에게 임계 영역 진입 차례를 넘겨 준다.&lt;/p&gt;
&lt;p&gt;이전까지 접근 방법과의 가장 중요한 차이점은 모든 쓰레드들이 각자의 순서에 따라 진행한다는 것이다. 쓰레드가 티켓 값을 할당받았다면, 미래의 어느 시점에 실행되기 위해 스케줄되어 있다는 것이다. 이전까지는 이러한 보장이 없었다. 예를 들어 &lt;code&gt;Test-And-Set&lt;/code&gt;의 경우 다른 쓰레드들은 락을 획득/해제하더라도 어떤 쓰레드는 계속 회전만 하고 있을 수 있다. 즉 이번 해법은 &lt;em&gt;&lt;strong&gt;공정성&lt;/strong&gt;&lt;/em&gt;이 있다.&lt;/p&gt;
&lt;h2 id=&quot;12-요약-과도한-스핀&quot;&gt;12. 요약: 과도한 스핀&lt;/h2&gt;
&lt;p&gt;지금까지 다룬 해법이 효율적이지 않은 경우도 있다. 특히 프로세서가 하나인 경우 비효율적이다.
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 쓰레드가 하나의 락을 획득하기 위해 경쟁하게 된다면? &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 쓰레드가 계속 &lt;code&gt;spin&lt;/code&gt;할 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;어떻게 하면 스핀에 CPU시간을 낭비하지 않는 락을 만들 수 있을까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;13-간단한-접근법-무조건-양보&quot;&gt;13. 간단한 접근법: 무조건 양보!&lt;/h2&gt;
&lt;p&gt;하드웨어의 지원을 받아 많은 것을 해결하였다. 동작이 검증된 락과 락 획득의 공정성까지도 해결했다. 하지만 스핀만 무한히 하는 경우는 어떻게 해결해야 할까?&lt;/p&gt;
&lt;p&gt;첫 번째로, 락이 해제되기를 기다리며 스핀해야 하는 경우 자신에게 할당된 CPU를 다른 쓰레드에게 양보하도록 할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;TestAndSet(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;flag&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		yield()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // CPU 양보&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;운영체제에 자신이 할당받은 CPU 시간을 포기하고 다른 쓰레드가 실행될 수 있도록 하는 &lt;code&gt;yield()&lt;/code&gt; 기법이 있다고 가정한다. 하나의 쓰레드는 &lt;code&gt;running&lt;/code&gt;, &lt;code&gt;ready&lt;/code&gt;, &lt;code&gt;blocked&lt;/code&gt; 세 가지 상태가 있다. &lt;code&gt;yield&lt;/code&gt; 라는 시스템 콜은 호출 쓰레드 상태를 &lt;code&gt;running&lt;/code&gt;에서 &lt;code&gt;ready&lt;/code&gt;로 변환하여 다른 쓰레드가 &lt;code&gt;running&lt;/code&gt; 상태로 전이하도록 한다.&lt;/p&gt;
&lt;p&gt;단일 CPU 시스템에서 두 개의 쓰레드를 실행하는 경우, 적절하게 동작하는 것을 알 수 있다. (계속 양보)&lt;/p&gt;
&lt;p&gt;100개 정도의 쓰레드들이 락을 획득하기 위해 경쟁하는 경우를 살펴보자. 한 쓰레드가 락을 획득하면 나머지 99개의 쓰레드가 각자 &lt;code&gt;lock()&lt;/code&gt;을 호출하고 CPU를 양보한다. 라운드 로빈 기법을 사용하는 경우, 락을 갖고 있는 쓰레드가 다시 실행되기까지 99개의 쓰레드가 실행하고 양보하는 패턴으로 동작하는데, 이는 비용이 만만치 않게 든다.&lt;/p&gt;
&lt;p&gt;또, 굶주림 문제도 해결하지 못했다. 어떤 쓰레드는 무한히 양보만 하게 될지도 모른다.&lt;/p&gt;
&lt;h2 id=&quot;14-큐의-사용-스핀-대신-잠자기&quot;&gt;14. 큐의 사용: 스핀 대신 잠자기&lt;/h2&gt;
&lt;p&gt;이전 방법들은 너무 많은 부분을 운에 맡겼다. 스케줄러가 좋지 않은 선택을 한다면 기다리거나 CPU를 양보해야 한다. 둘 다 낭비의 여지가 있고 쓰레드가 굶주릴 수 있다.&lt;/p&gt;
&lt;p&gt;어떤 쓰레드가 다음으로 락을 획득할지를 명시적으로 제어할 수 있어야 한다. 이를 위해 운영체제로부터 적절한 지원을 받고, 큐를 이용한 대기 쓰레드들을 관리할 것이다.&lt;/p&gt;
&lt;p&gt;간단히 Solaris의 방식으로 해보자.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;park()&lt;/code&gt;: 호출하는 쓰레드를 잠재우는 함수
&lt;code&gt;unpark(threadID)&lt;/code&gt;: threadID로 명시된 특정 쓰레드를 깨우는 함수&lt;/p&gt;
&lt;p&gt;이 두 루틴은 &lt;strong&gt;이미 사용 중인 락을 요청하는 프로세스를 재우고 해당 락이 해제되면 깨우도록 하는 락&lt;/strong&gt;을 제작하는 데 앞뒤로 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;TestAndSet&lt;/code&gt; 개념을 락 대기자 전용 큐와 함께 사용하여 효율적인 락을 만들 것이고, 큐를 사용하여 굶주림 현상을 방지할 것이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; flag;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; guard;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	queue_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;q;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock_init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;m) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;guard &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	queue_init(m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;m) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;TestAndSet(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;guard&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 회전하면서 guard 락을 획득&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 락 획득&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;guard &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		queue_add(m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; gettid())&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;guard &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		park()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 잠재우기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lock_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;m) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;TestAndSet(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;guard&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 회전하면서 guard 락을 획득&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;queue_empty(m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;flag &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 락을 포기함. 누구도 락을 원치 않음.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		unpark(queue_remove(m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 락을 획득함 (다음 쓰레드를 위해)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	m−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;guard &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;guard&lt;/code&gt; 변수를 사용하여 &lt;code&gt;flag&lt;/code&gt;와 큐의 삽입과 삭제 동작을 스핀 락으로 보호한다. 이 방법은 스핀을 완전히 배제하지는 못했다. 하지만 스핀 대기 시간은 꽤 짧다. 사용자가 지정한 임계 영역에 진입하는 것이 아니라 락과 언락 코드 내의 몇 개의 명령어만 수행하면 되기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lock()&lt;/code&gt; 에 추가된 동작이 있다. &lt;code&gt;lock()&lt;/code&gt;을 호출했는데 다른 쓰레드가 이미 락을 보유중이라면, &lt;code&gt;gettid()&lt;/code&gt;를 호출하여 현재 실행 중인 쓰레드 ID를 얻고, 락 소유자의 큐에 자기 자신을 추가하고 &lt;code&gt;guard&lt;/code&gt; 변수를 0으로 변경한 후 CPU를 양보한다.&lt;/p&gt;
&lt;p&gt;다른 쓰레드가 깨어났을 때 &lt;code&gt;flag&lt;/code&gt; 변수가 0으로 설정되지 않는다. 깨어날 때는 &lt;code&gt;guard&lt;/code&gt; 락을 획득한 상태가 아니기 때문에 &lt;code&gt;flag&lt;/code&gt;를 1로 변경할 수 없다. 따라서 그냥 1인 채로 두고  락을 획득하려는 다음 쓰레드로 직접 전달한다. &lt;code&gt;flag&lt;/code&gt;는 0이 되었다 다시 1이 되는게 아니라 그냥 계속 1이다.&lt;/p&gt;
&lt;p&gt;마지막으로, &lt;code&gt;park()&lt;/code&gt; 직전에 경쟁 조건이 발생한다. 한 쓰레드는 락이 사용중이라 &lt;code&gt;park()&lt;/code&gt;를 실행하려고 한다. 그 직전에 락 소유자한테 CPU가 할당되면 문제가 생길 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;경쟁-조건이-어떻게-발생하는가&quot;&gt;경쟁 조건이 어떻게 발생하는가?&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;B가 &lt;code&gt;park()&lt;/code&gt;를 호출하기 바로 직전에 CPU 스케줄링이 발생하여 A가 실행된다.&lt;/li&gt;
&lt;li&gt;A가 락을 해제하고 B를 깨우기 위해 &lt;code&gt;unpark()&lt;/code&gt;를 호출한다.&lt;/li&gt;
&lt;li&gt;하지만 B는 아직 &lt;code&gt;park()&lt;/code&gt;를 호출하지 않았으므로, 실제로는 깨워질 수 없다. 따라서 B는 락이 해제되었음에도 불구하고 계속 대기 상태에 머물게 된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이러한 문제를 해결하기 위해 Solaris 운영체제는 &lt;code&gt;setpark()&lt;/code&gt; 시스템 콜을 도입했다.&lt;/p&gt;
&lt;h3 id=&quot;setpark는-어떻게-동작하는가&quot;&gt;&lt;code&gt;setpark()&lt;/code&gt;는 어떻게 동작하는가?&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;setpark()&lt;/code&gt;는 쓰레드가 “이제 곧 &lt;code&gt;park()&lt;/code&gt;를 호출할 것이다”라고 시스템에 알리는 역할을 한다. 이렇게 하면, 만약 &lt;code&gt;setpark()&lt;/code&gt; 호출 후에 락이 해제되어 &lt;code&gt;unpark()&lt;/code&gt;가 호출되면, 시스템은 이 정보를 캐시에 저장한다. 따라서 실제 &lt;code&gt;park()&lt;/code&gt;가 호출될 때, 쓰레드는 잠들지 않고 바로 깨어나게 된다.
이런 방식으로 &lt;code&gt;setpark()&lt;/code&gt;는 락을 해제하고 나서 쓰레드를 깨우는 동작 사이에서 발생할 수 있는 경쟁 조건을 해결한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;guard&lt;/code&gt; 변수의 역할을 커널에서 담당하는 것도 하나의 방법이다. 커널은 락 해제와 실행 중인 쓰레드를 큐에서 제거하는 동작을 atomic하게 처리하기 위해 주의를 기울여야 한다.&lt;/p&gt;
&lt;h2 id=&quot;15-다른-운영체제-다른-지원&quot;&gt;15. 다른 운영체제, 다른 지원&lt;/h2&gt;
&lt;p&gt;Linux의 경우 &lt;code&gt;futex&lt;/code&gt;라는 것을 지원한다. 각 &lt;code&gt;futex&lt;/code&gt;는 특정 물리 메모리 주소와 연걸이 되어 있으며 &lt;code&gt;futex&lt;/code&gt;마다 커널 내부의 큐를 가지고 있다. 호출자는 &lt;code&gt;futex&lt;/code&gt;를 호출하여 필요에 따라 잠을 자거나 깨어날 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mutex_lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;atomic_bit_test_set (mutex&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 31&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	atomic_increment (mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;atomic_bit_test_set (mutex&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 31&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		atomic_decrement (mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	v &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (v &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		continue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	futex_wait (mutex&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; v)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mutex_unlock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;mutex) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;atomic_add_zero (mutex났 &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;0x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;80000000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	futex_wake (mutex)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;16-2단계-락&quot;&gt;16. 2단계 락&lt;/h2&gt;
&lt;p&gt;2단계 락 기법은 &lt;strong&gt;락이 곧 해제될 것 같은 경우라면 회전 대기가 유용할 수 있다&lt;/strong&gt;는 것에서 착안하였다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;회전 단계(Spinning Phase)&lt;/strong&gt;: 락을 곧 획득할 수 있을 것이라는 기대하에, 쓰레드는 “회전” 하면서 대기한다. 즉, 쓰레드는 일정 시간 동안 루프를 돌면서 락의 상태를 확인하고, 가능하면 락을 획득하려고 시도한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;잠김 단계(Sleeping Phase)&lt;/strong&gt;: 첫 단계에서 락을 얻지 못한 경우, 이제는 쓰레드가 잠에 들어서 락이 해제될 때까지 기다린다. 락이 해제되면 쓰레드는 깨어나서 작업을 계속합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;앞서 본 Linux의 락은 이러한 형태를 밖는 락이지만 한 번만 회전한다. 일반화된 방법은 &lt;code&gt;futex&lt;/code&gt;가 잠재우기 전에 일정 시간 동안 반복문 내에서 회전하도록 하는 것이다. 2 단계 락은 두 개의 좋은 개념을 사용하여 개선된 하나를 만들어 내는 하이브리드 방식의 일종이다.&lt;/p&gt;
&lt;h3 id=&quot;뜬금없지만-책-추천&quot;&gt;뜬금없지만 책 추천&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.aladin.co.kr/m/mproduct.aspx?ItemId=291746395&quot;&gt;동시성 프로그래밍 - Rust, C, 어셈블리어로 구현하며 배우는 동시성 프로그래밍 A to Z&lt;/a&gt;&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 29 Locked Data Structures</title><link>https://ks1ksi.io/blog/ostep-29-locked-data-structures/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-29-locked-data-structures/</guid><description>OSTEP Locked Data Structures 정리. counter, linked list, queue, hash table에 lock을 적용할 때의 정확성과 성능 trade-off를 설명한다.</description><pubDate>Mon, 11 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;흔하게 사용되는 자료 구조에서 락을 사용하는 방법을 살펴보자.
자료 구조에 락을 추가하여 쓰레드가 사용할 수 있도록 만들면 그 구조는 &lt;strong&gt;thread safe&lt;/strong&gt;하다고 할 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;특정 자료 구조가 주어졌을 때, 어떤 방식으로 락을 추가해야 그 자료 구조가 정확하게 동작하게 만들 수 있을까? 더 나아가 자료 구조에 락을 추가하여 여러 쓰레드가 그 자료 구조를 동시 사용이 가능하도록 하면 (병행성) 고성능을 얻기 위해 무엇을 해야 할까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-병행-카운터&quot;&gt;1. 병행 카운터&lt;/h2&gt;
&lt;p&gt;카운터는 가장 간단한 자료 구조 중 하나이다. 병행이 불가능한 카운터를 먼저 보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; _ &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;_counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; increment&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; decrement&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value−−;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;간단하지만-확장성이-없음&quot;&gt;간단하지만 확장성이 없음&lt;/h3&gt;
&lt;p&gt;위에서 정의한 카운터르 어떻게 하면 &lt;strong&gt;thread safe&lt;/strong&gt;하게 만들 수 있을까?&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; increment&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; decrement&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value−−;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	Pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rc;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 카운터는 가장 간단하고 기본적인 병행 자료 구조의 보편적인 디자인 패턴을 따른 것이다. 자료 구조를 조작하는 루틴을 호출할 때 &lt;strong&gt;락을 추가&lt;/strong&gt;하였고, 그 호출문이 리턴될 때 &lt;strong&gt;락이 해제&lt;/strong&gt;되도록 하였다.&lt;/p&gt;
&lt;p&gt;이 방식은 &lt;strong&gt;Monitor&lt;/strong&gt;를 사용하여 만든 자료 구조와 유사하다. 모니터 기법은 객체에 대한 메소드를 호출하고 리턴할 때 자동적으로 락을 획득하고 해제한다.&lt;/p&gt;
&lt;p&gt;이제 제대로 동작하는 병행 자료 구조를 가지게 되었지만, 성능이 문제다. 이번 장에서는 성능 최적화를 다룰 것이다.&lt;/p&gt;
&lt;p&gt;각 쓰레드가 특정 횟수만큼 공유 카운터를 증가시키는 벤치마크를 실행하였다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 29 Locked Data Structures-1694400264405.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;822&quot; height=&quot;584&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2029%20Locked%20Data%20Structures-1694400264405.C175g2tB_frDyg.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;1개에서 4개의 쓰레드를 사용하여 카운터를 백만 번 증가시켰을 때 총 걸린 시간을 나타낸 것이다. &lt;strong&gt;precise&lt;/strong&gt;라고 표시된 선에서 동기화된 카운터의 확장성이 떨어지는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;이상적으로는 하나의 쓰레드가 하나의 CPU에서 작업을 끝내는 것처럼 멀티프로세서에서 실행되는 쓰레드들도 빠르게 작업을 처리하고 싶을 것이다(완벽한 확장성: perfect scaling).&lt;/p&gt;
&lt;h3 id=&quot;확장성-있는-카운팅&quot;&gt;확장성 있는 카운팅&lt;/h3&gt;
&lt;p&gt;확장 가능한 카운터가 없으면 Linux의 몇몇 작업은 멀티코어 기기에서 심각한 확장성 문제를 겪을 수 있다고 한다.&lt;/p&gt;
&lt;p&gt;여러 기법 중 하나인 &lt;strong&gt;엉성한 카운터(sloppy counter)&lt;/strong&gt; 를 소개한다.&lt;/p&gt;
&lt;p&gt;엉성한 카운터는 하나의 논리적 카운터로 표현되는데, CPU 코어마다 존재하는 하나의 물리적인 지역 카운터와 하나의 전역 카운터로 구성되어 있다. 어떤 기기가 네 개의 CPU를 가지고 있다면 그 시스템은 네 개의 지역 카운터와 하나의 전역 카운터를 가지고 있는 것이다. 이 카운터들 외에도, 지역 카운터를 위한 락들과 전역 카운터를 위한 락이 존재한다.&lt;/p&gt;
&lt;p&gt;기본 개념은 다음과 같다.&lt;/p&gt;
&lt;p&gt;쓰레드는 지역 카운터를 증가시킨다. 이 지역 카운터는 지역 락에 의해 보호된다. 각 CPU는 저마다 지역 카운터를 갖기 때문에 CPU들에 분산되어 있는 쓰레드들은 지역 카운터를 경쟁 없이 갱신할 수 있다. 그러므로 카운터 갱신은 확장성이 있다.&lt;/p&gt;
&lt;p&gt;쓰레드가 카운터의 값을 읽을 수 있기 때문에 전역 카운터를 최신으로 갱신해야 한다. 최신 값으로 갱신하기 위해서 지역 카운터의 값은 주기적으로 전역 카운터로 전달되는데, 이때 전역 락을 사용하여 지역 카운터의 값을 전역 카운터의 값에 더하고, 그 지역 카운터의 값은 0으로 초기화한다.&lt;/p&gt;
&lt;p&gt;지역에서 전역으로 값을 전달하는 빈도는 정해 놓은 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 값에 의해서 결정된다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 값이 작을 수록 확장성 없는 카운터처럼 동작하고, 커질수록 전역 카운터의 값은 실제 값과 차이가 있게 된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 29 Locked Data Structures-1694400794159.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;686&quot; height=&quot;446&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2029%20Locked%20Data%20Structures-1694400794159.D04I-VXG_ZNFCEF.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 예제에서는 한계치를 5로 설정했고, 4개의 CPU에 각각의 지역 카운터 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; … &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;L_4&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 를 갱신하는 쓰레드들이 있다. 전역 카운터의 값 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;G&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;G&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;도 나타내었다. 지역 카운터가 한계치 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 도달하면 그 값은 전역 카운터에 반영되고 지역 카운터의 값은 초기화된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 29 Locked Data Structures-1694400927480.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;852&quot; height=&quot;680&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2029%20Locked%20Data%20Structures-1694400927480.GLyAdl6o_Z2urSnp.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;값이 낮다면 성능이 낮은 대신 전역 카운터의 값이 매우 정확해진다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;값이 높다면 성능은 탁월하지만 전역 카운터의 값은 CPU의 개수와 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;S&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 곱만큼 뒤쳐지게 된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; global;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; glock;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; local[NUMCPUS];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; llock[NUMCPUS];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; threshold;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; threshold) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;threshold &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; threshold;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;global &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;glock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; NUMCPUS; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;local[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		pthread_mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;llock[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; update&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; threadID&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; amt) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;llock[threadID])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;local[threadID] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; amt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;local[threadID] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;threshold) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;glock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;global &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;local[threadID];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;glock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;local[threadID] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;llock[threadID])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;counter_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;c) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;glock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; val &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;global;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;c−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;glock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; val;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;2-병행-연결-리스트&quot;&gt;2. 병행 연결 리스트&lt;/h2&gt;
&lt;p&gt;이제 조금 더 복잡한 구조인 연결 리스트를 다뤄보자. 간단하게 하기 위해 &lt;strong&gt;병행 삽입 연산&lt;/strong&gt;만 살펴보도록 하자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lock;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;L) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Insert&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (new &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		perror(“malloc ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	new−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;key &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	new−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Lookup&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;curr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (curr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (curr−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;key &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;			pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		curr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; curr−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;삽인 연산을 시작하기 전에 락을 획득하고 리턴 직전에 해제한다. 매우 드문 경우지만 &lt;code&gt;malloc()&lt;/code&gt;이 실패할 경우에 미묘한 문제가 생길 수 있다. 그런 경우 실패를 처리하기 전에 락을 해제해야 한다.&lt;/p&gt;
&lt;p&gt;삽입 연산이 병행하여 진행되는 상황에서 실패를 하더라도 락 해제를 호출하지 않으면서 삽입과 검색이 올바르게 동작하도록 수정할 수 있을까? 삽입 코드에서 임계 영역을 처리하는 부분만 락으로 감싸도록 코드 순서를 변경하고, 검색 코드의 종료는 검색과 삽입 모두 동일한 코드 패스를 사용토록 할 수 있다.&lt;/p&gt;
&lt;p&gt;이 방법이 동작하는 이유는 &lt;strong&gt;코드 일부는 사실 락이 필요 없기 때문&lt;/strong&gt;이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt; 자체가 thread safe하다면, 쓰레드는 언제든지 경쟁 조건과 다른 병행성 관련 버그를 걱정하지 않으면서 검색할 수 있다. 공유 리스트 갱신 때에만 락을 획득하면 된다.&lt;/p&gt;
&lt;h3 id=&quot;확장성-있는-연결-리스트&quot;&gt;확장성 있는 연결 리스트&lt;/h3&gt;
&lt;p&gt;병행이 가능한 연결 리스트를 갖게 되었지만, 확장성이 좋지 않다는 문제가 있다. 이를 해결해보자.&lt;/p&gt;
&lt;p&gt;병행성을 개선하는 방법 중 하나로 hand-over-hand locking(또는 lock coupling) 이라는 기법을 개발했다.&lt;/p&gt;
&lt;p&gt;개념은 단순하다. 전체 리스트에 하나의 락이 있는 것이 아니라 개별 노드마다 락을 추가하는 것이다. 리스트를 순회할 때 다음 노드의 락을 먼저 획득하고 지금 노드의 락을 해제하도록 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;L) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Insert&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 동기화를 할 필요 없음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (new &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		perror(“malloc ”)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	new−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;key &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// 임계 영역만 락으로 보호&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	new−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; new;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Lookup&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rv &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;curr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (curr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (curr−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;key &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;			rv &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;			break&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		curr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; curr−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;L−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; rv;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 성공 혹은 실패&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;리스트 연산에 병행성이 높아지기 때문에 괜찮은 것처럼 보인다. 하지만, 리스트를 순회할 때 &lt;strong&gt;각 노드에 락을 획득하고 해제하는 오버헤드가 매우 크기 때문에 속도 개선을 기대하기 쉽지 않다.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;락 획득/해제와 같이 부하가 큰 연산을 추가하여 자료 구조를 설계했다면, 병행성 자체가 좋아졌다는 것은 큰 의미가 없다. 오히려, 부하가 큰 루틴은 거의 사용하지 않는 간단한 방법이 더 좋다. 락을 많이 추가하고 복잡도가 증가하면 큰 단점이 된다. 어느 것이 더 좋은지 알 수 있는 방법은 딱 한 가지이다. 간단하지만 병행성이 떨어지는 것과 복잡하지만 병행성이 높은 두 경우를 다 구현하고 성능을 측정해 보아야 한다. 성능을 속일 수는 없지 않는가. 결과는 “좋다”, “나쁘다” 둘 중에 하나일 테니까 말이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;3-병행-큐&quot;&gt;3. 병행 큐&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __queue_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;tail;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; headLock;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	pthread_mutex_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tailLock;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;queue_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Queue_Init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;queue_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;q) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	tmp−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;tail &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;headLock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tailLock&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Queue_Enqueue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;queue_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;q&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	assert(tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	tmp−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	tmp−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tailLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;tail−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;tail &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tailLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Queue_Dequeue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;queue_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;q&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_lock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;headLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;newHead &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (newHead &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;headLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; newHead−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; newHead;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	pthread_mutex_unlock(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;q−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;headLock)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;	free(tmp)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;4-병행-해시-테이블&quot;&gt;4. 병행 해시 테이블&lt;/h2&gt;
&lt;p&gt;전체 자료 구조에 하나의 락을 사용한 것이 아니라 해시 버켓 (리스트로 구현되어 있음) 마다 락을 사용하여서 성능이 우수하다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#define&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; BUCKETS&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __hash_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	list_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lists[BUCKETS];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;hash_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Hash_Init&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;hash_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;H) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; BUCKETS; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;		List_Init(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;H−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lists[i])&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Hash_Insert&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;hash_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; bucket &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; BUCKETS;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Insert(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;H−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lists[bucket]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; key)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Hash_Lookup&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;hash_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; bucket &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; key &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; BUCKETS;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; List_Lookup(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;H−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lists[bucket]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; key)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 29 Locked Data Structures-1694421703747.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;746&quot; height=&quot;606&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2029%20Locked%20Data%20Structures-1694421703747.D9zDQBKc_Z2jaLKw.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;5-요약&quot;&gt;5. 요약&lt;/h2&gt;
&lt;p&gt;락 획득과 해제 시 코드의 흐름에 매우 주의를 기울여야 한다. 병행성 개선이 반드시 성능 개선으로 이어지는 것은 아니다. 성능 개선은 성능에 문제가 생길 경우에만 해결책을 강구해야 한다.&lt;/p&gt;
&lt;p&gt;락을 전혀 사용하지 않는 동기화 기법들도 추후에 다룰 것이다.&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 20 Advanced Page Tables</title><link>https://ks1ksi.io/blog/ostep-20-advanced-page-tables/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-20-advanced-page-tables/</guid><description>OSTEP Advanced Page Tables 정리. 선형 페이지 테이블의 공간 비용을 줄이기 위한 multi-level page table 등 개선 방식을 설명한다.</description><pubDate>Tue, 08 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;페이징의 두 번째 문제는 페이지 테이블의 크기이다. 어떻게 하면 페이지 테이블이 차지하는 메모리의 크기를 줄일 수 있을까??&lt;/p&gt;
&lt;h2 id=&quot;1-간단한-해법-더-큰-페이지&quot;&gt;1. 간단한 해법: 더 큰 페이지&lt;/h2&gt;
&lt;p&gt;페이지 크기를 증가시키면, 페이지 테이블의 크기가 줄어든다. 페이지 크기를 4KB에서 16KB로 증가시킨다면, 페이지 테이블의 크기는 4MB에서 1MB로 둘어들 것이다. 페이지 크기의 증가는 부작용이 있다. 바로 &lt;strong&gt;내부 단편화&lt;/strong&gt;이다.&lt;/p&gt;
&lt;p&gt;페이지 크기가 너무 크다면, 할당된 페이지 내부에서 낭비가 발생할 것이다. 결국 컴퓨터 시스템의 메모리가 금방 고갈될 것이다. 때문에 일반적으로 4KB 혹은 8KB의 페이지 크기를 사용한다.&lt;/p&gt;
&lt;h2 id=&quot;2-하이브리드-페이징과-세그먼트&quot;&gt;2. 하이브리드: 페이징과 세그먼트&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 20 Advanced Page Tables-1691519881843.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1137&quot; height=&quot;1485&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2020%20Advanced%20Page%20Tables-1691519881843.CnwTk4vR_Z2frRuk.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;1KB 크기의 페이지를 갖는 16KB의 주소 공간을 예로 들어보자.
이 예제에서 한 개의 코드 페이지(VPN 0)가 물리 페이지 10번, 그리고 한 개의 힙 페이지(VPN 4)가 23번 물리 페이지에 매핑되어 있다. 가상 주소 공간의 끝부분에 두 개의 스택 페이지 (VPN 14, 15)가 물리 페이지 28번과 4번에 매핑되어 있다.&lt;/p&gt;
&lt;p&gt;그림에서 보이듯 &lt;strong&gt;페이지 테이블 대부분이 비어 있다&lt;/strong&gt;. 이런 낭비를 막아보자.&lt;/p&gt;
&lt;p&gt;프로세스의 전체 주소 공간을 위해 하나의 페이지 테이블을 두는 대신, 논리 세그멘트마다 따로 페이지 테이블을 두면 어떨까? 코드, 힙, 스택 세그멘트에 대해 페이지 테이블을 각각 만들어보자.&lt;/p&gt;
&lt;p&gt;세그멘테이션에서는 세그멘트의 물리 주소 시작 위치를 나타내는 베이스 레지스터, 그리고 크기를 나타내는 바운드 또는 리미트 레지스터가 있다.&lt;/p&gt;
&lt;p&gt;우리 방식에서, 베이스 레지스터는 세그멘트 시작 주소가 아니라 세그멘트의 페이지 테이블의 시작 주소를 갖는다. 바운드 레지스터는 페이지 테이블의 끝을 나타내기 위해 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 20 Advanced Page Tables-1691519905981.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1385&quot; height=&quot;147&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2020%20Advanced%20Page%20Tables-1691519905981.BYGlbAwK_1c46K2.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;하드웨어에 세 개의 베이스/바운드 레지스터 쌍이 코드, 힙, 스택을 위해 존재한다고 가정해보자. 이 시스템에서 모든 프로세스는 세 개의 페이지 테이블을 갖는다.&lt;/p&gt;
&lt;p&gt;TLB 미스가 발생하면 하드웨어는 세그멘트 비트를 사용하여 어떤 베이스와 바운드 쌍을 사용할지 결정한다. 하드웨어는 그 레지스터에 들어 있는 물리 주소를 VPN과 다음과 같은 형싱으로 조작하여 페이지 테이블 항목 (PTE) 의 주소를 얻는다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;SN &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (VirtualAddress &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; SEG_MASK) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; SN_SHIFT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;VPN &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (VirtualAddress &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; VPN_MASK) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; VPN_SHIFT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;AddressOfPTE &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; Base[SN] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (VPN &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(PTE))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;앞에서 살펴본 선형 페이지 테이블과 작동이 거의 동일하다. 세 개의 페이지 테이블 레지스터를 사용하는 것이 차이점이다.&lt;/p&gt;
&lt;p&gt;이 방법 역시 문제가 존재한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;여전히 세그멘테이션을 사용한다. 세그멘테이션은 주소 공간의 사용에 있어 특정 패턴을 사용하기 때문에 유연하지 못하다.&lt;/li&gt;
&lt;li&gt;외부 단편화를 유발한다. 페이지 테이블 크기에 제한이 없으며 다양한 크기를 가진다. 따라서 메모리 상에서 페이지 테이블용 공간을 확보하는 것이 더 복잡하다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;3-멀티-레벨-페이지-테이블&quot;&gt;3. 멀티 레벨 페이지 테이블&lt;/h2&gt;
&lt;p&gt;페이지 테이블을 페이지 단위로 자른 뒤, 하나라도 유효한 entry가 없다면, 해당 페이지 테이블을 유지하지 않는 방식이다. 이를 처리하기 위해 멀티 레벨 페이지 테이블에는 페이지 디렉토리 (page directory) 라는 개념을 도입했다. 페이지 테이블의 페이지가 어디에 있는지, 해당 페이지 테이블에 유효한 페이지가 있는지를 알려주는 데 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 20 Advanced Page Tables-1691519923419.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1377&quot; height=&quot;815&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2020%20Advanced%20Page%20Tables-1691519923419.BuV1Rtk6_1oNyFo.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;페이지 디렉토리에는 실제로 사용중인 두 개의 페이지 테이블에만 접근할 수 있도록 하여 메모리 낭비를 방지한다.&lt;/p&gt;
&lt;p&gt;이렇게 주소 변환에 한 번의 단계가 추가되었기 때문에 멀티 레벨이라고 불린다.&lt;/p&gt;
&lt;p&gt;페이지 디렉토리는 페이지당 하니의 entry를 가지고 있다. 페이지 테이블의 시작 부분, 즉 베이스 레지스터 같은 느낌이다. page directory entry가 유효한지 알려주는 valid bit와 page frame number로 구성된다.&lt;/p&gt;
&lt;p&gt;이렇게 하면 메모리 낭비를 줄일 수 있지만, TLB 미스가 발생한 경우 메모리에서 페이지 테이블에 접근하기 위해 2번의 메모리 접근이 발생한다. 디렉토리 한 번, 페이지 테이블 한 번.&lt;/p&gt;
&lt;h3 id=&quot;2단계-이상-사용하기&quot;&gt;2단계 이상 사용하기&lt;/h3&gt;
&lt;p&gt;만약 페이지 디렉터리가 너무 커지면 어떻게 해야 할까?
페이지 디렉터리 자체를 멀티 페이지들로 나누어서, 트리의 단계를 늘리는 방식으로 해결할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 20 Advanced Page Tables-1691519976607.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1345&quot; height=&quot;229&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2020%20Advanced%20Page%20Tables-1691519976607.Cm3EMwgY_Zd30L4.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;4-역-페이지-테이블&quot;&gt;4. 역 페이지 테이블&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 20 Advanced Page Tables-1691520132956.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;657&quot; height=&quot;501&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2020%20Advanced%20Page%20Tables-1691520132956.cmLi2Igr_Z1uiXIj.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;물리 페이지를 가상 주소 상의 페이지로 변환한다.
순차 탐색을 하면 느리기 때문에, 해시 테이블 등을 사용한다.
역 페이지 테이블의 각 항목은 해당 물리페이지를 사용 중인 프로세스 번호, 해당 가상 페이지 번호를 갖고 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;역 페이지 테이블(Inverted Page Table, IPT)은 일반적인 페이지 테이블과 다르게 동작하는 메모리 관리 방식입니다. 일반적인 페이지 테이블은 각 프로세스에 대해 가상 주소를 물리 주소로 매핑하는 역할을 합니다. 그러나 이런 방식은 테이블의 크기가 가상 메모리의 크기에 비례하기 때문에, 테이블 자체가 매우 큰 메모리를 차지하게 될 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;역 페이지 테이블은 이 문제를 해결하기 위해 만들어진 데이터 구조로, 물리적 메모리의 각 페이지를 가상 주소 공간에 매핑합니다. 이는 물리 메모리의 각 페이지를 인덱스로 하는 배열을 유지함으로써 이루어집니다. 각 엔트리는 해당 물리 페이지를 사용 중인 프로세스의 식별자(ID)와 해당 가상 페이지의 주소를 저장합니다. 따라서 역 페이지 테이블은 모든 프로세스에 대한 정보를 한 곳에서 관리합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;역 페이지 테이블을 사용하면 전체 시스템에 대한 페이지 테이블의 크기가 물리 메모리의 크기에 비례하게 됩니다. 이는 가상 메모리 주소 공간이 물리 메모리보다 훨씬 클 수 있기 때문에, 메모리 사용량을 크게 줄일 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;그러나 역 페이지 테이블을 사용하면 가상 주소를 물리 주소로 변환하는 과정이 복잡해집니다. 주어진 가상 주소와 프로세스 ID를 가진 물리 페이지를 찾기 위해 전체 테이블을 검색해야 할 수 있습니다. 이를 해결하기 위해, 일반적으로 빠른 검색을 가능하게 하는 해시 테이블이나 다른 방식의 인덱싱이 사용됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;5-페이지-테이블을-디스크로-스왑&quot;&gt;5. 페이지 테이블을 디스크로 스왑&lt;/h2&gt;
&lt;p&gt;아무리 축소해도 메모리에 상주시키기에 너무 커진다면 어떻게 해야 할까?
페이지 테이블을 디스크에 저장하기도 한다.
스왑은 다음 단원에서 알아보자.&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 21 Swapping Mechanisms</title><link>https://ks1ksi.io/blog/ostep-21-swapping-mechanisms/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-21-swapping-mechanisms/</guid><description>OSTEP Swapping Mechanisms 정리. 메모리가 부족할 때 페이지를 디스크로 내보내고 다시 가져오는 swap 공간과 page fault 처리를 설명한다.</description><pubDate>Tue, 08 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;지금까지는 가상 주소 공간이 비현실적으로 작아 모두 물리 메모리에 탑재가 가능하다고 가정했다. 즉, 실행 중인 프로세스의 전체 주소 공간이 메모리에 탑재된 것으로 가정했다. 이제 이 가정을 완화해보자.&lt;/p&gt;
&lt;p&gt;다수 프로세스들의 큰 주소 공간을 지원하기 위해, 주소 공간 중 현재 필요하지 않는 일부를 보관해 둘 공간이 필요하다. 일반적으로 그 공간은 메모리 공간보다 용량은 크고, 속도는 느릴 것이다. HDD 혹은 SSD가 될 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;운영체제는 어떻게 크고 느린 HDD, SSD를 사용하면서 마치 커다란 가상 주소 공간이 있는 것처럼 할 수 있을까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;주소 공간이 충분히 크면, 프로그램을 위한 충분한 메모리 공간이 있는지 걱정할 필요가 없다, 그냥 필요할 때 메모리 할당을 운영체제에게 요구하기만 하면 된다. 운영체제가 이런 가상 환경을 제공하면 프로그램 입장에서 매우 편해진다.&lt;/p&gt;
&lt;p&gt;이와 반대로, 예전에는 메모리 오버레이라는 개념이 존재했다. 프로그래머가 코드 또는 데이터의 일부를 메모리에 수동으로 탑재하고 제거했다. 함수 호출이나 데이터에 접근할 때마다 코드 또는 데이터를 먼저 메모리에 탑재해야 하는 불편함이 있었다.&lt;/p&gt;
&lt;p&gt;멀티프로그래밍 시스템, 즉 &lt;strong&gt;동시에&lt;/strong&gt; 여러 프로그램들을 실행시키는 시스템이 발명되면서, 많은 프로세스들의 페이지를 물리 메모리에 전부 저장하는 것이 불가능하게 되었다. 실제 물리 메모리보다 더 많은 용량의 메모리가 필요하게 되었다. 현대 가상 메모리가 이를 어떻게 수행하는지 지금부터 알아보자.&lt;/p&gt;
&lt;h2 id=&quot;1-스왑-공간&quot;&gt;1. 스왑 공간&lt;/h2&gt;
&lt;p&gt;우선 디스크에 페이지들을 저장할 수 있는 일정 공간을 확보해야 한다. 이 용도의 공간을 &lt;strong&gt;스왑 공간(swap space)&lt;/strong&gt; 이라고 한다. 메모리 페이지를 읽어서 이곳에 쓰고 &lt;em&gt;(swap out)&lt;/em&gt;, 여기서 페이지를 읽어서 메모리에 탑재 &lt;em&gt;(swap in)&lt;/em&gt; 시키기 때문이다. 스왑 공간의 입출력 단위는 페이지라고 가정한다. 운영체제는 스왑 공간에 있는 모든 페이지들의 &lt;strong&gt;디스크 주소&lt;/strong&gt;를 기억해야 한다.&lt;/p&gt;
&lt;p&gt;스왑 공간의 크기는 시스템이 사용할 수 있는 메모리 페이지의 최대 수를 결정하기 때문에 중요하다. 일단 스왑 공간의 크기는 매우 크다고 가정하자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 21 Swapping Mechanisms-1691479560583.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1595&quot; height=&quot;661&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2021%20Swapping%20Mechanisms-1691479560583.oTnkkhCK_ZXer3O.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;물리 메모리에는 4개의 페이지, 스왑 공간에는 8개의 페이지가 존재한다. 물리 메모리는 프로세스 0, 1, 2가 공유하고 있다. 유효한 페이지 몇 개만 메모리에 올려 놓았고, 나머지는 디스크에 스왑 아웃되어 있다. 3번 프로세스는 모든 페이지가 스왑 아웃 되어 있는 것으로 보아 현재 실행중이 아니다.&lt;/p&gt;
&lt;p&gt;스왑 공간에만 스왑을 할 수 있는 것은 아니다. 물리 메모리가 추가 공간을 확보해야 할 때, 코드 영역의 페이지들이 차지하는 물리 페이지는 즉시 다른 페이지가 사용할 수 있다. 코드가 저장되어 있는 파일 시스템 영역이 스왑 목적으로 사용되는 것이다. 해당 페이지들은 디스크에 원본이 있기 때문에, 언제든지 스왑 인이 가능하기 때문이다.&lt;/p&gt;
&lt;h2 id=&quot;2-present-bit&quot;&gt;2. Present Bit&lt;/h2&gt;
&lt;p&gt;이제 페이지 스왑을 위한 기능을 다룰 차례다. 하드웨어 기반 TLB를 사용하는 시스템을 가정할 것이다.&lt;/p&gt;
&lt;p&gt;메모리가 참조되는 과정을 remind 해보자.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;프로세스가 가상 메모리 참조를 생성한다 (명령어 탑재, 데이터 접근 등)&lt;/li&gt;
&lt;li&gt;하드웨어는 메모리에서 원하는 데이터를 가져오기 전에, 우선 가상 주소를 물리 주소로 변환한다.
&lt;ol&gt;
&lt;li&gt;가상주소에서 VPN을 추출한 후에 TLB에 해당 정보가 있는지 검사한다. (TLB 히트) 만약 성공하면 물리 주소를 얻은 뒤에 메모리로 가져온다.&lt;/li&gt;
&lt;li&gt;만약 VPN을 TLB에서 찾을 수 없다면 (TLB 미스), 하드웨어는 페이지 테이블의 메모리 주소를 파악하고 (페이지 테이블 베이스 레지스터 사용), VPN을 인덱스로 하여 원하는 페이지 테이블 항목 (PTE) 를 추출한다.&lt;/li&gt;
&lt;li&gt;해당 페이지 테이블 항목이 유효하고, 관련 페이지가 물리 메모리에 존재하면 하드웨어는 PTE에서 PFN 정보를 추출하고 그 정보를 TLB에 탑재한다.&lt;/li&gt;
&lt;li&gt;탑재 후 명령어를 재실행한다. 이번에는 TLB 히트이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;페이지가 디스크로 스왑되는 것을 가능하게 하려면 많은 기법들이 추가되어야 한다.
하드웨어가 PTE에서 해당 페이지가 물리 메모리에 존재하지 않는다는 것을 표현해야 한다. &lt;strong&gt;present bit&lt;/strong&gt;를 사용하여 각 페이지 테이블 항복에 어떤 페이지가 존재하는지를 표현한다. present bit가 1로 설정되어 있으면, 물리 메모리에 해당 페이지가 존재한다는 것이고, 위에서 설명한 대로 작동한다. 하지만 0으로 설정되어 있으면 메모리에 해당 페이지가 존재하지 않고 디스크 어딘가에 존재한다는 것을 나타낸다.&lt;/p&gt;
&lt;p&gt;물리 메모리에 존재하지 않는 페이지 참조를 &lt;strong&gt;페이지 폴트 (page fault)&lt;/strong&gt; 라 한다. 페이지 폴트가 발생하면 이 페이지 폴트를 처리하기 위해 운영체제로 제어권이 넘어간다. 즉, 페이지 폴트 핸들러가 실행된다.&lt;/p&gt;
&lt;h2 id=&quot;3-페이지-폴트&quot;&gt;3. 페이지 폴트&lt;/h2&gt;
&lt;p&gt;TLB 처리 방법에 따라 두 종류의 시스템으로 나눌 수 있다. 하드웨어 기반 TLB 시스템, 소프트웨어 기반 TLB 시스템. 두 종류 모두 페이지 폴트가 발생하면 &lt;strong&gt;운영체제&lt;/strong&gt;가 그 처리를 담당한다. 운영체제의 페이지 폴트 핸들러가 그 처리 메커니즘을 규정한다.&lt;/p&gt;
&lt;p&gt;만약 요청된 페이지가 메모리에 없고, 디스크로 스왑되었다면, 운영체제는 해당 페이지를 메모리로 스왑해 온다. 그렇다면 &lt;em&gt;원하는 페이지의 위치를 어떻게 파악할까?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;많은 시스템들에서 해당 페이지의 스왑 공간사에서의 위치를 페이지 테이블에 저장한다. 운영체제는 PFN과 같은 PTE 비트들을 페이지의 디스크 주소를 나타내는 데 사용할 수 있다. 페이지 폴트 발생 시 운영체제는 페이지 테이블 항목에서 페이지의 디스크 상 위치를 파악하여 메모리로 탑재한다.&lt;/p&gt;
&lt;p&gt;디스크 IO가 완료되면 운영체제는 해당 PTE의 PFN 값을 탑재된 페이지의 메모리 위치로 갱신한다. 이 작업이 완료되면 페이지 폴트를 발생시킨 명령어가 &lt;strong&gt;재실행&lt;/strong&gt;된다. 재실행으로 인해 TLB 미스가 발생할 수 있다. TLB 미스 처리 과정에서 TLB 값이 갱신되고, 최종적으로 마지막 재실행 시에 TLB에서 주소 변환 정보를 찾아 이를 통해 물리 주소에서 원하는 데이터나 명령어를 가져온다.&lt;/p&gt;
&lt;p&gt;IO 전송 중에는 해당 프로세스가 &lt;strong&gt;blocked&lt;/strong&gt; 상태가 된다는 것에 유의해야 한다. 페이지 폴트 처리 시 운영체제는 다른 프로세스를 실행할 수 있다. 한 프로세스의 IO작업 (페이지 폴트 등) 은 오래 걸리는 일이기 때문에 IO작업과 다른 프로세스의 실행을 중첩시키는 방식을 통해 하드웨어를 효율적으로 사용한다.&lt;/p&gt;
&lt;h2 id=&quot;4-메모리에-빈-공간이-없으면&quot;&gt;4. 메모리에 빈 공간이 없으면?&lt;/h2&gt;
&lt;p&gt;위 설명에서, page in을 위한 메모리가 충분하다고 가정했다. 메모리에 여유 공간이 없다면 어떻게 해야 할까?&lt;/p&gt;
&lt;p&gt;메모리에 탑재하고자 하는 페이지를 위한 공간을 확보하기 위해, 다른 페이지들을 먼저 page out 하려고 할 수 있다. 이 교체 페이지를 선택하는 것을 &lt;strong&gt;페이지 교체 정책 (page replacement policy) 라고 한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;좋은 페이지 교체 정책을 위해 많은 노력이 있었다. 잘못된 교체 정책을 선택하면, 프로그램이 메모리 속도가 아니라 디스크 속도로 실행될 수 있기 때문이다. 다음 장에서 교체 정책에 대해 자세히 다룰 것이다.&lt;/p&gt;
&lt;h2 id=&quot;5-페이지-폴트의-처리&quot;&gt;5. 페이지 폴트의 처리&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 21 Swapping Mechanisms-1691483926992.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1691&quot; height=&quot;907&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2021%20Swapping%20Mechanisms-1691483926992.DmYzMwWx_iB5Bd.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 21 Swapping Mechanisms-1691483933676.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1681&quot; height=&quot;365&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2021%20Swapping%20Mechanisms-1691483933676.DRwlVTVN_2orIPz.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;6-교체는-언제-일어나는가&quot;&gt;6. 교체는 언제 일어나는가&lt;/h2&gt;
&lt;p&gt;지금까지는 메모리에 여유 공간이 고갈된 후에 교체 알고리즘이 작동하는 것을 가정하였다. 하지만 이 방법은 효율적이지 못하다. 또, 운영체제는 항상 어느 정도의 여유 메모리 공간을 확보하고 있어야 한다. 이를 위해 대부분의 운영체제들은 여유 공간에 관련된 최댓값과 최솟값 (high watermark HW, low watermark LW) 을 설정하여 교체 알고리즘에 활용한다.&lt;/p&gt;
&lt;p&gt;운영체제가 여유 공간의 크기가 최솟값보다 작아지면 여유 공간 확보를 담당하는 백그라운드 쓰레드가 실행되고, 여유 공간의 크기가 최댓값에 이를 때까지 페이지를 제거한다. 이를 일반적으로 스왑 데몬 또는 페이지 데몬이라고 불린다.&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 22 Swapping Policies</title><link>https://ks1ksi.io/blog/ostep-22-swapping-policies/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-22-swapping-policies/</guid><description>OSTEP Swapping Policies 정리. FIFO, Random, LRU 계열 페이지 교체 정책과 locality를 활용한 캐시 교체 전략을 요약한다.</description><pubDate>Tue, 08 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;내보낼 페이지는 어떻게 결정할까?
교체 정책에 의해 이 결정이 내려진다. 교체 정책을 자세히 알아보자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-캐시-관리&quot;&gt;1. 캐시 관리&lt;/h2&gt;
&lt;p&gt;시스템의 전체 페이지들 중 일부만이 메인 메모리에 유지된다는 것은, 메인 메모리는 가상 메모리의 페이지를 가져다 놓기 위한 &lt;strong&gt;캐시&lt;/strong&gt;로 생각할 수 있다. 즉, 디스크로부터 페이지를 가져오는 횟수를 최소한으로 하는 것이 우리의 목표다.&lt;/p&gt;
&lt;p&gt;캐시 히트와 미스이 횟수를 안다면, 프로그램의 평균 메모리 접근 시간 (Average memory access time, AMAT) 을 계산할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691492021156.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;560&quot; height=&quot;84&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691492021156.BQaZ0JiD_1LXE9H.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;P_{Hit}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.08125em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 캐시 히트 확률, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;P_{Miss}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;ss&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 캐시 미스 확률, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{M}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;은 메모리 접근 비용, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;T_{M}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;은 디스크 접근 비용이다.&lt;/p&gt;
&lt;h2 id=&quot;2-최적-교체-정책&quot;&gt;2. 최적 교체 정책&lt;/h2&gt;
&lt;p&gt;최적 교체 정책은 미스를 최소화한다. 가장 나중에 접근될 페이지를 교체하는 것이 최적이며, 가장 적은 횟수의 미스를 발생시킨다는 것이 증명되었다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691493443358.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;724&quot; height=&quot;684&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691493443358.CNkFJpkr_Z17XyFA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;페이지 3을 처음으로 접근할 때, 캐시 미스가 발생한다. 어떤 페이지를 내보내야 할까? 0, 1, 2 중에서 가장 나중에 접근한 2를 내보내는 것이 최적이다.&lt;/p&gt;
&lt;p&gt;하지만 미래를 아는 것은 일반적으로 불가능하다. 이 최적 기법은 다른 정책들과 비교하는데만 사용 될 것이고, 그 정책이 얼마나 정답에 가까운지 알 수 있을 것이다.&lt;/p&gt;
&lt;h2 id=&quot;3-간단한-정책-fifo&quot;&gt;3. 간단한 정책: FIFO&lt;/h2&gt;
&lt;p&gt;시스템에 페이지가 들어오면 큐에 삽입되고, 교체를 해야 할 경우 큐의 테일에 있는 페이지(먼저 들어온 페이지)가 내보내진다. FIFO는 매우 구현하기 쉽다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691494361159.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;722&quot; height=&quot;674&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691494361159.DD9x8ub7_Z15HoiU.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;3번 페이지에 처음 접근할 때 가장 처음 들어온 0번 페이지가 나가게 된다.&lt;/p&gt;
&lt;h2 id=&quot;4-무작위-선택&quot;&gt;4. 무작위 선택&lt;/h2&gt;
&lt;p&gt;이 방식은 메모리 압박이 있을 때 페이지를 무작위로 선택하여 교체한다. FIFO처럼 구현하기 쉽지만 내보낼 블럭을 제대로 선택하려는 노력을 하지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691494510597.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;720&quot; height=&quot;684&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691494510597.HXt5JeUj_28sU9o.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;FIFO보다는 약간 더 좋은 성능을 보이며, 최적의 방법보다는 약간 나쁜 성능을 보인다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691494638908.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;968&quot; height=&quot;624&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691494638908.NBPbZimi_Z2uRzq6.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;5-과거-정보의-사용-lru&quot;&gt;5. 과거 정보의 사용: LRU&lt;/h2&gt;
&lt;p&gt;과거 사용 이력을 활용해 보자. 예를 들어 어떤 프로그램이 가까운 과거에 한 페이지를 접근했다면, 가까운 미래에 그 페이지를 다시 접근하게 될 확률이 높다. 이런 류의 정책은 지역성의 원칙 (principle of locality) 이라고 부르는 특성에 기반을 둔다.&lt;/p&gt;
&lt;p&gt;Least Frequently Used (LFU) 정책은 가장 적은 빈도로 사용된 페이지를 교체한다. Least Recently Used (LRU) 정책은 가장 오래 전에 사용하였던 페이지를 교체한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691494885435.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;712&quot; height=&quot;680&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691494885435.DzPMdLf__Z1EY1DF.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;3번 페이지에 처음 접근했을 때, 운영체제는 2번 페이지를 내보낸다. 0번 페이지와 1번 페이지가 최근에 사용되었기 때문이다. 그 후에는 0번 페이지를 내보낸다. 1번 페이지와 3번 페이지가 최근에 사용되었기 때문이다.&lt;/p&gt;
&lt;p&gt;두 경우 모두 LRU는 과거 정보를 활용하였고, 결과적으로 이후의 참조들에서 히트가 발생하였다는 것을 보면 결정이 옳았다는 것을 알 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;6-워크로드에-따른-성능-비교&quot;&gt;6. 워크로드에 따른 성능 비교&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691495235847.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;706&quot; height=&quot;808&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691495235847.DrKxQD6M_Z2fIEkd.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691495247904.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;788&quot; height=&quot;818&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691495247904.BVj3cF5-_2mmdaB.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;80대 20 워크로드는 20%의 페이지들에서 80%의 참조가 발생하고, 나머지 80%의 페이지에서 20%의 참조가 발생한다. 인기 있는 페이지를 두는 LRU가 더 좋은 성능을 보인다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691495329637.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;740&quot; height=&quot;816&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691495329637.CP6ov6kN_URh8d.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 워크로드는 50개의 페이지를 순차적으로 참조한다. 그 후 다시 처음으로 돌아가서 그 접근 순서를 반복한다.&lt;/p&gt;
&lt;p&gt;LRU와 FIFO 정책에서 좋지 못한 성능을 보인다. 오래된 페이지를 내보낸다는 특성으로 인해 캐시 크기가 49라고 할지라도 50개 페이지를 순차 반복하는 경우 히트율이 0%가 된다.&lt;/p&gt;
&lt;h2 id=&quot;7-과거-이력-기반-알고리즘-구현&quot;&gt;7. 과거 이력 기반 알고리즘 구현&lt;/h2&gt;
&lt;p&gt;LRU 정책을 완벽하게 구현하기 위해서는 많은 작업을 해야한다. 각 페이지 접그남다 해당 페이지가 리스트의 가장 앞으로 이동하도록 자료 구조를 갱신해야 한다. 어떤 페이지가 가장 최근에 또는 가장 오래 전에 사용되었는지를 관리하기 위해서 &lt;strong&gt;모든 메모리 참조 정보를 기록해야 한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 작업을 효율적으로 하는 법은 약간의 하드웨어 지원을 받는 것이다.
예를 들어 페이지 접근이 있을 때마다 하드웨어가 메모리의 시간 필드를 갱신하도록 할 수 있다. 이렇게 하여 페이지가 접근되면 하드웨어가 시간 필드를 현재 시간으로 설정한다. 페이지 교체 시에 운영체제는 가장 오래 전에 사용된 페이지를 찾기 위해 시간 필드를 검색한다.&lt;/p&gt;
&lt;p&gt;페이지 수가 증가하면 페이지들의 시간 정보 배열을 검사하는 일이 매우 고비용의 연산이 된다. 가장 오래된 페이지를 꼭 찾아야 할까? 비슷하게 오래된 페이지를 찾아도 되지 않을까?&lt;/p&gt;
&lt;h2 id=&quot;8-lru-정책-근사&quot;&gt;8. LRU 정책 근사&lt;/h2&gt;
&lt;p&gt;LRU를 근사하여 연산량을 줄일 수 있다. 이 개념에는 &lt;strong&gt;use bit&lt;/strong&gt; 라고 하는 약간의 하드웨어 자원이 필요하다. 시스템의 각 페이지마다 하나의 use bit가 있으며 이 use bit는 메모리 어딘가에 존재한다.&lt;/p&gt;
&lt;p&gt;페이지가 참조될 때마다 하드웨어에 의해서 use bit가 1로 설정된다. 하드웨어는 이 비트를 절대로 지우지 않는다. 운영체제만 0으로 바꿀 수 있다.&lt;/p&gt;
&lt;p&gt;운영체제는 LRU에 가깝게 구현하기 위해 use bit를 어떻게 활용할까?
시계 알고리즘에 대해 알아보자. 시스템의 모든 페이지들이 환형 리스트를 구성한다고 가정하고, 운영체제는 현재 바늘이 가리키고 있는 페이지 P의 use bit가 1인지 0인지 검사한다. 만약 1이면 최근에 사용되었고, 바람직한 교체 대상이 아니라는 것이다. P의 use bit를 0으로 바꾸고 다음 페이지 P+1로 바늘을 이동한다. 이런 방식으로 use bit가 0인 페이지를 탐색한다. 최악의 경우 모든 페이지를 돌면서 use bit를 전부 0으로 설정하게 될 수도 있다.&lt;/p&gt;
&lt;p&gt;미사용 페이지를 찾기 위해 매번 모든 메모리를 검사하지 않아도 된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 22 Swapping Policies-1691498468659.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;832&quot; height=&quot;832&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2022%20Swapping%20Policies-1691498468659.BCPhHA28_Z1X2j4k.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;9-갱신된-페이지-dirty-page-의-고려&quot;&gt;9. 갱신된 페이지 (Dirty Page) 의 고려&lt;/h2&gt;
&lt;p&gt;어떤 페이지가 변경되어 dirty 상태가 되었다면, 그 페이지를 내보내기 위해서는 디스크에 변경 내용을 기록해야 하기 때문에 비용이 비싸다. 만약 변경되지 않았다면 내보낼 때 추가 비용은 없다. 때문에 dirty page 대신 수정된 적 없는 페이지를 내보내는 것을 선호한다. 하드웨어는 이를 지원하기 위해 더티 비트를 둔다.&lt;/p&gt;
&lt;p&gt;예를 들어 시계 알고리즘으로 교체 대상을 선택할 때, 사용되지 않은 상태이고 깨끗한 페이지를 먼저 찾도록 하고, 이를 만족하는 대상을 찾지 못하는 경우, 깨끗하지 않지만 (dirty 상태이지만) 한동안 사용되지 않았던 페이지를 찾도록 할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;10-다른-vm-정책&quot;&gt;10. 다른 VM 정책&lt;/h2&gt;
&lt;p&gt;페이지 교체 정책 외에도 다른 정책들이 존재한다.
예를 들어, 운영체제는 언제 페이지를 메모리로 불러들일지 결정해야 한다. 이 정책은 &lt;strong&gt;페이지 선택 (page selection) 정책&lt;/strong&gt; 이라고 불린다.&lt;/p&gt;
&lt;p&gt;운영체제는 대부분의 페이지를 읽어 들일 때 &lt;strong&gt;요구 페이징 정책&lt;/strong&gt;을 사용한다. 이 정책은 요청된 후 즉시, 페이지가 실제로 접근 될 때 운영체제가 해당 페이지를 메모리로 읽어 들인다.&lt;/p&gt;
&lt;p&gt;요청됐을 때 메모리로 읽어 들이는 대신, 어떤 페이지가 곧 사용될 것이라는 것을 예상하여 &lt;strong&gt;선반입&lt;/strong&gt;하는 경우도 있다. 어떤 시스템은 페이지 P가 탑재될 때 P+1이 접근될 확률이 높기 때문에 P+1도 함께 탑재되도록 할 수 있다.&lt;/p&gt;
&lt;p&gt;또 다른 정책은 운영체제가 변경된 페이지를 디스크에 반영하는 데 관련된 방식이다. 한 번에 한 페이지씩 디스크에 쓸 수 있지만, 기록해야 할 페이지들을 메모리에 모은 후, 한 번에 디스크에 기록할 수 있다. 이와 같은 동작을 &lt;strong&gt;클러스터링(clustering)&lt;/strong&gt; 이라고 부르며 효과적인 동작 방식이다.&lt;/p&gt;
&lt;h2 id=&quot;11-쓰래싱-thrashing&quot;&gt;11. 쓰래싱 (Thrashing)&lt;/h2&gt;
&lt;p&gt;메모리 사용 요구가 감당할 수 없을 만큼 많고 실행 중인 프로세스가 요구하는 메모리가 가용 물리 메모리 크기를 초과하는 경우 운영체제는 어떻게 해야 할까?&lt;/p&gt;
&lt;p&gt;이런 경우 운영체제는 끊임없이 페이징을 하게 될 것이고 이와 같은 상황을 쓰래싱 (Thrashing) 이라 부른다.&lt;/p&gt;
&lt;p&gt;몇몇 초기 운영체제들은 다수 프로세스 중 일부 프로세스의 실행을 중지시키고, 나머지 프로세스를 메모리에 올려 실행하도록 했다.&lt;/p&gt;
&lt;p&gt;최신 운영체제들은 더 과감한 방법을 사용하기도 한다. 예를 들어, Linux의 일부 버전에서는 ‘메모리 부족 킬러’를 동작시켜 메모리 요구가 많은 프로세스를 강제로 종료함으로써 메모리 부족 상황을 해결하려고 시도한다.
이 방법은 효과적으로 메모리 부족 문제를 해결할 수 있지만, 중요한 프로세스를 종료하게 되면 다른 문제가 발생할 수 있다.&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 17 Free Space Management</title><link>https://ks1ksi.io/blog/ostep-17-free-space-management/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-17-free-space-management/</guid><description>OSTEP Free Space Management 정리. free list, splitting, coalescing과 best-fit, worst-fit, first-fit 등 메모리 할당 정책을 요약한다.</description><pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690828800464.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;625&quot; height=&quot;189&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690828800464.C6izyGgQ_Z1kcYNb.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;메모리에 빈 공간이 이렇게 존재한다고 해보자.
프로세스 A가 메모리 10을 차지하고 있고, 빈 공간의 전체 크기는 20이다. 하지만 각각 10으로 파편화 되어 있기 때문에 프로세스 B의 15바이트의 요청은 실패할 것이다. 이 문제를 이번 장에서 해결해보자.&lt;/p&gt;
&lt;h2 id=&quot;1-가정&quot;&gt;1. 가정&lt;/h2&gt;
&lt;p&gt;매번 하듯 몇 가지 가정을 하고 시작하자.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt;과 &lt;code&gt;free()&lt;/code&gt;에서 제공하는 것과 같은 기본 인터페이스를 가정한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;void *malloc(size_t size)&lt;/code&gt;는 프로그램이 요청한 바이트 수를 나타내는 &lt;code&gt;size&lt;/code&gt;를 받아들이고, 요청된 크기와 같거나 더 큰 영역을 가리키는 &lt;code&gt;void&lt;/code&gt; 포인터를 반환한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;void free(void *ptr)&lt;/code&gt;는 포인터를 전달받고 해당 영역을 해제한다. 메모리 공간을 해제할 때 사용자는 라이브러리에게 크기를 전달하지 않는다. 라이브러리는 &lt;strong&gt;포인터만으로 해제하고자 하는 메모리 영역의 크기를 파악해야 한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;우리는 오늘 &lt;strong&gt;외부 단편화 방지&lt;/strong&gt;에 초점을 둘 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;외부 단편화: 위에서 본 그림처럼 메모리 공간이 여러 개의 작은 조각으로 나뉘어 메모리를 효과적으로 사용하지 못하는 상태.
내부 단편화: 할당된 메모리 영역 내에서 사용되지 않는 공간이 발생하는 것.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;또, &lt;strong&gt;클라이언트에게 할당된 메모리는 다른 위치로 재배치될 수 없다고 가정&lt;/strong&gt;할 것이다. 즉 &lt;code&gt;malloc()&lt;/code&gt;을 호출해서 힙의 일부를 할당받은 경우, 그 메모리 영역은 &lt;code&gt;free()&lt;/code&gt;를 호출하기 전 까지 프로그램이 소유하게 되고, 다른 위치로 옮겨질 수 없다. 이 경우 &lt;strong&gt;메모리 압축&lt;/strong&gt; 기법을 사용할 수 없다.&lt;/p&gt;
&lt;h2 id=&quot;2-저수준-기법들&quot;&gt;2. 저수준 기법들&lt;/h2&gt;
&lt;p&gt;우선 대부분의 할당기에서 사용되는 일반적인 기법에 대해 알아보자.&lt;/p&gt;
&lt;h3 id=&quot;분할과-병합&quot;&gt;분할과 병합&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;빈 공간 리스트&lt;/strong&gt;는 힙에 있는 빈 공간들의 집합이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690828800464.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;625&quot; height=&quot;189&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690828800464.C6izyGgQ_Z1kcYNb.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 힙의 빈 공간 리스트에는 다음과 같이 두 개의 원소가 있을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690866725253.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;761&quot; height=&quot;249&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690866725253.nSNzZofg_Z1dDSAJ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;10바이트보다 큰 요청은 모두 실패하여 &lt;code&gt;NULL&lt;/code&gt;을 반환할 것이다.
만약 1바이트를 요청한다면 어떻게 될까? 이 경우 할당기는 &lt;strong&gt;분할(splitting)&lt;/strong&gt; 이라는 작업을 수행한다. 요청을 만족시킬 수 있는 빈 청크를 찾아 이를 둘로 분할한다. 첫 번째 청크는 호출자에게 반환되고, 두 번째 청크는 리스트에 남게 된다. 위의 그림에서 1바이트 요청이 발생하고, 할당기가 리스트의 두 번째 원소를 사용하기로 했다면 다음과 같이 될 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690867003290.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;739&quot; height=&quot;207&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690867003290.DvzGke8Y_r8PO8.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt;은 20(1바이트가 할당된 영역의 주소)을 반환하고, 빈 공간의 주소는 21부터 시작하고, 길이는 9가 될 것이다. &lt;strong&gt;요청이 특정 빈 청크의 크기보다 작은 경우 분할 기법을 사용한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;분할에 동반되는 기법은 빈 공간의 &lt;strong&gt;병합(coalescing)&lt;/strong&gt; 이다. 응용 프로그램이 &lt;code&gt;free(10)&lt;/code&gt;을 호출하여 힙의 중간에 존재하는 공간을 반환하면 어떻게 될까?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690867282520.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1011&quot; height=&quot;229&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690867282520.BcICkfyf_ZrJOAI.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 빈 공간을 리스트에 추가하면 다음과 같은 모양이 될 것이다. 힙 전체가 비어 있지만 10바이트 길이의 청크 3개로 나누어져 있다. 사용자가 20바이트를 요청하는 경우, 단순한 리스트 탐색은 실패할 것이다.&lt;/p&gt;
&lt;p&gt;할당기는 이런 문제를 해결하기 위하여 빈 공간을 병합한다. 메모리 청크를 반환할 때 해제되는 청크의 주소화 바로 인접한 빈 청크의 주소를 살펴보고, 새로 해제된 빈 공간이 왼쪽의 빈 청크와 바로 인접해 있다면, 하나의 더 큰 빈 청크로 병합한다. 최종적으로 길이 30짜리 원소 하나가 존재하는 모양이 될 것이다.&lt;/p&gt;
&lt;h3 id=&quot;할당된-공간의-크기-파악&quot;&gt;할당된 공간의 크기 파악&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;free(void *ptr)&lt;/code&gt; 함수는 할당된 크기를 매개변수로 받지 않는데 어떻게 정확히 해제할 수 있을까? 이 작업을 위해 할당기는 추가 정보를 헤더 블럭에 저장한다. 헤더 블럭은 메모리에 유지되며, 보통 해제된 청크 바로 직전에 위치한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690869266755.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1115&quot; height=&quot;1121&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690869266755.u9J0bWym_Z1d81pC.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;사용자가 &lt;code&gt;ptr = malloc(20);&lt;/code&gt; 을 호출하였다고 가정하자. 헤더는 할당된 크기 (20바이트) 를 저장해야 한다. 또, 해제 속도를 향상시키기 위한 추가의 포인터, 부가적인 무결성 검사를 제공하기 위한 매직 넘버 및 기타 정보를 저장할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __header_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; magic;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;header_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;사용자가 &lt;code&gt;free(ptr);&lt;/code&gt; 호출을 하면 라이브러리는 헤더의 시작 위치를 파악하기 위해 포인터 연산을 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ptr) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    header_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;hptr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)ptr − &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;header_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;    // rest of code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;헤더를 가리키는 포인터를 얻어 내면, 매직 넘버가 기대하는 값과 일치하는지 안정성 검사 (sanity check)를 실시한다. &lt;code&gt;assert(hptr-&gt;magic == 1234567)&lt;/code&gt;
헤더의 크기와 해제된 영역의 크기를 더해 총 해제된 메모리의 크기를 계산한다.&lt;/p&gt;
&lt;p&gt;때문에, 사용자가 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;바이트의 메모리 청크를 요청하면, 운영체제는 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;_&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N + header\_size&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0044em;vertical-align:-0.31em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord&quot; style=&quot;margin-right:0.02778em;&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ze&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 크기인  청크를 찾는다.&lt;/p&gt;
&lt;h3 id=&quot;빈-공간-리스트-내장&quot;&gt;빈 공간 리스트 내장&lt;/h3&gt;
&lt;p&gt;이러한 리스트를 빈 공간에 어떻게 구현할 수 있을까?
4096 바이트 크기의 메모리 청크가 있다고 하자. 이를 빈 공간 리스트로 관리하기 위해 먼저 리스트를 초기화해야 한다. 처음에 리스트는 4096 - header size 항목 하나를 가지고 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;typedef&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; __node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;빈 공간 리스트에 첫 번째 원소를 넣는 코드를 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// mmap()이 빈 공간의 청크에 대한 포인터를 반환&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; mmap&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 4096&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PROT_READ&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;PROT_WRITE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                                MAP_ANON&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;MAP_PRIVATE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; −&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;size &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 4096&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; − &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;node_t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;head−&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;next &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690870194215.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1051&quot; height=&quot;527&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690870194215.DVZ92J9Y_20OSJE.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 때 100바이트 메모리 청크가 요청되면 어떻게 될까?
이 요청을 처리하기 위해 우선 충분한 크기의 청크를 찾는다. 이 청크는 이제 다음과 같이 &lt;strong&gt;분할&lt;/strong&gt;된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690870386570.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1033&quot; height=&quot;931&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690870386570.BG6ss1Rh_Z1Uej0f.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;헤더를 8바이트라고 가정하면 기존 하나의 빈 청크 중 108바이트를 할당하고, 할당 영역을 가리키는 포인터를 반환한다. 그리고 할당된 공간 직전 8바이트에 헤더 정보를 넣고, 남은 빈 노드를 3980(4088-108)으로 축소한다.&lt;/p&gt;
&lt;p&gt;이런 방식으로 100바이트씩 3번 할당된 힙의 모습을 살펴보자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690870648166.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1197&quot; height=&quot;1419&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690870648166.C6gEw0xQ_Z2mpCWp.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;힙의 시작 부분 324바이트가 할당 되어 있다. 할당 영역 중 가운데를 &lt;code&gt;free()&lt;/code&gt;하면 어떻게 될까?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690871223751.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1171&quot; height=&quot;1427&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690871223751.B7wdL9eO_O6zr4.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이제 빈 공간 리스트의 첫 번째 원소는 작은 빈 청크 (100바이트 크기, 리스트의 헤드가 가리킴) 이고, 두 번째 원소는 큰 빈 청크 (3764 바이트 크기) 이다. 리스트가 하나 이상의 원소를 가지게 되었고, 단편화가 발생하였다.&lt;/p&gt;
&lt;p&gt;남은 두 개의 사용중인 청크가 해제된다고 하자. &lt;strong&gt;병합&lt;/strong&gt;이 없다면 작은 단편으로 이루어진 빈 공간 리스트가 될 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690871746742.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1239&quot; height=&quot;1425&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690871746742.CyNrbyF-_2crubD.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;모든 메모리가 비어 있지만, 전부 조각나 있기 대문에 한 청크가 아니라 단편으로 이루어진 메모리처럼 보인다. 이를 해결하기 위해 &lt;em&gt;리스트를 순회&lt;/em&gt;하면서 &lt;strong&gt;인접한 청크를 병합&lt;/strong&gt; 하면 된다. 병합이 완료되면 힙은 전체 하나의 큰 청크가 된다.&lt;/p&gt;
&lt;h3 id=&quot;힙의-확장&quot;&gt;힙의 확장&lt;/h3&gt;
&lt;p&gt;힙 공간이 부족한 경우에는 어떻게 해야 할까? 우선 실패하고 &lt;code&gt;NULL&lt;/code&gt;을 반환하는 방법이 있다. 또, 대부분의 전통적인 할당기는 운영체제로부터 더 많은 메모리를 요청한다. 할당기는 힙을 확장하기 위하여 특정 시스템 콜 &lt;code&gt;sbrk&lt;/code&gt; 등을 호출한다. 그런 후 확장된 영역에서 새로운 청크를 할당한다. 이 요청을 수행하기 위해 운영체제는 빈 물리 페이지를 찾아 요청 프로세스의 주소 공간에 매핑한 후 새로운 힙의 마지막 주소를 반환한다. 이제부터 더 큰 힙을 사용할 수 있게 된다.&lt;/p&gt;
&lt;h2 id=&quot;3-기본-전략&quot;&gt;3. 기본 전략&lt;/h2&gt;
&lt;p&gt;이상적인 할당기는 속도가 빠르고 단편화를 최소로 해야 한다. 우리는 몇 가지 기본 정책에 대해 알아 보고 각각의 장단점에 대해 논의할 것이다.&lt;/p&gt;
&lt;h3 id=&quot;최적-적합-best-fit&quot;&gt;최적 적합 (Best Fit)&lt;/h3&gt;
&lt;p&gt;최적 적합 전략은 &lt;strong&gt;요청한 크기와 같거나 더 큰 빈 메모리 청크를 찾아서 가장 작은 크기의 청크를 반환&lt;/strong&gt;하는 방식이다. 이는 공간의 낭비를 줄이려는 전략이지만, 항상 전체를 검색해야 하기 때문에 성능 저하를 초래할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;최악-적합-worst-fit&quot;&gt;최악 적합 (Worst Fit)&lt;/h3&gt;
&lt;p&gt;최악 적합은 최적 적합의 반대 방식으로, &lt;strong&gt;가장 큰 빈 청크를 찾아 요청된 크기만큼 반환&lt;/strong&gt;하고 나머지 부분은 빈 공간 리스트에 계속 유지하는 방식이다. 최악 적합은 작은 청크 대신 커다란 빈 청크를 남기려고 시도하지만, 이 또한 전체를 탐색해야 하므로 비용이 높다. 또한, 단편화 문제를 해결하지 못하고 오버헤드가 커질 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;최초-적합-first-fit&quot;&gt;최초 적합 (First Fit)&lt;/h3&gt;
&lt;p&gt;최초 적합은 &lt;strong&gt;요청보다 큰 첫 번째 블록&lt;/strong&gt;을 찾아 반환하는 방식이다. 이 방식의 장점은 항상 전체를 탐색할 필요가 없어 빠르다는 것이다. 그러나 리스트의 시작부분에 작은 블록이 많이 생기는 문제가 있을 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;다음-적합-next-fit&quot;&gt;다음 적합 (Next Fit)&lt;/h3&gt;
&lt;p&gt;다음 적합은 최초 적합과 비슷하지만, 항상 리스트의 처음부터 탐색하는 대신 마지막으로 찾았던 원소를 가리키는 포인터를 유지하여 탐색을 진행하는 방식이다. 이 방법은 리스트의 첫 부분에만 단편화가 집중되는 것을 방지할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;4-다른-접근법&quot;&gt;4. 다른 접근법&lt;/h2&gt;
&lt;h3 id=&quot;segregated-lists&quot;&gt;Segregated Lists&lt;/h3&gt;
&lt;p&gt;가장 먼저 알아볼 방법은 segregated list(분리된 리스트)를 사용하는 것이다. 이는 자주 요청되는 메모리 크기가 있다면 이를 위한 별도의 메모리를 계속 유지하는 방법이다. 이렇게 하면 기기의 요청에 의해 매번 할당할 필요도 없고 매번 할당할 때마다 발생하는 단편화 문제도 줄일 수 있다.&lt;/p&gt;
&lt;p&gt;이렇게 자주 사용되는 메모리 크기를 할당하는 방법 중 slab 할당자라는 것이 있다. 이 할당자는 커널이 부팅될 때 자주 요청되는 메모리 크기를 객체 캐시로 할당한다. 그래서 해당 크기만큼 요청이 발생하면 바로바로 메모리를 할당할 수 있다. 만약 처음 만든 모든 캐시를 사용 중일 때 요청이 발생하면 일반적인 방법으로 메모리를 할당합니다. 이러한 방법을 사용하면 오버헤드가 낮아진다.&lt;/p&gt;
&lt;h3 id=&quot;buddy-allocation&quot;&gt;Buddy Allocation&lt;/h3&gt;
&lt;p&gt;합병을 단순화하기 위해 설계된 방식이 buddy allocation 방법이다. 우선 이 방법은 항상 여유 메모리가 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^N&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8413em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 크기로 존재한다고 가정한다. 메모리 요청이 있을 때 이를 만족시키는 가장 작은 블록을 찾을 때까지 반으로 쪼갠다. 이를 그림으로 보면 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 17 Free Space Management-1690873551914.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;663&quot; height=&quot;407&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2017%20Free%20Space%20Management-1690873551914.BboIMIpw_3L83e.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;처음에 64KB가 있었는데 8KB의 요청이 들어왔다. 그래서 64KB를 반으로 쪼갠 32KB를 또 반으로 쪼갠 16KB를 또 반으로 쪼갠 둘 중 하나에 현재 요청을 할당한다. 그런 뒤 이 공간을 해제할 때는 바로 &lt;strong&gt;자신과 함께 쪼개진 메모리, 즉 buddy를 찾고 사용하고 있지 않다면 바로 합병한다.&lt;/strong&gt; 이렇게 하면 합병을 쉽게 할 수 있다.&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 18 Introduction to Paging</title><link>https://ks1ksi.io/blog/ostep-18-introduction-to-paging/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-18-introduction-to-paging/</guid><description>OSTEP Paging 정리. 주소 공간과 물리 메모리를 고정 크기 페이지로 나누는 방식, page table과 주소 변환 과정을 설명한다.</description><pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;운영체제는 거의 모든 공간 관리 문제를 해결할 때 두 가지 중 하나를 사용한다.
첫 번째는 가상 메모리의 세그멘테이션 처럼 &lt;em&gt;가변 크기의 조각들&lt;/em&gt;로 분할하는 것이다. 이 해결책은 태생적 문제인 &lt;strong&gt;단편화&lt;/strong&gt;를 가지고 있다.
두 번째 방법은 공간을 &lt;em&gt;동일 크기의 조각들&lt;/em&gt;으로 분할하는 것이다. 가상 메모리에서 이를 &lt;strong&gt;페이징(paging)&lt;/strong&gt; 이라고 부른다.&lt;/p&gt;
&lt;p&gt;프로세스의 주소 공간을 몇 개의 가변 크기 논리 세그먼트 (코드, 힙, 스택) 으로 나누는 것이 아니라 고정 크기의 단위로 나눈다. 이 고정 크기 단위를 &lt;strong&gt;페이지(page)&lt;/strong&gt; 라고 부른다.
이에 상응하여 물리 메모리도 &lt;strong&gt;페이지 프레임(page frame)&lt;/strong&gt; 이라고 불리는 고정 크기 슬롯 배열이라고 생각한다. 이 프레임 각각은 하나의 가상 메모리 페이지를 저장할 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;페이지를 사용하여 어떻게 메모리를 가상화할 수 있을까?
세그멘테이션의 문제점을 해결하면서 공간과 시간 오버헤드를 최소로 해보자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-간단한-예제-및-개요&quot;&gt;1. 간단한 예제 및 개요&lt;/h2&gt;
&lt;p&gt;총 크기가 64바이트이고, 4개의 16바이트 페이지로 구성된 작은 주소 공간을 상상해보자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1690876518081.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;701&quot; height=&quot;441&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1690876518081.BQgm208x_ZarP9U.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;물리 메모리는 8개의 페이지 프레임을 가지고 있는 128 바이트라고 가정해보자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1690876562630.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;991&quot; height=&quot;707&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1690876562630.2EuFceoz_ZdToL9.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 가상 주소 공간의 페이지들은 물리 메모리 전체에 분산 배치되어 있다. 또, 운영체제가 자신을 위해 물리 메모리의 페이지 프레임을 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;페이징&lt;/strong&gt;은 이전 방식에 비해 많은 장점을 가지고 있다. 프로세스의 주소 공간 사용 방식과는 상관 없이 유연하고 효율적으로 주소 공간 개념을 지원할 수 잇다. 힙과 스택이 어디로 커지는지, 어떻게 사용되는지 알 필요가 없다.&lt;/p&gt;
&lt;p&gt;또 다른 장점은 빈 공간 관리의 단순함이다. 예를 들어 64바이트 주소 공간을 8페이지 물리 메모리에 배치하기를 원한다면, 비어 있는 4개의 페이지만 찾으면 된다. 아마 운영체제는 이를 위해 모든 비어 있는 페이지의 &lt;strong&gt;빈 공간 리스트&lt;/strong&gt;를 유지하고 리스트의 첫 네 개 페이지를 선택할 것이다.&lt;/p&gt;
&lt;p&gt;주소 공간의 각 가상 페이지에 대한 물리 메모리 위치 기록을 위해, 운영체제는 &lt;em&gt;프로세스&lt;/em&gt;마다 &lt;strong&gt;페이지 테이블&lt;/strong&gt; 이라는 자료 구조를 유지한다. 페이지 테이블의 주요 역할은 주소 공간의 가상 페이지 주소 변환 정보를 저장하는 것이다.&lt;/p&gt;
&lt;p&gt;64바이트 주소 공간을 가진 프로세스가 다음 메모리 접근을 수행한다고 가정하자&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;movl &amp;#x3C;virtual address&gt;, %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;주소 &lt;code&gt;&amp;#x3C;virtual address&gt;&lt;/code&gt;의 데이터를 &lt;code&gt;eax&lt;/code&gt; 레지스터에 탑재하는 데 집중하자. 프로세스가 생성한 가상 주소의 변환을 위해 먼저 &lt;em&gt;가상 주소&lt;/em&gt;를 &lt;strong&gt;가상 페이지 번호(virtual page number, VPN)&lt;/strong&gt; 와 페이지 내의 &lt;strong&gt;오프셋&lt;/strong&gt; 두 개의 구성 요소로 분할한다.&lt;/p&gt;
&lt;p&gt;이 예시에서는 가상 주소 공간의 크기가 64바이트이기 때문에 가상 주소는 6개의 비트가 필요하다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;64&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^6 = 64&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;6&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1690878110052.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;555&quot; height=&quot;229&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1690878110052.CqU5b__t_1JqyP7.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Va5는 가상 주소의 최상위 비트이며, Va0은 가상 주소의 최하위 비트이다. 페이지 크기가 16바이트 이기 때문에, 다음과 같이 나눌 수 있다. 64바이트 주소 공간에서 16바이트 페이지 4개 중 1개를 선택해야 하기 때문에 우리는 &lt;strong&gt;2비트 가상 페이지 번호 (VPN)&lt;/strong&gt; 이 필요하다. 나머지 비트는 페이지 내에서 우리가 원하는 바이트의 위치를 나타낸다. 이것을 오프셋이라고 부른다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;movl &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;가상 주소 21을 이진 형식으로 변환하면 010101이고, 이를 가상 페이지 번호와 오프셋으로 나눈다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1690878278570.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;535&quot; height=&quot;211&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1690878278570.CxvbxMx2_12nun9.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;가상 주소 21은 가상 페이지 01번의 0101번째 바이트가 된다.&lt;/p&gt;
&lt;p&gt;이 가상 페이지 번호를 가지고 실제 물리 프레임 어디에 저장되어 있는지 찾을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1691519804168.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1033&quot; height=&quot;823&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1691519804168.DNjCYxiF_1luOXf.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;오프셋은 동일하고, 가상 주소 01을 물리 주소 111로 변환했다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;물리 프레임 번호: (physical frame number, PFN)
물리 페이지 번호: (physical page number, PPN)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;2-페이지-테이블은-어디에-저장되는가&quot;&gt;2. 페이지 테이블은 어디에 저장되는가&lt;/h2&gt;
&lt;p&gt;페이지 테이블은 매우 커질 수 있다. 4KB 크기의 페이지를 가지는 전형적인 32비트 주소 공간을 생각해 보자. 이 가상 주소는 20비트의 VPN과 12비트의 오프셋으로 구성된다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;12&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;4096&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^{12}=4096&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;12&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;4096&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;20비트 VPN은 운영체제가 각 프로세스를 위해 관리해야 하는 변환의 개수가 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msup&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mn&gt;20&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2^{20}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개 라는 것을 의미한다. 물리 주소로의 변환 정보와 다른 필요한 정보를 저장하기 위하여 페이지 테이블 항목(page table entry, PTE)마다 4바이트가 필요하다고 가정하면, 각 페이지 테이블을 저장하기 위해 프로세스마다 4MB의 메모리가 필요하게 된다. 프로세스 100개가 실행중이라면 400MB의 메모리가 필요할 것이다.&lt;/p&gt;
&lt;p&gt;페이지 테이블이 매우 크기 때문에 현재 실행 중인 프로세스의 페이지 테이블을 MMU가 아닌 메모리에 저장할 것이다.
당분간 운영체제가 관리하는 물리 메모리에 페이지 테이블이 상주한다고 가정하자. 페이지 테이블은 가상 메모리에 저장될 수 있고 디스크에 스왑될 수도 있지만 복잡하니까 일단 무시하자.
운영체제 메모리 영역 (PFN 0)에 페이지 테이블이 존재한다고 하자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1690879405984.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;895&quot; height=&quot;609&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1690879405984.C8UU_jvh_21lEE4.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;3-페이지-테이블에는-실제로-무엇이-있는가&quot;&gt;3. 페이지 테이블에는 실제로 무엇이 있는가&lt;/h2&gt;
&lt;p&gt;페이지 테이블은 가상 주소를 물리 주소로 매핑하는데 사용되는 자료 구조이다. 가장 간단한 형태는 선형 페이지 테이블(linear page table)이다. 단순한 배열이다.
운영체제는 원하는 물리 프레임 번호(PFN)를 찾기 위하여 가상 페이지 번호(VPN)로 배열의 항목에 접근하고, 그 항목의 페이지 테이블 항목(PTE)을 검색한다.&lt;/p&gt;
&lt;p&gt;각 PTE에는 여러 비트가 존재한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1690879517425.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1161&quot; height=&quot;247&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1690879517425.BXkf7D7h_Bmf3c.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Valid bit은 특정 변환의 유효 여부를 나타내는 역할을 한다. 프로그램이 실행을 시작할 때 할당되지 않은 주소 공간이 무효로 표시되며, 프로세스가 이 무효 메모리를 접근하려고 하면 운영체제에 트랩을 발생시킨다.&lt;/p&gt;
&lt;p&gt;Protection bit은 페이지가 읽을 수 있는지, 쓸 수 있는지, 또는 실행될 수 있는지를 표시하는 역할을 한다. Protection bit가 허용하지 않는 방식으로 페이지에 접근하려고 하면 운영체제에 트랩을 생성한다.&lt;/p&gt;
&lt;p&gt;Present bit은 이 페이지가 물리 메모리에 있는지 혹은 디스크에 있는지(즉, 스왑 아웃되었는지)를 가리키는 역할을 한다.&lt;/p&gt;
&lt;p&gt;Dirty bit은 메모리에 반입된 후 페이지가 변경되었는지 여부를 나타내는 역할을 한다.&lt;/p&gt;
&lt;p&gt;Reference bit(또는 Accessed bit)는 페이지가 접근되었는지를 추적하기 위해 사용되는 역할을 한다. 이 비트는 어떤 페이지가 인기가 있는지 결정하여 메모리에 유지되어야 하는 페이지를 결정하는 데에도 유용하다. 나중에 페이지 교체 장에서 자세히 다룬다.&lt;/p&gt;
&lt;p&gt;Read/Write bit은 이 페이지에 쓰기가 허용되는지를 결정하는 역할을 한다.&lt;/p&gt;
&lt;p&gt;User/Supervisor bit은 사용자 모드 프로세스가 페이지에 액세스 할 수 있는지를 결정하는 역할을 한다.&lt;/p&gt;
&lt;p&gt;PWT, PCD, PAT, G 비트는 이 페이지에 대한 하드웨어 캐시의 동작을 결정하는 역할을 한다.&lt;/p&gt;
&lt;h2 id=&quot;4-페이징-너무-느림&quot;&gt;4. 페이징: 너무 느림&lt;/h2&gt;
&lt;p&gt;페이징은 느리다. 가상 주소를 물리 주소로 변환하는데 오래 걸린다.&lt;/p&gt;
&lt;ol&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;하드웨어는 현재 실행중인 프로세스에 대한 page table 위치를 알아야 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 가상 주소에서 vpn만 추출한다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;VPN &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (VirtualAddress &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; VPN_MASK) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; SHIFT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// Page table 주소에 vpn 값으로 현재 접근하는 프로세스의 PTE 찾는다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;PTEAddr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PageTableBaseRegister &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (VPN &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(PTE))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// 가상 주소에서 offset만 추출한다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;offset &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; VirtualAddress &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; OFFSET_MASK&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// offset과 PFN 값으로 실제 메모리 주소를 얻는다.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;PhysAddr &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (PFN &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; SHIFT) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; offset&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이러한 순서로 실제 메모리 주소를 얻는데 굉장히 복잡하다.
모든 메모리 참조에 대해 먼저 페이지 테이블에서 변환 정보를 반입해야 하기 때문에 반드시 한 번의 추가적인 메모리 참조가 필요하고, 이는 프로세스를 2배 이상 느려지게 한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1690880418810.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;815&quot; height=&quot;461&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1690880418810.CtiJFthj_Z1lwhT8.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;5-메모리-트레이스&quot;&gt;5. 메모리 트레이스&lt;/h2&gt;
&lt;p&gt;간단한 메모리 액세스 예시를 통해 페이징을 사용했을 때 발생하는 모든 메모리 접근을 살펴보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; array[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    array[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;gcc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; array&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; array.c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; -Wall&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt; -O&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;./array&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x1024&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; movl $0x0, (%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;edi&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;,%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x1028&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; incl %&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x102c&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cmpl $0x03e8,%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x1030&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; jne&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0x1024&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;0x1024 movl $0x0, (%edi,%eax,4)&lt;/code&gt;: 이 명령은 0x0 (즉, 0)을 메모리 위치 (%edi,%eax,4)로 이동시키라는 명령입니다. 여기서 (%edi,%eax,4)는 주소 계산 방식을 나타내는데, 이는 edi 레지스터의 값과 eax 레지스터의 값에 4를 곱한 것을 더한 위치를 가리킵니다. 이 경우, 이것은 배열의 i번째 위치를 가리키는 포인터라고 볼 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;0x1028 incl %eax&lt;/code&gt;: 이 명령은 eax 레지스터의 값을 1 증가시키는 명령입니다. 이 명령은 for 루프에서 i를 증가시키는 것과 같은 역할을 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;0x102c cmpl $0x03e8,%eax&lt;/code&gt;: 이 명령은 eax 레지스터의 값과 0x03e8 (즉, 1000)을 비교하는 명령입니다. 이 명령은 for 루프의 종료 조건 (즉, i &amp;#x3C; 1000)과 동일합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;0x1030 jne 0x1024&lt;/code&gt;: 이 명령은 “jump if not equal”의 줄임말로, 만약 eax 레지스터의 값과 1000이 같지 않다면 (즉, i가 1000보다 작다면) 주소 0x1024 (즉, 첫 번째 명령어)로 점프하라는 명령입니다. 이것은 for 루프의 내용을 반복하기 위한 것입니다. 만약 i가 1000이라면, 이 명령은 점프하지 않고 계속 진행하여 루프를 종료합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 예시를 직접 수행해보자.&lt;/p&gt;
&lt;p&gt;프로세스의 가상 주소는 64KB이고 page 크기는 1KB라고 가정하자. 수행하기 위해 알아야 하는 것은 page table의 내용과 실제 메모리의 주소이다.
VPN 1페이지에 코드에 대한 정보가 있고, 이것은 PFN 4로 연결된다고 가정한다. array 의 VPN은 39, 40, 41, 42이고 각각의 PFN은 7, 8, 9, 10이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 18 Introduction to Paging-1691519842728.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1471&quot; height=&quot;1369&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2018%20Introduction%20to%20Paging-1691519842728.CDTtGLzI_ZTbWM2.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;코드가 실행될 때 명령어 fetch는 두 개의 메모리 참조를 생성한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;page table에 대한 메모리 참조&lt;/li&gt;
&lt;li&gt;명령어에 대한 참조&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;5번의 반복 메모리 접근을 나타낸 그림이다. 한 번의 반복을 위해 10번의 메모리 접근이 발생하는 것이다. 이를 최적화하는 방법은 없을까?&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 19 Translation Lookaside Buffer</title><link>https://ks1ksi.io/blog/ostep-19-translation-lookaside-buffer/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-19-translation-lookaside-buffer/</guid><description>OSTEP TLB 정리. 주소 변환 캐시인 TLB의 동작, hit와 miss, context switch에서의 처리와 성능 영향을 요약한다.</description><pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;앞서 본 것처럼 페이징은 상당한 성능 저하를 가져올 수 있다. 주소 변환 속도를 어떻게 향상할까?&lt;/p&gt;
&lt;p&gt;하드웨어의 도움을 받아야 한다. 주소 변환을 빠르게 하기 위해서 우리는 &lt;strong&gt;변환 색인 버퍼 (Translation Lookaside Buffer, TLB)&lt;/strong&gt; 라는 것을 도입한다. 칩의 메모리 관리 유닛 MMU의 일부이다. 자주 참조되는 가상 주소 -&gt; 실제 주소 변환 정보를 저장하는 하드웨어 캐시이다. &lt;strong&gt;주소 변환 캐시&lt;/strong&gt;가 좀 더 정확한 명칭이라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;가상 메모리 참조 시, 하드웨어는 먼저 TLB에 원하는 변환 정보가 있는지 확인하고, 만약 있다면 페이지 테이블을 통하지 않고 캐시를 통해 빠르게 주소를 변환한다.&lt;/p&gt;
&lt;h2 id=&quot;1-tlb의-기본-알고리즘&quot;&gt;1. TLB의 기본 알고리즘&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 19 Translation Lookaside Buffer-1690881642585.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;881&quot; height=&quot;539&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2019%20Translation%20Lookaside%20Buffer-1690881642585.C0DwQ5CF_Ztfol3.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;먼저 가상 주소에서 가상 페이지 번호를 추출하고, 해당 VPN의 TLB 존재 여부를 검사한다.
만약 존재하면 TLB 히트이다. 여기서 PFN을 추출할 수 있다. 해당 페이지에 대한 접근 권한 검사가 성공하면, 그 정보를 원래 가상 주소의 오프셋과 합쳐서 원하는 물리 주소를 구성하고, 메모리에 접근할 수 있다.&lt;/p&gt;
&lt;p&gt;TLB에 변환 정보가 존재하지 않는다면 (TLB 미스) 할 일이 많아진다. 페이지 테이블에 접근하고, 참조가 유효하고 접근 가능하다면 이를 TLB로 불러들인다. TLB가 갱신되면 하드웨어는 명령어를 재실행한다. 이번에는 TLB에 존재하므로 메모리 참조가 빠르게 처리된다.&lt;/p&gt;
&lt;p&gt;메모리 접근은 다른 CPU 연산에 비해 매우 시간이 오래 걸리는 작업이다. TLB 미스가 많이 발생할수록 메모리 접근 횟수가 많아진다. TLB 미스가 발생하는 경우를 최대한 피해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;2-예제-배열-접근&quot;&gt;2. 예제: 배열 접근&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 19 Translation Lookaside Buffer-1690881925789.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;659&quot; height=&quot;729&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2019%20Translation%20Lookaside%20Buffer-1690881925789.C9R0N7gr_ZCj84U.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 배열이 구성되어 있을 때, &lt;code&gt;a[0], a[3], a[7]&lt;/code&gt;에 접근할 때 빼고 모두 TLB 히트이다. 이 예제에서는 1 page가 16 byte의 크기를 가지는데 만약 페이지 크기가 더 커진다면, TLB 히트 확률이 더 올라갈 것이다.&lt;/p&gt;
&lt;p&gt;일반적인 경우 페이지는 4KB이다. 예제처럼 정수 배열을 연속적으로 접근하는 경우 한 번의 미스만 발생할 것이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;시간 지역성(Temporal Locality): 이는 프로그램이 한 번 접근한 메모리 위치를 가까운 미래에 다시 접근할 가능성이 높다는 개념입니다. 예를 들어, 루프에서 반복적으로 사용되는 변수나 배열은 이러한 지역성의 예입니다. 시간 지역성을 활용하면, 한 번 접근한 데이터를 캐시에 저장하고, 미래의 접근에서는 빠르게 캐시에서 데이터를 가져올 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;공간 지역성(Spatial Locality): 이는 프로그램이 한 번 접근한 메모리 위치 주변을 가까운 미래에 접근할 가능성이 높다는 개념입니다. 예를 들어, 순차적으로 실행되는 명령어나 연속적인 메모리 위치에 저장된 배열의 원소들은 이러한 지역성의 예입니다. 공간 지역성을 활용하면, 데이터를 캐시에 블록 단위로 가져오고, 인접한 메모리 위치에 대한 접근에서는 캐시에서 빠르게 데이터를 가져올 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;3-tlb-미스는-누가-처리할까&quot;&gt;3. TLB 미스는 누가 처리할까&lt;/h2&gt;
&lt;p&gt;하드웨어에서 처리하는 방법(CISC)과 소프트웨어에서 처리하는 방법(RICS) 두 가지가 있다.&lt;/p&gt;
&lt;p&gt;하드웨어에서 처리하는 경우, 하드웨어가 페이지 테이블에 대한 명확한 정보를 가지고 있어야 한다. 이를 위해서 페이지 테이블 레지스터를 두고, 이 레지스터로 TLB를 갱신했다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 19 Translation Lookaside Buffer-1690882580633.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;925&quot; height=&quot;335&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2019%20Translation%20Lookaside%20Buffer-1690882580633.DxbbQOn3_9qAT0.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;TLB에서 주소 찾는 것이 실패한 경우, 하드웨어는 예외 시그널을 발생시킨다. 시그널을 받은 운영체제는 잠시 실행을 중단하고 커널 모드로 변경한 후 TLB 미스를 처리하는 트랩 핸들러를 실행시킨다. 이 핸들러는 페이지 테이블을 검색하여 변환 정보를 찾고, TLB를 갱신한 후 리턴한다.&lt;/p&gt;
&lt;p&gt;TLB를 소프트웨어로 관리하면 하드웨어 변경 없이 테이블 구조를 유연하게 변경할 수 있고, 하드웨어가 처리할 일이 없어서 더 단순하다.&lt;/p&gt;
&lt;h2 id=&quot;4-tlb의-구성-무엇이-있나&quot;&gt;4. TLB의 구성: 무엇이 있나?&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;TLB &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; PFN &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; 다른 비트&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;변환 정보 저장 위치에 제약이 없도록, 각 항목마다 VPN, PFN이 존재한다. TLB는 완전 연관 캐시이다.
다른 비트들은 무엇을 할까?
TLB는 일반적으로 valid bit를 가지고 있다. 이 비트는 특정 항목이 유효한 변환 정보를 가지고 있는지 여부를 나타낸다.
protection bit는 읽기, 쓰기, 실행 등 권한을 관리한다.
그 외에도 주소 공간 식별자, 더티 비트 등 여러 비트가 존재한다.&lt;/p&gt;
&lt;h2 id=&quot;5-tlb의-문제-문맥-교환&quot;&gt;5. TLB의 문제: 문맥 교환&lt;/h2&gt;
&lt;p&gt;TLB에 탑재된 가상 주소와 실제 주소 간의 변환 정보는 그것을 탑재시킨 프로세스에서만 유효하다. 다른 프로세스로 context switch가 일어나면 어떻게 해야 할까?&lt;/p&gt;
&lt;p&gt;첫 번째 방법은 문맥 교환을 수행할 때 다음 프로세스가 실행되기 전 TLB를 비우는 것이다.
문맥 교환이 일어날 때마다 TLB를 비우면 잘못 작동하는 것을 막을 수 있겠지만 TLB 미스가 많이 발생할 것이다.&lt;/p&gt;
&lt;p&gt;이 부담을 개선하기 위해 몇몇 시스템에서는 문맥 교환이 발생하더라도 TLB의 내용을 보존할 수 있는 하드웨어 기능을 추가하였다. TLB 내에 주소 공간 식별자 (Address Space Identifier) 필드를 추가하는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 19 Translation Lookaside Buffer-1690883218200.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;595&quot; height=&quot;315&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2019%20Translation%20Lookaside%20Buffer-1690883218200.DdRMSOuY_Z1yrzos.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이를 통해 프로세스 별로 TLB 변환 정보를 구분할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;6-이슈-교체-정책&quot;&gt;6. 이슈: 교체 정책&lt;/h2&gt;
&lt;p&gt;모든 캐시가 그러하듯, TLB에서도 캐시 교체 정책이 매우 중요하다. TLB에 새로운 항목을 탑재할 때 어떤 항목을 교체 대상으로 선정해야 할까?&lt;/p&gt;
&lt;p&gt;이 내용은 디스크, 메모리 간의 페이지 스왑 부분에서 상세히 다루고, 지금은 몇 개의 일반적인 정책들만 요약하도록 하자.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;최저 사용 빈도(least-recently-used, LRU)&lt;/strong&gt; 가 가장 흔한 방법이다. 사용되지 않은 오래된 항목일수록 앞으로도 사용될 가능성이 적으며, 교체 대상으로 적합할 것이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;랜덤&lt;/strong&gt;하게 고르는 방법도 일반적이다. 이는 구현이 간단하고 예외 상황의 발생을 피할 수 있다.&lt;/p&gt;
&lt;p&gt;LRU같은 합리적인 정책은 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 변환 정보를 저장할 수 있는 TLB가 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n+1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 페이지들에 대해 반복문을 수행하는 프로그램에서 최악의 TLB 미스를 생성할수도 있다. 랜덤하게 교체하는 경우 이런 일이 (거의) 없을 것이다.&lt;/p&gt;
&lt;h2 id=&quot;7-실제-tlb&quot;&gt;7. 실제 TLB&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 19 Translation Lookaside Buffer-1690883505312.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1205&quot; height=&quot;241&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2019%20Translation%20Lookaside%20Buffer-1690883505312.DSTCmeJN_1mm0KA.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;MIPS R4000는 32비트 주소 공간에서 4KB 페이지를 지원한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;가상 페이지 번호(VPN): 19비트로 할당되며, 주소 공간의 절반은 사용자 주소 공간으로 할당된다.&lt;/li&gt;
&lt;li&gt;물리 프레임 번호(PFN): 24비트로 할당되며, 최대 64GB의 메모리(2^24 개의 4KB 페이지들) 지원이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TLB 항목에는 또한 몇 가지 중요한 비트들이 포함되어 있습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;전역 비트(G): 이 비트는 프로세스 간에 공유되는 페이지들을 위해 사용된다. 전역 비트가 설정되면 ASID(Address Space Identifier)는 무시됩니다.&lt;/li&gt;
&lt;li&gt;ASID 필드: 8비트로, 운영체제는 이 필드를 통해 주소 공간을 구분한다.&lt;/li&gt;
&lt;li&gt;일관성 비트(C): 이 비트는 페이지가 하드웨어에 어떻게 캐시되어 있는지 판별하는 데 사용된다.&lt;/li&gt;
&lt;li&gt;더티 비트(D): 페이지가 갱신되면 세팅된다.&lt;/li&gt;
&lt;li&gt;유효 비트(V): 항목에 유효한 변환 정보가 존재하는지 나타낸다.&lt;/li&gt;
&lt;li&gt;페이지 마스크 필드: 여러 개의 페이지 크기를 지원할 때 사용된다. 그림에는 나타나있지 않다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 14 Memory API</title><link>https://ks1ksi.io/blog/ostep-14-memory-api/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-14-memory-api/</guid><description>OSTEP Memory API 정리. stack과 heap, malloc과 free, 동적 메모리 할당의 메타데이터와 흔한 메모리 오류를 설명한다.</description><pubDate>Mon, 17 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;1-메모리-공간의-종류&quot;&gt;1. 메모리 공간의 종류&lt;/h2&gt;
&lt;p&gt;C 프로그램이 실행되면, 두 가지 유형의 메모리 공간이 할당된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;stack 메모리
&lt;ul&gt;
&lt;li&gt;컴파일러에 의해 암묵적으로 할당과 반환이 이루어짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 스택에 int 형을 선언&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;    // rest of code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;heap 메모리
&lt;ul&gt;
&lt;li&gt;모든 할당과 반환이 프로그래머에 의해 명시적으로 처리됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;malloc(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;	// rest of code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;한 행에 스택과 힙 할당이 모두 발생한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;컴파일러가 포인터 변수의 선언 &lt;code&gt;int *x&lt;/code&gt; 를 만나면 정수 포인터를 위한 공간을 할당해야 한다.&lt;/li&gt;
&lt;li&gt;프로그램이 &lt;code&gt;malloc()&lt;/code&gt; 을 호출하여 정수를 위한 공간을 힙으로부터 요구한다.&lt;/li&gt;
&lt;li&gt;성공한 경우 그 정수의 주소를 반환, 실패한 경우 &lt;code&gt;NULL&lt;/code&gt;을 반환&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;2-malloc-함수&quot;&gt;2. &lt;code&gt;malloc()&lt;/code&gt; 함수&lt;/h2&gt;
&lt;p&gt;힙에 요청할 공간의 크기를 넘겨 주면, 성공했을 경우 새로 할당된 공간에 대한 포인터를 사용자에게 반환하고, 실패했을 경우 &lt;code&gt;NULL&lt;/code&gt;을 반환하는 간단한 함수.
&lt;code&gt;malloc()&lt;/code&gt; 함수를 사용하기 위해 &lt;code&gt;stdlib.h&lt;/code&gt;를 include 해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt; 함수의 인자는 &lt;code&gt;size_t&lt;/code&gt; 타입이고 이 변수는 필요 공간의 크기를 &lt;strong&gt;바이트&lt;/strong&gt; 단위로 표시한 것이다. 숫자를 직접 쓰지 않고 &lt;code&gt;sizeof()&lt;/code&gt; 함수를 통해 쓴다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt; 함수는 &lt;code&gt;void&lt;/code&gt; 타입에 대한 포인터를 반환한다. 주소만 넘겨주고 해당 주소에 어떤 타입의 자료를 저장할 지는 프로그래머가 결정하게 하는 전형적인 C 프로그래밍 방식이다.&lt;/p&gt;
&lt;h2 id=&quot;3-free-함수&quot;&gt;3. &lt;code&gt;free()&lt;/code&gt; 함수&lt;/h2&gt;
&lt;p&gt;더 이상 사용되지 않는 힙 메모리를 해제하기 위해 프로그래머는 &lt;code&gt;free()&lt;/code&gt;를 호출한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; sizeof&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// rest of code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;free&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(x);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;한개의 인자 &lt;strong&gt;&lt;code&gt;malloc()&lt;/code&gt;에 의해 반환된 포인터&lt;/strong&gt;를 받는다. &lt;strong&gt;할당된 영역의 크기는 전달되지 않는다.&lt;/strong&gt; 그 크기는 메모리 할당 라이브러리가 알고 있어야 한다. 이 크기를 어떻게 알 수 있을까?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt;이나 &lt;code&gt;calloc()&lt;/code&gt; 함수를 호출하여 동적 메모리를 할당하면, 실제로 요청된 크기보다 약간 더 많은 메모리가 할당됩니다. 이 추가된 메모리 영역에는 메타데이터 정보가 저장되며, 여기에는 할당된 메모리 블록의 크기, 사용 여부 등의 정보가 포함됩니다.
이러한 메타데이터는 메모리 블록이 해제되어야 할 때 &lt;code&gt;free()&lt;/code&gt; 함수가 몇 바이트의 메모리를 해제해야 하는지 알 수 있게 해줍니다. 일반적으로 이 메타데이터는 할당된 메모리 블록 바로 앞에 위치하게 됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 14 Memory API-1689612989858.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;696&quot; height=&quot;340&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2014%20Memory%20API-1689612989858.CpQTdu6q_ZGPlTr.webp&quot; &gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; malloc_chunk {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;  INTERNAL_SIZE_T      prev_size;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;  /* Size of previous chunk (if free).  */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;  INTERNAL_SIZE_T      size;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;       /* Size in bytes, including overhead. */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;  struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; malloc_chunk&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fd;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;         /* double links -- used only if free. */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;  struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; malloc_chunk&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; bk;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;  /* Only used for large blocks: pointer to next larger size.  */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;  struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; malloc_chunk&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fd_nextsize;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; /* double links -- used only if free. */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;  struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; malloc_chunk&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; bk_nextsize;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;이 코드는 C 프로그래밍 언어의 &lt;code&gt;malloc()&lt;/code&gt; 함수에서 메모리 할당에 사용되는 데이터 구조인 &lt;code&gt;malloc_chunk&lt;/code&gt;의 정의입니다. &lt;code&gt;malloc_chunk&lt;/code&gt;는 메모리 블록의 메타데이터를 저장하는 구조체로, 각 메모리 블록의 상태와 관련된 정보를 포함합니다. 구체적으로 다음과 같은 정보들이 저장됩니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prev_size&lt;/code&gt;: 이 필드는 현재 블록이 해제된 상태라면 바로 앞에 위치한 블록의 크기를 저장합니다. 현재 블록이 사용 중이면 이 필드는 무시됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;size&lt;/code&gt;: 이 필드는 현재 메모리 블록의 전체 크기를 저장합니다. 이 크기에는 메타데이터의 크기도 포함되며, 또한 블록의 할당 상태에 대한 정보도 함께 저장됩니다. (보통 마지막 비트를 사용하여 블록이 사용 중인지 아닌지를 표시합니다)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fd&lt;/code&gt;와 &lt;code&gt;bk&lt;/code&gt;: 이들 필드는 더블 링크드 리스트의 포워드(&lt;code&gt;fd&lt;/code&gt;) 노드와 백워드(&lt;code&gt;bk&lt;/code&gt;) 노드를 가리킵니다. 이들은 &lt;code&gt;malloc_chunk&lt;/code&gt;가 메모리의 해제 리스트(free list)에 위치한 경우에만 사용됩니다. 이 리스트는 현재 사용되지 않고 해제된 상태의 메모리 블록들을 관리합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fd_nextsize&lt;/code&gt;와 &lt;code&gt;bk_nextsize&lt;/code&gt;: 이들 필드는 큰 메모리 블록의 경우에만 사용되며, 다음 크기의 더 큰 메모리 블록을 가리킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt; 함수가 호출되면, 메모리 블록 전체가 할당되고 메타데이터 영역에는 해당 블록의 크기 정보 등이 저장됩니다. 그런 다음 함수는 사용자 데이터가 저장될 영역의 시작 주소, 즉 메타데이터 바로 다음의 주소를 반환합니다.
이렇게 하면 &lt;code&gt;free()&lt;/code&gt; 함수는 메모리 블록을 해제할 때 해당 블록의 크기를 알 수 있습니다. &lt;code&gt;free()&lt;/code&gt; 함수가 호출되면, 해당 메모리 주소를 받아들이고 메타데이터 영역으로 “뒤로 걸어가” 메모리 블록의 크기를 확인한 후 그 크기만큼의 메모리를 해제합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;4-흔한-오류&quot;&gt;4. 흔한 오류&lt;/h2&gt;
&lt;h3 id=&quot;메모리-할당-잊어버리기&quot;&gt;메모리 할당 잊어버리기&lt;/h3&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;src &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;hello&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;dst;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;strcpy&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(dst&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; src);&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 할당이 되어 있지 않음. segfault.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Segmentation Fault는 프로그램이 자신이 접근 권한이 없는 메모리 영역에 접근하려고 시도할 때 발생하는 오류. 자세한 내용은 &lt;a href=&quot;https://ks1ksi.io/blog/ostep-16-segmentation/&quot;&gt;OSTEP 16 Segmentation&lt;/a&gt;에서 알아보자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;메모리를-부족하게-할당받기&quot;&gt;메모리를 부족하게 할당받기&lt;/h3&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;src &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;hello&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;dst &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;strlen&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(src));&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 부족하게 할당&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;strcpy&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(dst&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; src);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Buffer Overflow&lt;/strong&gt;.
구현 방식에 따라 정상적으로 작동할수도 있다.
프로그램이 한 번 올바르게 실행된다고 하더라고, 프로그램이 올바르다는 것을 의미하지는 않는다.&lt;/p&gt;
&lt;p&gt;다음과 같이 작성해야 올바른 코드다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;src &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;hello&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;dst &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; malloc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;strlen&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(src) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (dst &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    strcpy(dst&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; src)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;할당받은-메모리-초기화하지-않기&quot;&gt;할당받은 메모리 초기화하지 않기&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt;을 호출해서 새로 할당받은 데이터 타입에 값을 넣어야 하는데 그냥 읽으면? &lt;strong&gt;힙으로부터 알 수 없는 값을 읽는 일(uninitialized read)이 생긴다.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;메모리-해제하지-않기&quot;&gt;메모리 해제하지 않기&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;memory leak.&lt;/strong&gt;
장시간 실행되는 응용 프로그램이나 운영체제 자체와 같은 시스템 프로그램에서 큰 문제다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Garbage Collector&lt;/strong&gt;가 있어도 이 문제를 피해갈 수 없다. 메모리 청크에 대한 참조가 존재하면, 어느 GC도 그 청크를 해제하지 않을 것이기 때문이다. 따라서 현대적인 언어에서도 메모리 누수는 여전히 문제가 된다.&lt;/p&gt;
&lt;p&gt;한 바이트라도 명시적으로 할당받았으면 해제하는 습관을 들이도록 하자.&lt;/p&gt;
&lt;h3 id=&quot;메모리-사용이-끝나기-전에-메모리-해제하기&quot;&gt;메모리 사용이 끝나기 전에 메모리 해제하기&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;dangling pointer.&lt;/strong&gt;
심각한 실수이다. 차후 그 포인터를 사용하면 프로그램을 크래시 시키거나 유효 메모리 영역을 덮어쓸 수 있다. &lt;code&gt;free()&lt;/code&gt;를 호출하고 다른 용도로 &lt;code&gt;malloc()&lt;/code&gt;을 호출하는 경우, 잘못 해제된 메모리를 재사용하게 된다.&lt;/p&gt;
&lt;h3 id=&quot;반복적으로-메모리-해제하기&quot;&gt;반복적으로 메모리 해제하기&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;double free.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; malloc_chunk&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fd;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;         /* double links -- used only if free. */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; malloc_chunk&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; bk;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;chunk의 메타데이터 일부이다. 더블 링크드리스트를 만드는 데 쓰인다.
이 링크드리스트는 &lt;code&gt;free()&lt;/code&gt;된 청크들을 모아놓는 리스트이다. 다음에 같은 사이즈의 할당이 될 경우 빠르게 재할당 할 수 있도록 한다.
double free가 일어나면 이 링크드리스트에 &lt;strong&gt;같은 메모리 주소가 두 번&lt;/strong&gt; 들어간다.
프로그래머의 의도와는 다르게, 변수 여러 개가 같은 메모리 공간을 점유하게 되어 버그가 발생한다.&lt;/p&gt;
&lt;h3 id=&quot;free-잘못-호출하기&quot;&gt;&lt;code&gt;free()&lt;/code&gt; 잘못 호출하기&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt; 받은 포인터만 전달해야 한다. &lt;strong&gt;invalid frees&lt;/strong&gt;는 매우 위험하다(undefined behavior).&lt;/p&gt;
&lt;h2 id=&quot;5-운영체제의-지원&quot;&gt;5. 운영체제의 지원&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;malloc()&lt;/code&gt;과 &lt;code&gt;free()&lt;/code&gt;는 시스템 콜이 아니라 라이브러리 함수이다. &lt;code&gt;malloc()&lt;/code&gt;라이브러리는 시스템에게 더 많은 메모리를 요구하고 반환하는 시스템 콜(&lt;code&gt;brk&lt;/code&gt;, &lt;code&gt;sbrk&lt;/code&gt;)을 기반으로 구축된다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;brk&lt;/code&gt;와 &lt;code&gt;sbrk&lt;/code&gt;는 운영체제가 제공하는 시스템 호출입니다. 이들은 프로세스의 힙 영역에서 사용할 수 있는 메모리의 양을 관리합니다.
&lt;code&gt;brk&lt;/code&gt;는 프로그램의 힙 끝, 즉 “break” 위치를 설정하는 시스템 호출입니다. &lt;code&gt;brk&lt;/code&gt;에 주어진 인자는 힙 영역의 새로운 끝을 지정합니다. 이 값이 현재 break보다 크다면, 운영체제는 힙 영역을 확장하고, 이 값이 현재 break보다 작다면, 운영체제는 힙 영역을 축소합니다. 다시 말해, &lt;code&gt;brk&lt;/code&gt;는 운영체제에게 프로세스의 힙 영역 크기를 조정하도록 요청하는 함수입니다.
&lt;code&gt;brk&lt;/code&gt;와 비슷하게, &lt;code&gt;sbrk&lt;/code&gt;도 힙 영역을 관리하는 시스템 호출입니다. 하지만 &lt;code&gt;sbrk&lt;/code&gt;는 새로운 break 위치를 직접 지정하는 대신, 현재 break 위치에서의 상대적인 변화를 지정합니다. 즉, &lt;code&gt;sbrk&lt;/code&gt;에 주어진 인자는 현재 break 위치에 더해질 크기를 나타냅니다.
이들 시스템 호출은 메모리 할당 라이브러리(예를 들어, &lt;code&gt;malloc&lt;/code&gt;와 &lt;code&gt;free&lt;/code&gt;)가 운영체제로부터 메모리를 요청하거나 반환할 때 사용됩니다. 따라서 일반적으로는 프로그래머가 직접 사용하는 것이 아니라, 메모리 관리 라이브러리가 내부적으로 사용합니다.
&lt;code&gt;brk&lt;/code&gt;와 &lt;code&gt;sbrk&lt;/code&gt;를 프로그래머가 직접 사용하려고 하면, 메모리 할당 라이브러리의 내부 상태와 충돌이 발생할 수 있습니다. 이는 메모리 문제를 일으킬 수 있으므로, 프로그래머는 대신 &lt;code&gt;malloc&lt;/code&gt;과 &lt;code&gt;free&lt;/code&gt;와 같은 라이브러리 함수를 사용하여 메모리를 할당하고 해제해야 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;mmap()&lt;/code&gt; 함수를 통해 운영체제로부터 메모리를 얻는 방법도 있다.
특정 파일과 연결되지 않은 anonymous 메모리 영역을 생성한다. swap space에 연결되며, 힙과 유사하게 취급되고 관리된다.&lt;/p&gt;
&lt;h2 id=&quot;6-기타-함수들&quot;&gt;6. 기타 함수들&lt;/h2&gt;
&lt;h3 id=&quot;calloc&quot;&gt;&lt;code&gt;calloc()&lt;/code&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;메모리를 할당하고 이를 0으로 초기화하여 반환하는 함수&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;realloc&quot;&gt;&lt;code&gt;realloc()&lt;/code&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;이미 할당된 공간에 추가적인 공간이 필요할 때 유용한 함수&lt;/li&gt;
&lt;li&gt;더 큰 새로운 영역을 확보하고, 이전 영역의 내용을 복사한 후에 새로운 영역에 대한 포인터를 반환한다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 15 Address Translation</title><link>https://ks1ksi.io/blog/ostep-15-address-translation/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-15-address-translation/</guid><description>OSTEP Address Translation 정리. 가상 주소를 물리 주소로 바꾸는 base/bounds 방식과 제한적 직접 실행의 메모리 보호를 요약한다.</description><pubDate>Mon, 17 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;CPU 가상화 부분에서 &lt;strong&gt;제한적 직접 실행 (LDE)&lt;/strong&gt; 기법에 대해 배웠다. &lt;a href=&quot;https://ks1ksi.io/blog/ostep-06-direct-execution/&quot;&gt;OSTEP 06 Direct Execution&lt;/a&gt;
메모리 가상화에서도 비슷한 전략을 추구한다. 가상화를 제공하는 동시에 효율성과 제어 모두를 추구한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;효율성&lt;/strong&gt;을 높이기 위해 하드웨어 자원을 활용한다. 몇 개의 레지스터 활용부터 TLB, 페이지 테이블 등 점점 복잡한 하드웨어를 사용한다.
&lt;strong&gt;제어&lt;/strong&gt;는 프로그램이 자기 자신의 메모리 이외에는 접근하지 못하도록 운영체제가 보장한다는 것.
유연성 측면에서, 프로그래머가 원하는 대로 주소 공간을 사용하고, 프로그래밍하기 쉬운 시스템을 만들기 원헌다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;핵심 질문: 어떻게 효율적이고 유연하게 메모리를 가상화 할 수 있을까?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;우리가 다룰 기법은 &lt;strong&gt;(하드웨어 기반) 주소 변환&lt;/strong&gt;이다. 이 기술은 제한적 직접 실행 방식에 부가적으로 사용되는 기능이라고 생각할 수 있다. 주소 변환을 통해 하드웨어는 명령어 반입, 탑재, 저장 등의 &lt;strong&gt;가상&lt;/strong&gt; 주소를 정보가 실제 존재하는 &lt;strong&gt;물리&lt;/strong&gt; 주소로 변환한다.&lt;/p&gt;
&lt;p&gt;하드웨어가 변환을 가속화하는데 도움을 주지만 그것만으로는 모자라다. 정확한 변환이 일어날 수 있도록 운영체제가 관여해야 한다.&lt;/p&gt;
&lt;p&gt;운영체제는 &lt;strong&gt;메모리의 빈 공간과 사용중인 공간을 항상 알고 있어야 하고, 메모리 사용을 제어하고 관리한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;이 모든 작업의 목표는 바로 &lt;em&gt;&lt;strong&gt;프로그램이 자신의 전용 메모리를 소유하고 있고, 그 안에 자신의 코드와 데이터가 있다는 환상&lt;/strong&gt;&lt;/em&gt;을 만드는 것이다.&lt;/p&gt;
&lt;h2 id=&quot;1-가정&quot;&gt;1. 가정&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;주소 공간은 물리 메모리에 연속적으로 배치되어야 한다.&lt;/li&gt;
&lt;li&gt;주소 공간은 물리 메모리 크기보다 작다.&lt;/li&gt;
&lt;li&gt;각 주소 공간의 크기는 같다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;2-사례&quot;&gt;2. 사례&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // 우리가 관심있는 코드&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;128&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;: movl &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0x0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(\%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;ebx&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;), \%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;;	# 0+ebx를 eax에 저장&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;132&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;: addl \$0x03, \%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;;		# eax레지스터에 3을 더한다&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;135&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;: movl \%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0x0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(\%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;ebx&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;;	# eax를 메모리에 다시 저장&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;x&lt;/code&gt;의 주소가 레지스터 &lt;code&gt;ebx&lt;/code&gt;에 저장되어 있다고 가정하고, 이 주소에 저장되어 있는 값을 범용 레지스터 &lt;code&gt;eax&lt;/code&gt;에 넣는다. 다음 명령은 &lt;code&gt;eax&lt;/code&gt;에 3을 더하고,  마지막 명령은 &lt;code&gt;eax&lt;/code&gt;의 값을 같은 위치의 메모리에 저장한다.&lt;/p&gt;
&lt;p&gt;프로그램 코드는 주소 128에 위치하고 변수 &lt;code&gt;x&lt;/code&gt;의 값은 주소 15KB (아래 쪽 스택)에 위치한다.
이 프로그램이 실행되면 다음과 같은 메모리 접근이 일어난다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;주소 128의 명령어를 반입&lt;/li&gt;
&lt;li&gt;이 명령어 실행 (주소 15 KB에서 탑재)&lt;/li&gt;
&lt;li&gt;주소 132의 명령어를 반입&lt;/li&gt;
&lt;li&gt;이 명령어 실행 (메모리 참조 없음)&lt;/li&gt;
&lt;li&gt;주소 135의 명령어를 반입&lt;/li&gt;
&lt;li&gt;이 명령어 실행 (15 KB에 저장)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 15 Address Translation-1689616534903.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1368&quot; height=&quot;1522&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2015%20Address%20Translation-1689616534903.j_ZEorI9_X6mr3.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 프로세스 관점에서 메모리 주소가 0부터 시작하도록 가상 환경을 제공해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 15 Address Translation-1689616860906.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1330&quot; height=&quot;828&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2015%20Address%20Translation-1689616860906.CVfdteyd_2kIvri.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;실제로는 0부터 시작하지 않더라도 프로그램이 0부터 시작하는 것 처럼 작동해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;3-동적-하드웨어-기반-재배치&quot;&gt;3. 동적 (하드웨어-기반) 재배치&lt;/h2&gt;
&lt;h3 id=&quot;base-and-bound-dynamic-relocation&quot;&gt;Base And Bound (dynamic relocation)&lt;/h3&gt;
&lt;p&gt;각 CPU마다 2개의 하드웨어 레지스터가 필요하다.
하나는 &lt;strong&gt;베이스 레지스터&lt;/strong&gt;로, &lt;strong&gt;프로세스의 주소 공간이 시작하는 물리 메모리 주소&lt;/strong&gt;를 저장한다.
다른 하나는 &lt;strong&gt;바운드 레지스터&lt;/strong&gt;로, &lt;strong&gt;프로세스의 주소 공간 크기&lt;/strong&gt;를 저장한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;physical address &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; virtual address &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; base&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;asm&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;128&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;: movl &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0x0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;EBX&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) , % &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;eax&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;하드웨어가 이 명령어를 반입할 때, PC값(128)을 베이스 레지스터의 값(32KB = 32768)에 더해서 물리 주소(32896)를 얻는다.&lt;/p&gt;
&lt;p&gt;이 주소의 재배치는 실행 시에 일어나고, 실행 후에도 주소 공간을 이동할 수 있기 때문에 &lt;strong&gt;동적 재배치 (dynamic relocation)&lt;/strong&gt; 라고도 불린다.&lt;/p&gt;
&lt;p&gt;바운드 레지스터는 보호를 지원하기 위해 존재한다. 가상 주소가 바운드 안에 있는지 확인하는 용도. 바운드보다 큰 가상 주소를 참조하면 CPU는 예외를 발생시키고 프로세스가 종료된다.
바운드 레지스터 구현 방법은 두 가지가 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;주소 공간의 크기 저장&lt;/li&gt;
&lt;li&gt;주소 공간의 마지막 물리 주소를 저장&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이렇게 주소 변환에 도움을 주는 프로세서의 일부를 메모리 관리 장치 (MMU) 라고 부른다.&lt;/p&gt;
&lt;h3 id=&quot;예제&quot;&gt;예제&lt;/h3&gt;
&lt;p&gt;주소 공간의 크기가 4KB(4096)인 프로세스가 물리 주소 16KB(16384)에 탑재되어 있다고 가정하자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 15 Address Translation-1689617753303.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;608&quot; height=&quot;326&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2015%20Address%20Translation-1689617753303.BC-X01L__tBRrQ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;가상 주소가 너무 크면(바운드를 벗어나면) 오류가 발생한다.&lt;/p&gt;
&lt;h2 id=&quot;4-하드웨어-지원-요약&quot;&gt;4. 하드웨어 지원 요약&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 15 Address Translation-1689673685369.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1162&quot; height=&quot;844&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2015%20Address%20Translation-1689673685369.CSoVTLAK_23f7Db.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;5-운영체제-이슈&quot;&gt;5. 운영체제 이슈&lt;/h2&gt;
&lt;p&gt;베이스와 바운드 방식의 가상 메모리 구현을 위해 운영체제가 반드시 개입되어야 하는 시점이 4개 존재한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;프로세스가 생성될 때 운영체제는 주소 공간이 저장될 메모리 공간을 찾아 조치를 취해야 한다.&lt;/li&gt;
&lt;li&gt;프로세스가 종료할 때(정상적 종료 및 잘못된 행동으로 인한 강제 종료) 사용하던 메모리를 회수하여 다른 프로세스나 운영체제가 사용할 수 있게 해야 한다.&lt;/li&gt;
&lt;li&gt;운영체제는 문맥 교환이 일어날 때, 베이스와 바운드 쌍을 저장하고 복원해야 한다. -&gt; PCB에 있음&lt;/li&gt;
&lt;li&gt;예외가 발생할 때 호출될 함수를 제공해야 한다. -&gt; 부팅할 때 설치&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 15 Address Translation-1689674031826.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1100&quot; height=&quot;524&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2015%20Address%20Translation-1689674031826.CHEyvdTm_Z1O9eiy.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 15 Address Translation-1689674090849.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;942&quot; height=&quot;1296&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2015%20Address%20Translation-1689674090849.BOeaMm8H_uCpFD.webp&quot; &gt;&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 16 Segmentation</title><link>https://ks1ksi.io/blog/ostep-16-segmentation/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-16-segmentation/</guid><description>OSTEP Segmentation 정리. 주소 공간을 코드, 스택, 힙 세그먼트로 나누어 배치하는 방식과 단편화 문제를 설명한다.</description><pubDate>Mon, 17 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;지금까지 프로세스 주소 공간 &lt;strong&gt;전체&lt;/strong&gt;를 메모리에 탑재하는 것을 가정해 왔다. 베이스와 바운드 레지스터를 사용하여 운영체제는 프로세스는 물리 메모리의 다른 부분으로 쉽게 재배치할 수 있었다&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 16 Segmentation-1689674323191.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;506&quot; height=&quot;1348&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2016%20Segmentation-1689674323191.C9QrdhKa_Z12qf4k.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;하지만 프로그램의 힙과 스택 사이에 빈 공간이 사용되지 않더라도 주소 공간을 물리 메모리에 재배치할 때 메모리를 차지한다. &lt;strong&gt;베이스와 바운드 레지스터 방식은 메모리 낭비가 심하다&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;1-세그멘테이션-베이스바운드의-일반화&quot;&gt;1. 세그멘테이션: 베이스/바운드의 일반화&lt;/h2&gt;
&lt;p&gt;이 아이디어는 MMU 안에 오직 하나의 베이스와 바운드 쌍만 존재하는 것이 아니라 &lt;strong&gt;주소 공간의 논리적인 세그먼트 마다 베이스와 바운드 쌍이 존재한다.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;세그먼트: 특정 길이를 가지는 연속적인 주소 공간&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;우리가 기준으로 삼은 주소 공간에는 코드, 스택, 및 힙 세 종류의 세그먼트가 있다. 운영체제는 각 세그먼트를 물리 메모리의 각기 다른 위치에 배치할 수 있고, 사용되지 않는 가상 주소 공간이 물리 메모리를 차지하는 것을 방지할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 16 Segmentation-1689674692978.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;690&quot; height=&quot;812&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2016%20Segmentation-1689674692978.BCXXtLFO_Z2uGlkK.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이 예제의 경우 3쌍의 베이스와 바운드 레지스터 집합이 필요하다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 16 Segmentation-1689674722721.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;456&quot; height=&quot;202&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2016%20Segmentation-1689674722721.CBQ8wm4J_Z2gVTNk.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;그림 19.1의 주소 공간을 사용하여 주소 변환을 해 보자. 가상 주소 100을 참조한다고 가정하자.&lt;/p&gt;
&lt;p&gt;가상 주소 100번지는 &lt;strong&gt;코드 세그먼트&lt;/strong&gt;에 속한다. 참조가 일어나면 하드웨어는 베이스 값에 이 세그먼트의 오프셋을 더해 물리 주소는 100 + 32KB = 32868이 된다. 그 후 주소가 범위(2KB) 내에 있는지 검사하고 범위 내에 있을 경우 물리 메모리 주소 32868을 얻는다.&lt;/p&gt;
&lt;p&gt;가상 주소 4200의 힙을 사펴보자. 가상 주소 4200을 힙의 베이스 34KB에 더하는 방법을 잘못 된 방법이다. 힙 안에서의 오프셋, &lt;strong&gt;즉 주소가 참조하는 바이트가 이 세그먼트 시작으로부터 몇 번째 바이트인지&lt;/strong&gt;를 얻어야 한다. 힙은  가상 주소 4KB에서 시작하기 때문에 오프셋 4200은 4200 - 4096 = 104가 된다. 이 오프셋을 베이스 레지스터의 물리 주소 34KB에 더해 원하는 결과 34920을 얻게 된다.&lt;/p&gt;
&lt;p&gt;만약 힙의 마지막을 벅어난 7KB와 같은 잘못된 주소를 접근하려고 한다면, 하드웨어가 주소 범위가 벗어났다는 사실을 감지하고 운영체제에 트랩을 발생시킨다. 운영체제는 아마 프로세스를 종료시킬 것이고 이것이 &lt;strong&gt;Segment Fault&lt;/strong&gt;이다.&lt;/p&gt;
&lt;h2 id=&quot;2-세그먼트-종류의-파악&quot;&gt;2. 세그먼트 종류의 파악&lt;/h2&gt;
&lt;p&gt;하드웨어는 변환을 위해 &lt;strong&gt;세그먼트 레지스터&lt;/strong&gt;를 사용한다. 하드웨어는 &lt;strong&gt;가상 주소가 어느 세그먼트를 참조하는지&lt;/strong&gt;, 그리고 &lt;strong&gt;그 세그먼트 안에서 오프셋은 얼마인지&lt;/strong&gt;를 어떻게 알 수 있을까?&lt;/p&gt;
&lt;p&gt;방법 1: 가상 주소의 최상위 몇 비트를 기준으로 주소 공간을 여러 세그먼트로 나누기.&lt;/p&gt;
&lt;p&gt;위의 예시에서는 3개의 세그먼트가 있었다. 주소 공간을 세그먼트로 나누기 위해서는 2비트가 필요하다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;최상위 2비트가 00이면 가상 주소가 코드 세그먼트를 가리킨다
최상위 2비트가 01이면  가상 주소가 힙 세그먼트를 가리킨다
…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 16 Segmentation-1689675668694.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;628&quot; height=&quot;198&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2016%20Segmentation-1689675668694.CysCrk2d_qNbeH.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;3-스택&quot;&gt;3. 스택&lt;/h2&gt;
&lt;p&gt;스택은 다른 세그먼트들과는 다르게 &lt;strong&gt;반대 방향으로 확장된다.&lt;/strong&gt; 따라서 다른 방식의 변환이 필요하다.
간단한 하드웨어가 추가로 필요하다. &lt;strong&gt;세그먼트가 어느 방향으로 확장하는지&lt;/strong&gt;도 알아야 한다. 하나의 비트를 사용하여 주소가 커지는 방향으로 확장하면 1, 작아지는 방향으로 확장하면 0으로 설정할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 16 Segmentation-1689675870887.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;676&quot; height=&quot;270&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2016%20Segmentation-1689675870887.DLJCbus4_ZPR9d.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;4-공유-지원&quot;&gt;4. 공유 지원&lt;/h2&gt;
&lt;p&gt;메모리를 절약하기 위해 주소 공간들 간에 특정 메모리 세그먼트를 공유하도록 할 수 있다. 이를 위해 하드웨어에 &lt;strong&gt;protection bit&lt;/strong&gt;의 추가가 필요하다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;세그먼트를 읽거나 쓸 수 있는지 / 세그먼트의 코드를 실행시킬 수 있는지&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 16 Segmentation-1689676095627.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;854&quot; height=&quot;260&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2016%20Segmentation-1689676095627.ByU8SrTx_2drHq3.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 하면 주소 공간의 독립성을 유지하면서도, 여러 프로세스가 주소 공간의 일부를 공유할 수 있다. 각 프로세스는 여전히 자신의 전용 메모리를 사용하고 있다고 생각한다.&lt;/p&gt;
&lt;p&gt;가상 주소가 범위 내에 있는지 확인하는 것에 더해, 특정 액세스가 허용되는지를 확인하도록 알고리즘을 수정해야 한다. 허용되지 않은 액세스를 시도하는 경우, 하드웨어는 예외를 발생시킨다.&lt;/p&gt;
&lt;h2 id=&quot;5-소단위-대-대단위-세그먼테이션&quot;&gt;5. 소단위 대 대단위 세그먼테이션&lt;/h2&gt;
&lt;p&gt;지금까지 예제는 소수의 세그먼트(코드, 스택, 힙)만을 지원하는 시스템에 초점을 맞추었다. 이 세그먼테이션을 &lt;strong&gt;대단위 (coarse-grained)&lt;/strong&gt; 라고 생각할 수 있다. 일부 초기 시스템은 더 작은 단위로 주소 공간을 나누는 것이 허용되었다. 이를 &lt;strong&gt;소단위 (fine-grained)&lt;/strong&gt; 세그먼테이션이라고 부른다.
많은 수의 세그먼트를 지원하기 위해 &lt;strong&gt;세그먼트 테이블&lt;/strong&gt;같은 하드웨어를 따로 두었다.&lt;/p&gt;
&lt;h2 id=&quot;6-운영체제의-지원&quot;&gt;6. 운영체제의 지원&lt;/h2&gt;
&lt;p&gt;스택과 힙 사이의 사용하지 않는 공간에 물리 메모리를 할당할 필요가 없어졌다. 따라서 같은 크기의 물리 메모리에 더 많은 주소 공간을 탑재할 수 있게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;문맥 교환 시 운영체제는 어떤 일을 해야 할까?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;세그먼트 레지스터의 저장과 복원이 필요하다.
프로세스가 다시 실행되기 전에 레지스터들을 올바르게 설정해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;각 세그먼트의 크기가 다를 수 있기 때문에  딱 맞게 주소를 할당할 수 없다. 미사용 중인 물리 메모리 공간의 관리는 어떻게 해야 할까?(외부 단편화 문제)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 16 Segmentation-1689676700351.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1066&quot; height=&quot;766&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2016%20Segmentation-1689676700351.BTJV9O4__Zs5TWL.webp&quot; &gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;기존의 세그먼트를 정리하여 물리 메모리를 압축한다.
프로세스를 중단하고 그들의 데이터를 하나의 연속된 공간에 복사하고, 세그먼트 레지스터가 새로운 물리 주소를 가리키게 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;세그먼트 복사는 메모리에 부하가 큰 연산이다. 비용이 많이 드는 압축 말고 다른 방법은 없을까?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;빈 공간 리스트를 관리하는 알고리즘을 사용한다.
best-fit, worst-fit, buddy-algorithm 등 여러 가지 알고리즘이 존재한다.
best-fit 알고리즘은 빈 공간 리스트에서 요청된 크기와 가장 비슷한 크기의 공간을 할당하는 알고리즘이다.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 09 Lottery Scheduling</title><link>https://ks1ksi.io/blog/ostep-09-lottery-scheduling/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-09-lottery-scheduling/</guid><description>OSTEP Lottery Scheduling 정리. 티켓 기반 비례 배분, 티켓 양도와 팽창, stride scheduling과의 차이를 설명한다.</description><pubDate>Tue, 04 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;앞에서 배운 반환 시간 혹은 응답 시간을 최적화하는 스케줄러 대신, 각 작업에게 CPU의 일정 비율을 보장하는 것이 목적인 비례 배분 스케줄러에 대해 알아보자.&lt;/p&gt;
&lt;h2 id=&quot;1-추첨권-티켓&quot;&gt;1. 추첨권 (티켓)&lt;/h2&gt;
&lt;p&gt;전체 티켓 중 프로세스가 보유한 티켓의 비율이 받아야 할 CPU 자원의 비율이다.
그리고 &lt;a href=&quot;https://ks1ksi.io/blog/ostep-07-cpu-scheduling/#%5E865cd1&quot;&gt;타임 슬라이스&lt;/a&gt; 한 번마다 전체 티켓 중 하나를 무작위로 추첨하여 실행할 프로세스를 결정한다.&lt;/p&gt;
&lt;p&gt;0부터 99까지의 티켓 중 A가 0부터 74, B가 75에서 99까지의 티켓을 가지고 있다고 하자.
&lt;img alt=&quot;OSTEP 09 Lottery Scheduling-1688318106781.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;809&quot; height=&quot;49&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2009%20Lottery%20Scheduling-1688318106781.CrkHg-83_Z2ij88K.webp&quot; &gt;
&lt;img alt=&quot;OSTEP 09 Lottery Scheduling-1688318090682.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;663&quot; height=&quot;55&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2009%20Lottery%20Scheduling-1688318090682.BhE90GNG_D1mnb.webp&quot; &gt;
이렇게 뽑힌 티켓 값에 따라 어떤 프로세스를 실행할지 결정한다.
전체 20개의 타임 슬라이스 중, B는 4개(20%) 의 타임 슬라이스를 획득했다. 목표로 했던 25%보다는 적지만, 시간이 지나면 지날수록 25%에 가까워질 것이다.&lt;/p&gt;
&lt;h2 id=&quot;2-추첨-기법&quot;&gt;2. 추첨 기법&lt;/h2&gt;
&lt;h3 id=&quot;1-추첨권-화폐ticket-currency&quot;&gt;1. 추첨권 화폐(ticket currency)&lt;/h3&gt;
&lt;p&gt;티켓을 화폐처럼, 환율을 적용해서 스케줄링하는 기법이다.
각각의 사용자가 100장의 global 티켓을 받았다고 가정하자. 사용자 A는 프로세스 A1, A2 두 개를 실행중이고, 자신이 정한 티켓 1000장 중 500장씩 A1, A2에 할당했다. 사용자 B는 프로세스 B에 자신이 정한 티켓 10장 중 10장을 할당했다.
환율을 적용하면, A1은 50장, A2는 50장, B는 100장의 global 티켓을 받는다.&lt;/p&gt;
&lt;h3 id=&quot;2-추첨권-양도ticket-transfer&quot;&gt;2. 추첨권 양도(ticket transfer)&lt;/h3&gt;
&lt;p&gt;프로세스가 일시적으로 티켓을 다른 프로세스에게 넘겨줄 수 있다.
예를 들어, 클라이언트 프로세스가 서버에게 특정 작업을 대신해달라고 요청할 때, 티켓을 함께 넘겨주어 작업이 빨리 완료될 수 있도록 한다.&lt;/p&gt;
&lt;h3 id=&quot;3-추첨권-팽창ticket-inlation&quot;&gt;3. 추첨권 팽창(ticket inlation)&lt;/h3&gt;
&lt;p&gt;프로세스가 일시적으로 자신이 소유한 티켓의 수를 늘이거나 줄일 수 있다.
그런데 이렇게 하면 하나의 욕심 많은 프로세스가 매우 많은 양의 추첨권을 자신에게 할당할 수 있다. 때문에 프로세스간 신뢰 가능한 시스템에서 유용하다. 추첨권 양도처럼 다른 프로세스와 통신할 필요 없이, 혼자 티켓을 늘려 CPU 자원을 많이 받을 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;3-구현&quot;&gt;3. 구현&lt;/h2&gt;
&lt;p&gt;난수 발생기, 프로세스들의 집합을 표현하는 자료 구조, 추첨권의 전체 개수 이렇게 3개만 있으면 구현할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 09 Lottery Scheduling-1688318859577.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;821&quot; height=&quot;527&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2009%20Lottery%20Scheduling-1688318859577.HCRfEkA-_ZpwSmi.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 09 Lottery Scheduling-1688318865724.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;747&quot; height=&quot;151&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2009%20Lottery%20Scheduling-1688318865724.CXvRtdLe_Z25AasW.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;A는 0부터 99, B는 100부터 149, C는 150부터 399까지 티켓을 할당받는다. winner에 난수 300이 할당되었다고 하자. 리스트를 앞에서부터 순회하면서 counter의 값을 증가시킨다. A를 만나면 100, B를 만나면 150이 된다. C를 만나면 400이 되어 난수 300보다 커지므로 당첨자를 찾은 것이다.
리스트를 내림차순으로 정렬 (티켓 많이 받은 프로세스가 앞에 오도록) 하면 좀 더 효율적이다.&lt;/p&gt;
&lt;h2 id=&quot;4-예제&quot;&gt;4. 예제&lt;/h2&gt;
&lt;p&gt;같은 개수의 티켓을 보유하고 있고, 동일한 실행 시간을 가지는 프로세스 두 개의 수행 시간을 살펴보자. 두 프로세스를 거의 동시에 종료시키는 것이 목표다.&lt;/p&gt;
&lt;p&gt;첫 번째 작업이 종료된 시간을 두 번째 작업이 종료된 시간으로 나눈 지표인 &lt;strong&gt;불공정 지표&lt;/strong&gt;인 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;U&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;U&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 정의하자. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;U&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;U&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 1일 때, 스케줄러는 완벽한 공정 스케줄러이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 09 Lottery Scheduling-1688319451851.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;797&quot; height=&quot;671&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2009%20Lottery%20Scheduling-1688319451851.B6o7wzSy_Z2bO7DC.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;작업의 시간이 짧은 경우, 무작위성에 영향을 많이 받아 불공정 지표가 1에 가깝지 않고, 작업의 시간이 긴 경우 무작위성에 영향을 덜 받아 불공정 지표가 1에 가깝게 나온다.&lt;/p&gt;
&lt;p&gt;작업의 길이가 길어야 추첨 스케줄러를 통해 원하는 결과 (공정한 스케줄러) 를 얻을 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;5-티켓-배분-방식&quot;&gt;5. 티켓 배분 방식&lt;/h2&gt;
&lt;p&gt;티켓을 어떻게 할당하느냐는 문제는 굉장히 어려운 문제이다.
한 가지 접근 방식은 사용자가 어떻게 배분해야 할지 알고 있다고 가정하고, 사용자에게 모두 맡기는 것이다. 사용자에게 티켓을 주고, 실행시키고자 하는 작업들에게 티켓을 배분한다. 하지만 이 방법은 해결책이 될 수 없다.&lt;/p&gt;
&lt;h2 id=&quot;6-왜-결정론적-deterministic-방법을-사용하지-않는가&quot;&gt;6. 왜 결정론적 (Deterministic) 방법을 사용하지 않는가&lt;/h2&gt;
&lt;p&gt;위에서 본 바와 같이, 무작위성을 이용하면 스케줄러를 단순하게 만들 수 있지만 &lt;strong&gt;정확한 비율을 보장할 수 없다.&lt;/strong&gt; 특히 &lt;strong&gt;짧은 기간만 실행되는 경우&lt;/strong&gt;는 더욱 심하다. 때문에 결정론적 공정 배분 스케줄러인 보폭 스케줄링(stride scheduling)을 고안했다.&lt;/p&gt;
&lt;h3 id=&quot;보폭-스케줄링stride-scheduling&quot;&gt;보폭 스케줄링(Stride Scheduling)&lt;/h3&gt;
&lt;p&gt;시스템의 각 작업은 ‘보폭’이라는 값을 가지고 있다. 이 보폭은 해당 작업이 가지고 있는 추첨권 수에 반비례하는 값이다. 예를 들어, 작업 A, B, C가 각각 100, 50, 250의 추첨권을 가지고 있다고 가정해보자. 이때 임의의 큰 값을 각 작업의 추첨권 개수로 나누어 보폭을 계산할 수 있다. 여기서는 10,000을 각 작업의 추첨권 개수로 나누면, 각 작업의 보폭은 100, 200 및 40이 된다.&lt;/p&gt;
&lt;p&gt;이제 각 작업이 CPU를 사용할 때마다, ‘pass’라는 값이 보폭만큼 증가합니다. 이 ‘pass’ 값은 해당 작업이 얼마나 많이 CPU를 사용했는지를 추적하는 데 사용됩니다. 스케줄러는 이 보폭과 pass 값을 사용하여 어떤 작업을 다음으로 실행시킬지를 결정한다.
가장 작은 pass 값을 가진 작업을 선택하고, 그 작업을 실행한 후에는 해당 작업의 pass 값을 보폭만큼 증가시킨다.
&lt;strong&gt;보폭 스케줄링은 각 스케줄링 주기마다 정확한 비율로 CPU를 배분한다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 09 Lottery Scheduling-1688320073390.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1065&quot; height=&quot;121&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2009%20Lottery%20Scheduling-1688320073390.CVKFFwc9_21SPaR.webp&quot; &gt;&lt;/p&gt;
&lt;h3 id=&quot;왜-보폭-스케줄링이-아닌-추첨-스케줄링을-사용하는가&quot;&gt;왜 보폭 스케줄링이 아닌 추첨 스케줄링을 사용하는가?&lt;/h3&gt;
&lt;p&gt;추첨 스케줄링에는 보폭 스케줄링이 가지고 있지 않은 멋진 특성이 있기 때문. 바로 &lt;strong&gt;상태 정보가 필요 없다&lt;/strong&gt;는 점이다.&lt;/p&gt;
&lt;p&gt;보폭 스케줄링에서는 스케줄링 중간에 새로운 작업이 시스템에 도착하면, 그 작업의 pass 값이 얼마가 되어야 할지 결정해야 한다. 그런데 추첨 스케줄링에서는 이러한 정보가 필요 없다. 새로운 작업이 추가될 때, 그냥 새 작업이 가진 추첨권의 개수를 전체 추첨권의 개수에 추가하고 스케줄링을 수행하면 된다. 따라서, 추첨 스케줄링에서는 새로운 작업을 쉽게 추가할 수 있다.&lt;/p&gt;
&lt;p&gt;비례 배분 스케줄러는 추첨권 할당량을 비교적 정확하게 결정할 수 있는 환경에서 유용하게 사용된다. 예를 들어, &lt;strong&gt;가상화 데이터 센터&lt;/strong&gt;에서 Windows 가상 머신에 CPU 사이클의 1/4을 할당하고 나머지는 Linux 시스템에 할당하고 싶은 경우 비례 배분이 간단하고 효과적이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/&quot;&gt;OSTEP 교재&lt;/a&gt; 참고&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 10 Multi-CPU Scheduling</title><link>https://ks1ksi.io/blog/ostep-10-multi-cpu-scheduling/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-10-multi-cpu-scheduling/</guid><description>OSTEP Multi-CPU Scheduling 정리. 캐시 일관성, 동기화, 캐시 친화성, 단일 큐와 멀티 큐 스케줄링의 장단점을 요약한다.</description><pubDate>Tue, 04 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;멀티프로세서 스케줄링의 기본을 알아보자. 나중에 병행성(concurrency)에 대해 공부하고 다시 복습하면 좋을 것이다.&lt;/p&gt;
&lt;p&gt;최근에는 여러개의 코어가 하나의 칩에 내장된 멀티코어 프로세서가 대중화 되었다.
하지만 전통적인 프로그램들은 오직 하나의 CPU만 사용하도록 설계되었다. 이 문제를 해결하려면 응용 프로그램을 &lt;strong&gt;병렬(parallel)&lt;/strong&gt; 로 실행되도록 다시 작성해야 한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;동시성(Concurrency) vs 병렬성(Parallelism)
&lt;a href=&quot;https://black7375.tistory.com/90&quot;&gt;참고&lt;/a&gt;
&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688397745618.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1865&quot; height=&quot;1627&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688397745618.DVWHbX3I_Z1oyAg4.webp&quot; &gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;보통 &lt;strong&gt;쓰레드&lt;/strong&gt;를 여러 코어에 할당하는 방식을 통해 이를 해결한다.&lt;/p&gt;
&lt;p&gt;운영체제도 이에 대응해야 한다.
우리가 지금까지 배운 CPU 스케줄링 기법은 단일 CPU환경에서 논의된 내용이다. 이를 멀티코어 환경에서 동작하도록 확장해보자.
&lt;strong&gt;핵심 질문 : 여러 CPU에 작업을 어떻게 스케줄 해야 하는가&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;1-배경-멀티프로세서-구조&quot;&gt;1. 배경: 멀티프로세서 구조&lt;/h2&gt;
&lt;p&gt;단일 CPU 하드웨어와 멀티 CPU 하드웨어가 어떻게 다른가?
다수의 프로세서간 데이터 공유, 그리고 하드웨어 캐시의 사용 방식에서 근본적인 차이가 발생한다. 구체적인 내용을 살펴보긴 어려우니, 개념적으로만 다뤄보자.&lt;/p&gt;
&lt;p&gt;단일 CPU 시스템에는 &lt;strong&gt;하드웨어 캐시&lt;/strong&gt; 계층이 존재한다. 캐시는 메인 메모리에서 자주 사용되는 데이터의 복사본을 저장하는 작고 빠른 메모리이다. 캐시는 크기가 작은 대신 메인 메모리보다 훨씬 빠르게 데이터를 가져올 수 있다.&lt;/p&gt;
&lt;p&gt;프로세서가 데이터가 다시 사용될 것으로 예상하면 읽은 데이터의 복사본은 캐시 메모리에 저장하고, 나중에 데이터를 읽을 때 캐시에 해당 데이터가 존재하는지 검사한다.&lt;/p&gt;
&lt;p&gt;캐시는 지역성(locality)에 기반한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;시간 지역성(temporal locality): 데이터가 한 번 접근되면 가까운 미래에 다시 접근될 확률이 높다. ex) 루프에서 여러 번 반복해서 접근되는 변수&lt;/li&gt;
&lt;li&gt;공간 지역성(spatial locality): 프로그램이 주소 x의 데이터를 접근하면, x 근처에 있는 데이터가 접근될 확률이 높다. ex) 전체 배열을 차례대로 접근하는 프로그램&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688409586302.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;567&quot; height=&quot;501&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688409586302.DLdcBs7A_1jrGFT.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;그런데 이렇게 하나의 시스템에 여러 CPU가 존재하고, 하나의 공유 메모리가 존재하는 경우에는 어떤 일이 일어날까?&lt;/p&gt;
&lt;p&gt;CPU 1에서 실행 중인 프로그램이 주소 A에 써있는 값 D를 읽는다고 가정해보자. 메인 메모리로부터 값 D를 읽고 값을 D’으로 변경한다. 이 때 메인 메모리에 데이터를 쓰는 것은 오래 걸리기 때문에 보통 캐시에 D’ 값을 쓰고 메인 메모리에는 나중에 반영한다.
이 때 CPU 2에서 주소 A의 값을 읽으면 D’가 아닌 D를 읽게 된다.&lt;/p&gt;
&lt;p&gt;이를 &lt;strong&gt;캐시 일관성 문제 (cache coherence)&lt;/strong&gt; 라고 한다. 캐시 일관성 문제는 어떻게 해결할까?
하드웨어가 메모리 주소를 계속 감시하고, 관리하는 해결책이 있다.
여러 개의 프로세스들이 하나의 메모리에 갱신할 때 공유되도록, 버스 기반 시스템에서 &lt;strong&gt;버스 스누핑&lt;/strong&gt; 이라는 기법을 사용한다.&lt;/p&gt;
&lt;h3 id=&quot;버스-스누핑&quot;&gt;버스 스누핑&lt;/h3&gt;
&lt;p&gt;캐시가 자신과 연결된 메모리를 연결하는 버스의 통신 상황을 모니터링하다, 캐시 데이터에 대한 변경이 발생하면 자신의 복사본을 무효화 시키거나 새로운 값을 캐시에 기록한다.&lt;/p&gt;
&lt;h2 id=&quot;2-동기화&quot;&gt;2. 동기화&lt;/h2&gt;
&lt;p&gt;캐시가 일관성 유지를 담당한다면, 운영체제는 공유 데이터에 접근할 때 어떻게 해야할까?&lt;/p&gt;
&lt;p&gt;CPU가 동일한 데이터 또는 구조체에 접근할 때, 올바른 연산 결과를 보장하기 위해 락과 같은 상호 배제를 보장하는 동기화 기법이 사용된다.&lt;/p&gt;
&lt;p&gt;연결 리스트에서 원소를 삭제하는 코드를 생각해보자.
&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688410677868.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;913&quot; height=&quot;361&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688410677868.BGTLgOBZ_2wi0xp.webp&quot; &gt;
사용자가 함수를 두 번 호출하여 두 쓰레드가 동시에 루틴으로 진입했을 때, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;tmp&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8095em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 포인터에는 같은 메모리 주소가 기록되고, 같은 메모리를 두 번 해제하게 된다. 두 번 호출했는데, 한 번만 지워졌다.&lt;/p&gt;
&lt;p&gt;해결책은 락을 걸어서 올바르게 작동하도록 만드는 것이다. 간단한 &lt;code&gt;mutex&lt;/code&gt;를 할당하고 (&lt;code&gt;pthread_mutex_t m;&lt;/code&gt;) 루틴의 시작에 &lt;code&gt;lock(&amp;#x26;m)&lt;/code&gt;, 마지막에 &lt;code&gt;unlock(&amp;#x26;m)&lt;/code&gt; 을 추가하면 문제를 해결할 수 있다. 하지만 CPU의 개수가 증가할수록, 동기화된 자료구조에 접근하는 연산은 매우 느려진다.&lt;/p&gt;
&lt;h2 id=&quot;3-캐시-친화성&quot;&gt;3. 캐시 친화성&lt;/h2&gt;
&lt;p&gt;CPU에서 프로세스가 실행될 때, 해당 CPU 캐시와 TLB에 상당한 양의 정보를 올려 놓는데, 이 때문에 다음 번에 실행 될 때 동일한 CPU에서 실행되는 것이 유리하다. 해당 CPU 캐시에 일부 정보가 남아있기 때문이다. 캐시 일관성 프로토콜 때문에 다른 CPU에서 실행되더라도 제대로 실행은 되겠지만, 다른 CPU에서 실행되는 경우 필요한 정보를 캐시에 다시 탑재해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CPU 캐시(CPU Cache)&lt;/strong&gt; 는 CPU와 주기억장치 사이에 위치하여, CPU가 필요로 하는 데이터를 미리 저장해 놓는 고속 메모리이다. CPU가 데이터를 필요로 할 때, 먼저 CPU 캐시에서 해당 데이터를 찾는다. 이때 해당 데이터가 CPU 캐시에 있으면 ‘캐시 히트(Cache Hit)‘라고 하며, 없으면 ‘캐시 미스(Cache Miss)‘라고 한다.&lt;/p&gt;
&lt;p&gt;반면, &lt;strong&gt;TLB(Translation Lookaside Buffer)&lt;/strong&gt; 는 가상 메모리 시스템에서 가상 주소를 물리 주소로 변환하는 과정을 가속화하기 위해 사용하는 캐시이다. CPU가 데이터를 참조할 때 가상 주소를 물리 주소로 변환해야 하는데, 이때 먼저 TLB를 조회한다. TLB에 해당 정보가 있으면 ‘TLB 히트’라고 하고, 없으면 ‘TLB 미스’라고 한다.&lt;/p&gt;
&lt;p&gt;두 기술 모두 CPU의 작업을 가속화하기 위한 캐시 메모리이지만, 저장하는 데이터의 종류와 그 역할에 차이가 있다. CPU 캐시는 실제 데이터를 저장하고, 이 데이터는 CPU가 직접 작업을 수행하는 데 사용된다. 반면에, TLB는 가상 주소와 물리 주소 간의 매핑 정보를 저장하며, 이 정보는 CPU가 메모리에서 데이터를 찾는 데 사용된다. 즉, CPU 캐시는 ‘무엇’을 저장하는 반면, TLB는 ‘어디에’ 정보를 저장하는 역할을 한다.&lt;/p&gt;
&lt;h2 id=&quot;4-단일-큐-스케줄링&quot;&gt;4. 단일 큐 스케줄링&lt;/h2&gt;
&lt;p&gt;멀티프로세서 시스템의 스케줄러에 대해 알아보자. 단일 프로세서에서 하던 것 처럼, 그대로 적용할 수 있다. 이러한 방식을 &lt;strong&gt;단일 큐 멀티프로세서 스케줄링(single queue multiprocessor scheduling, SQMS)&lt;/strong&gt; 이라 부른다.&lt;/p&gt;
&lt;p&gt;아주 단순하다. CPU가 1개일 때는 작업을 하나씩 선택해서 실행했고, CPU가 2개일 때는 작업을 두개씩 선택해서 실행하면 된다.
하지만 단점이 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;확장성 (scalability) 결여: 스케줄러가 다수의 CPU에서 동작하도록 코드에 락을 삽입해야 한다. 그래야 실행시킬 다음 작업을 올바르게 찾을 수 있다(동시에 같은 작업 고르면?). CPU 개수가 증가할수록 락은 성능을 크게 저하시킨다.&lt;/li&gt;
&lt;li&gt;캐시 친화성 (cache affinity): 각 CPU는 공유 큐에서 다음 작업을 선택하기 때문에 각 작업은 CPU를 옮겨다니게 된다.
&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688411970608.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;905&quot; height=&quot;417&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688411970608.DFVR45JA_Z1WYv24.webp&quot; &gt;
특정 작업들에 대해서 캐시 친화성을 고려하여 스케줄링하고, 다른 작업들은 여러군데로 분산시키는 정책을 사용할 수 있긴 하다. 하지만 구현이 복잡해진다.
&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688412107270.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;877&quot; height=&quot;439&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688412107270.CWVCopiQ_1XVzuy.webp&quot; &gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;5-멀티-큐-스케줄링&quot;&gt;5. 멀티 큐 스케줄링&lt;/h2&gt;
&lt;p&gt;이러한 문제때문에 일부 시스템은 CPU마다 큐를 하나씩 둔다. 이 방식을 멀티 큐 멀티프로세서 스케줄링(multi-queue multiprocessor scheduling, MQMS)이라고 부른다.&lt;/p&gt;
&lt;p&gt;각각의 큐는 라운드 로빈같은 특정 스케줄링 규칙을 따르고 있다. 작업이 여러 스케줄링 큐 중 하나에 배치된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688412265974.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;749&quot; height=&quot;113&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688412265974.C7JhvaRC_1Dkq2o.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;Q&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Q0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 배치되었고, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;Q&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Q1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;가 배치되었다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688412327426.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1229&quot; height=&quot;247&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688412327426._4DDapbn_ZW5zEL.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;라운드 로빈 방식이라면 이렇게 스케줄링 될 것이다.&lt;/p&gt;
&lt;p&gt;SQMS에 비해 확장성이 좋다. CPU 개수가 증가할수록 큐의 개수도 증가하므로 락에 대한 걱정을 할 필요가 없다. 또 MQMS는 캐시 친화적이다. 작업이 같은 CPU에서 계속 실행되기 때문에 캐시에 저장된 내용을 계속 재사용할 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 MQMS는 워크로드의 불균형 (load imbalance) 문제를 가지고 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688412473870.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;835&quot; height=&quot;147&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688412473870.SY2rFIfQ_Z2opTPf.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;Q&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Q0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 있는 모든 작업들이 종료된다면&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688413591826.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1201&quot; height=&quot;239&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688413591826.DJK5Uu8q_Z1zJn4i.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;CPU 0은 일을 하지 않을 것이다.&lt;/p&gt;
&lt;p&gt;이를 해결하기 위해 &lt;strong&gt;작업을 다른 CPU로 이주 (migration)&lt;/strong&gt; 시킴으로써 워크로드의 균형을 달성할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688412633462.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;763&quot; height=&quot;159&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688412633462.BAma88_u_Z1VpXOi.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;Q&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Q0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 작업이 하나, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;Q&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;Q1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 작업이 두 개 있다고 가정하자. 이주 없이 그냥 실행시키면 작업 A가 남들보다 2배의 CPU 자원을 받을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 10 Multi-CPU Scheduling-1688412683555.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1203&quot; height=&quot;247&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2010%20Multi-CPU%20Scheduling-1688412683555.y5R8ji6W_1QkhO1.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이런 식으로 작업을 지속적으로 이주시켜, 워크로드의 균형을 달성할 수 있다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A, B, D&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05017em;&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 모두 8번의 타임 슬라이스를 받았다.
작업이 적게 할당된 큐가, 다른 큐를 가끔 검사한다. 작업이 많다면, 작업을 가져와서 균형을 맞춘다.&lt;/p&gt;
&lt;h2 id=&quot;6-linux-멀티프로세서-스케줄러&quot;&gt;6. Linux 멀티프로세서 스케줄러&lt;/h2&gt;
&lt;p&gt;Linux에는 여러 가지 멀티프로세서 스케줄러가 존재하며, 대표적으로 O(1) 스케줄러, Completely Fair Scheduler(CFS), 그리고 BFS 스케줄러가 있다. 이들 스케줄러는 각기 다른 특성과 장단점을 가지고 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;O(1) 스케줄러: 이는 우선순위 기반 스케줄링 방식으로, 프로세스의 우선순위를 시간에 따라 변경하며 우선순위가 가장 높은 작업을 선택한다. 상호작용을 우선시하는 특징이 있다.&lt;/li&gt;
&lt;li&gt;CFS: 이는 결정론적인 비례배분 방식으로 스케줄링한다. 보폭 스케줄링 방식에 가깝다고 볼 수 있다.&lt;/li&gt;
&lt;li&gt;BFS: 이는 유일하게 단일 큐 방식을 사용하며, 비례배분 방식으로 스케줄링한다. 복잡한 알고리즘인 Earliest Eligible Virtual Deadline First(EEVDF)에 기반을 두고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;7-요약&quot;&gt;7. 요약&lt;/h2&gt;
&lt;p&gt;멀티프로세서 스케줄링에는 크게 단일 큐 방식과 멀티 큐 방식이 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;단일 큐 방식: 구현이 간단하고 워크로드의 균형을 잘 맞추는 특징이 있다. 하지만, 많은 프로세서에 대한 확장성과 캐시 친화성이 좋지 않다.&lt;/li&gt;
&lt;li&gt;멀티 큐 방식: 확장성이 좋고 캐시 친화성을 잘 다루는 반면, 워크로드의 불균형에 취약하고 구현이 복잡하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/&quot;&gt;OSTEP 교재&lt;/a&gt; 참고&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 13 Address Spaces</title><link>https://ks1ksi.io/blog/ostep-13-address-spaces/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-13-address-spaces/</guid><description>OSTEP Address Spaces 정리. 멀티프로그래밍과 시분할을 배경으로 주소 공간 추상화, 투명성, 효율성, 보호 목표를 설명한다.</description><pubDate>Tue, 04 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;1-초기-시스템&quot;&gt;1. 초기 시스템&lt;/h2&gt;
&lt;p&gt;운영체제는 메모리에 상주하는 루틴(라이브러리)의 집합이었다. 물리 메모리에 하나의 실행 중인 프로그램이 존재하였고, 운영체제가 쓰고 남은 메모리를 사용하였다. 가상화? 그런건 없었다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 13 Address Spaces-1688413695513.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;475&quot; height=&quot;509&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2013%20Address%20Spaces-1688413695513.CoDFWj4h_1YTI0e.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;2-멀티프로그래밍과-시분할&quot;&gt;2. 멀티프로그래밍과 시분할&lt;/h2&gt;
&lt;p&gt;멀티프로그래밍 시대가 왔다. 여러 프로세스가 실행 준비 상태에 있고, 운영체제가 이들을 전환하면서 실행하였다. 한 프로세스가 입출력을 하면, CPU는 다른 프로세스로 전환하였다.&lt;/p&gt;
&lt;p&gt;이렇게 여러 프로세스간 전환을 통해 CPU의 이용률이 올라갔다. 사람들은 컴퓨터를 더 많이 사용하길 원했고, &lt;strong&gt;시분할 (time sharing)&lt;/strong&gt; 방식을 사용했다. 일괄처리방식 (batch) 컴퓨팅의 한계를 느꼈기 때문이다.&lt;/p&gt;
&lt;p&gt;시분할을 구현하는 한 가지 방법은 하나의 프로세스를 짧은 시간 동안 실행시키는 것이었다. 그런 후 프로세스를 중단하고, 중단 시점의 모든 상태를 디스크에 저장하고 다른 프로세스의 상태를 탑재하여 실행시키는 방식이었다.
하지만 이 방법에는 문제가 있었다. 메모리 크기가 커질수록 성능이 느려지는 문제가 발생했다.&lt;/p&gt;
&lt;p&gt;다음 사진처럼 프로세스를 전환할 때, 프로세스를 메모리에 그대로 유지하면서, 시분할 방식으로 작동하도록 해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 13 Address Spaces-1688414404626.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;475&quot; height=&quot;533&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2013%20Address%20Spaces-1688414404626.MTU1YPN6_mB7Dq.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;여러 프로세스들이 메모리의 일정 부분을 함께 사용한다. 함께 사용하려면, &lt;em&gt;한 프로세스가 다른 프로세스의 메모리를 읽거나 쓰지 못하도록 &lt;strong&gt;보호(protection)&lt;/strong&gt; 해야 한다.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;3-주소-공간&quot;&gt;3. 주소 공간&lt;/h2&gt;
&lt;p&gt;이러한 위험에 대비하여 운영체제는 사용하기 쉬운(추상화된) 메모리 개념인 &lt;strong&gt;주소 공간(address space)&lt;/strong&gt; 를 만들었다. 프로세스는 자신의 주소 공간에만 접근한다.
주소 공간은 실행 프로그램의 모든 메모리 상태를 가지고 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 13 Address Spaces-1688414817225.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;637&quot; height=&quot;563&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2013%20Address%20Spaces-1688414817225.Clf1K2JH_1Nef6S.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;그림에는 0KB부터 16KB라고 써있지만 실제로 물리 주소 0 ~ 16 사이에 존재하는 것은 아니다. A, B, C가 함께 메모리에 올라가 있는 그림처럼, 실제 물리 주소는 다를 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;가상화&lt;/strong&gt;: 물리 메모리를 공유하는 다수의 프로세스에게 프로세스 전용의 커다란 주소 공간이라는 개념을 제공하는 것&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그러면 메모리를 어떻게 가상화 하는 것일까?&lt;/p&gt;
&lt;h2 id=&quot;4-목표&quot;&gt;4. 목표&lt;/h2&gt;
&lt;p&gt;가상 메모리 시스템 (VM) 의 주요 목표에 대해 살펴보자.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;투명성(transparency): 실행 중인 프로그램이 가상 메모리의 존재를 인지하지 못하도록 가상 메모리 시스템을 구현해야 한다. 물리 메모리를 소유한 것처럼 행동해야 한다.&lt;/li&gt;
&lt;li&gt;효율성(eiciency): 가상화를 지원하기 위해 너무 느리게 실행되거나 너무 많은 메모리를 소모해서는 안된다. TLB 등의 도움을 받을 수 있다.&lt;/li&gt;
&lt;li&gt;보호(protection): 프로세스를 다른 프로세스로부터 보호해야 한다. 운영체제 자신도 프로세스로부터 보호해야 한다. &lt;strong&gt;절대 다른 프로세스나 운영체제의 메모리 내용에 접근하거나 영향을 줄 수 있어서는 안 된다.&lt;/strong&gt; 프로세스들을 서로 고립시켜야 한다.&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 04 Process</title><link>https://ks1ksi.io/blog/ostep-04-process/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-04-process/</guid><description>OSTEP Process 정리. 프로세스의 개념, 주소 공간과 레지스터 상태, 프로세스 생성 과정, 상태 전이와 운영체제 자료구조를 요약한다.</description><pubDate>Mon, 03 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;1-프로세스의-개념&quot;&gt;1. 프로세스의 개념&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;프로세스는 실행 중인 프로그램&lt;/strong&gt;을 의미한다.&lt;/p&gt;
&lt;p&gt;그리고 &lt;strong&gt;프로그램은 디스크에 존재하는 명령어와 정적 데이터의 묶음&lt;/strong&gt;이다. 이것을 우리가 사용 가능하도록 실행하는 것이 운영체제의 목표이다.
프로세스의 구성 요소를 이해하기 위해서는 하드웨어 상태를 이해해야 한다. 프로그램이 실행되는 동안 하드웨어 상태를 읽거나 갱신할 수 있기 때문이다.
그중 가장 중요한 하드웨어 구성 요소는 &lt;strong&gt;메모리&lt;/strong&gt;이다. 명령어와 프로그램이 읽고 쓰는 데이터는 모두 메모리에 저장된다.
&lt;strong&gt;레지스터&lt;/strong&gt;도 중요한 구성 요소이다. &lt;strong&gt;프로그램 카운터&lt;/strong&gt;는 프로그램의 어떤 명령어가 실행 중인지 알려준다. &lt;strong&gt;스택 포인터와 프레임 포인터&lt;/strong&gt;는 함수의 변수와 리턴 주소를 저장하는 스택을 관리할 때 사용하는 레지스터이다.
또 프로그램은 &lt;strong&gt;영구 저장장치&lt;/strong&gt;에 접근하기도 한다. 이 IO 정보는 프로세스가 현재 열어 놓은 파일 목록을 가지고 있다.&lt;/p&gt;
&lt;h2 id=&quot;2-프로세스-api&quot;&gt;2. 프로세스 API&lt;/h2&gt;
&lt;p&gt;다음 챕터에서 자세히 다룰 예정이기 때문에 어떤 종류가 있는지만 확인.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create → 프로세스를 새로 생성한다&lt;/li&gt;
&lt;li&gt;Destroy → 프로세스를 강제로 종료한다&lt;/li&gt;
&lt;li&gt;Wait → 종료 전 대기&lt;/li&gt;
&lt;li&gt;Miscellaneous Control → 대기, 종료 외에 일시정지 및 재개 등&lt;/li&gt;
&lt;li&gt;Status → 얼마나 실행됐는지, 어떤 상태인지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-프로세스-생성&quot;&gt;3. 프로세스 생성&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 04 Process-1687712572337.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;709&quot; height=&quot;836&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2004%20Process-1687712572337.Bscz8Hcj_ZltfKq.webp&quot; &gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;프로그램 코드와 정적 데이터를 메모리, 프로세스의 주소 공간에 로드.
&lt;ol&gt;
&lt;li&gt;운영체제는 디스크의 해당 바이트를 읽어서 메모리의 어딘가에 올려야 한다.&lt;/li&gt;
&lt;li&gt;필요한 부분만 메모리에 탑재 → 페이징, 스와핑 이해 필요. 예전에는 그냥 다 때려박음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;일정량의 메모리가 프로그램의 실행시간 스택 (런타임 스택) 용도로 할당되어야 함.&lt;/li&gt;
&lt;li&gt;힙을 위한 메모리 영역도 할당되어야 함. (&lt;code&gt;malloc&lt;/code&gt;, &lt;code&gt;free&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;입출력과 관계된 초기화 작업 수행 (STDIN, STDOUT, STDERR 3개의 파일 디스크립터) → 3번째 부분인 영속성에서 다룸&lt;/li&gt;
&lt;li&gt;실행준비 완료. 프로그램의 시작 지점인 main()에서부터 프로그램 실행. 운영체제는 CPU를 새로 생성된 프로세스에게 할당. 프로그램 실행 시작.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;4-프로세스-상태&quot;&gt;4. 프로세스 상태&lt;/h2&gt;
&lt;p&gt;프로세스는 3가지 상태를 가진다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 04 Process-1687712593825.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;487&quot; height=&quot;437&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2004%20Process-1687712593825.OjqPAXcs_ZlxTNu.webp&quot; &gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;실행(Running): 프로세스는 명령어를 실행하고 있다.&lt;/li&gt;
&lt;li&gt;준비(Ready): 실행할 준비가 되어 있지만 운영체제가 다른 프로세스를 실행하고 있는 등의 이유로 기다리는 중&lt;/li&gt;
&lt;li&gt;대기(Blocked): 프로세스가 다른 사건을 기다리는 동안 프로세스의 수행을 중단시키는 연산. ex) 디스크에 대한 입출력 요청 → 순차적으로 실행해야 하기 때문에 다 완료될때까지 해당 프로세스는 멈춰있음(blocked).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;운영체제는 어떤 프로세스를 실행할 지 스케쥴러를 통해 결정을 내린다.&lt;/p&gt;
&lt;h2 id=&quot;5-자료구조&quot;&gt;5. 자료구조&lt;/h2&gt;
&lt;p&gt;운영체제는 다른 프로그램들처럼 정보를 유지하기 위한 자료 구조를 가지고 있다.
&lt;img alt=&quot;OSTEP 04 Process-1687712609999.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;750&quot; height=&quot;786&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2004%20Process-1687712609999.CCx8FKRR_Za3cG3.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;프로세스 상태를 파악하기 위한 프로세스 리스트 등.&lt;/p&gt;
&lt;p&gt;운영체제는 이렇게 레지스터 및 프로세스의 상태를 저장하고, 이를 통해 프로세스 실행을 재개한다 (context switch)&lt;/p&gt;
&lt;p&gt;참고: &lt;a href=&quot;https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/&quot;&gt;OSTEP 교재&lt;/a&gt;&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 07 CPU Scheduling</title><link>https://ks1ksi.io/blog/ostep-07-cpu-scheduling/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-07-cpu-scheduling/</guid><description>OSTEP CPU Scheduling 정리. FIFO, SJF, STCF, Round Robin을 반환 시간과 응답 시간 관점에서 비교한다.</description><pubDate>Mon, 03 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;1-워크로드에-대한-가정&quot;&gt;1. 워크로드에 대한 가정&lt;/h2&gt;
&lt;p&gt;일련의 프로세스들이 실행하는 상황을 워크로드라고 부르기로 하자. 우리가 시스템에서 실행 중인 프로세스 혹은 작업에 대해 다음과 같은 가정을 하자.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;모든 작업은 같은 시간 동안 실행된다.&lt;/li&gt;
&lt;li&gt;모든 작업은 동시에 도착한다.&lt;/li&gt;
&lt;li&gt;각 작업은 시작되면 완료될 때까지 실행된다.&lt;/li&gt;
&lt;li&gt;모든 작업은 CPU만 사용한다. 즉 입출력을 수행하지 않는다.&lt;/li&gt;
&lt;li&gt;각 작업의 실행 시간은 사전에 알려져 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;2-스케줄링-평가-항목&quot;&gt;2. 스케줄링 평가 항목&lt;/h2&gt;
&lt;h3 id=&quot;반환-시간-turnaround-time&quot;&gt;반환 시간 (Turnaround Time)&lt;/h3&gt;
&lt;p&gt;작업 반환 시간은 &lt;strong&gt;작업이 완료된 시각에서 작업이 시스템에 도착한 시각을 뺀 시간&lt;/strong&gt;으로 정의된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687805795335.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;497&quot; height=&quot;55&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687805795335.BJf9LQ1P_6K0oT.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;3-first-in-first-out-선입선출&quot;&gt;3. First In First Out (선입선출)&lt;/h2&gt;
&lt;p&gt;가장 기초적인 선입선출 알고리즘. 단순하고 구현하기 쉽다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687805851046.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;757&quot; height=&quot;367&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687805851046.BPQFNAJP_1k4GbW.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 먼저 도착한 작업이 오래 걸리는 경우, 평균 반환 시간이 늘어나게 된다. 그렇다면 다른 좋은 알고리즘은 없을까?&lt;/p&gt;
&lt;h2 id=&quot;4-shortest-job-first-최단-작업-우&quot;&gt;4. Shortest Job First (최단 작업 우)&lt;/h2&gt;
&lt;p&gt;이 문제를 해결하기 위해, 가장 짧은 실행 시간을 가진 작업을 먼저 실행시키자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687805932236.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;753&quot; height=&quot;369&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687805932236.BuNqleTr_yaGVj.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;모든 작업이 동시에 도착한다면, SJF가 optimal한 스케줄링 알고리즘이다. 하지만 A가 먼저 도착하고, B와 C가 도착한다면?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687805997011.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;755&quot; height=&quot;421&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687805997011.CR2fZwgV_QAfAn.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;A가 끝날 때까지 기다릴 수밖에 없고, 평균 반환 시간이 올라간다.&lt;/p&gt;
&lt;h2 id=&quot;5-shortest-time-to-completion-first-최소-잔여시간-우선&quot;&gt;5. Shortest Time-to-Completion First (최소 잔여시간 우선)&lt;/h2&gt;
&lt;p&gt;이 알고리즘은 새로운 작업이 시스템에 들어오면, 남아있는 작업과 새로운 작업의 잔여 실행 시간을 계산하고 그 중 가장 적은 잔여 실행 시간을 가진 작업을 스케줄한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687806121061.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;749&quot; height=&quot;301&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687806121061.Ddfv23vz_ZN1PIa.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;B와 C가 더 빨리 끝나서 평균 반환 시간이 단축된다.&lt;/p&gt;
&lt;h2 id=&quot;6-새로운-평가-기준-응답-시간-response-time&quot;&gt;6. 새로운 평가 기준: 응답 시간 (Response Time)&lt;/h2&gt;
&lt;p&gt;작업의 길이를 미리 알고 있고, 작업이 오직 CPU만 사용하며, 평가 기준이 반환 시간 하나라면, STCF는 매우 훌륭한 알고리즘이다.&lt;/p&gt;
&lt;p&gt;그러나 시분할 컴퓨터의 등장이 모든 것을 바꾸었다. 이제 사용자는 터미널에서 작업하게 되어 시스템에게 상호작용을 원활히 하기 위한 성능을 요구하게 되었다. 응답 시간(response time)이라는 새로운 평가 기준이 태어나게 된다. &lt;strong&gt;응답 시간은 작업이 도착할 때부터 처음 스케줄 될 때까지의 시간&lt;/strong&gt;으로 정의된다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687806264753.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;441&quot; height=&quot;69&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687806264753.Cdr-YjNN_ZqUHaC.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687806287759.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;769&quot; height=&quot;737&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687806287759.mEmhZGAm_vO7r4.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;7-round-robin&quot;&gt;7. Round Robin&lt;/h2&gt;
&lt;p id=&quot;^865cd1&quot;&gt;응답 시간 문제를 해결하기 위하여, 라운드 로빈(RR) 스케줄링이 도입되었다. RR은 작업이 끝날 때까지 기다리지 않는다. 대신 일정 시간 동안 실행한 후 실행 큐의 다음 작업으로 전환한다. 이때 &lt;strong&gt;작업이 실행되는 일정 시간을 타임 슬라이스(time slice) 또는 스케줄링 퀀텀(scheduling quantum)&lt;/strong&gt; 이라 부른다.&lt;/p&gt;
&lt;p&gt;타임 슬라이스가 짧을수록, 응답 시간이 좋아진다. 하지만 너무 짧게 지정하면 문제가 생긴다.
&lt;strong&gt;문맥 교환 비용&lt;/strong&gt;이 전체 성능에 큰 영향을 미치기 때문이다. 따라서 최적의 실이를 결정해야 한다.&lt;/p&gt;
&lt;p&gt;반환 시간이 유일한 측정의 기준인 경우, 라운드 로빈은 거의 최악의 알고리즘이다.&lt;/p&gt;
&lt;h2 id=&quot;8-입출력-연산의-고려&quot;&gt;8. 입출력 연산의 고려&lt;/h2&gt;
&lt;p&gt;4번 가정을 완화하자. 프로그램이 입출력 작업을 수행한다면?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687806591737.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;761&quot; height=&quot;371&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687806591737.FNOqAUVQ_1IXVvQ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;현재 실행중인 작업은 입출력이 완료될 때까지 CPU를 사용하지 않을 것이기 때문에, 스케줄러는 다른 작업을 스케줄해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 07 CPU Scheduling-1687806750918.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;781&quot; height=&quot;361&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2007%20CPU%20Scheduling-1687806750918.DdpCRg89_Z12WBMI.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;9-no-more-oracle&quot;&gt;9. No More Oracle&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;스케줄러가 각 작업의 실행 시간을 알고 있다는 가정은 최악의 가정&lt;/strong&gt;이다. 미래를 예측하는 일은 매우 힘들기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/&quot;&gt;OSTEP 교재&lt;/a&gt; 참고&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>2022 SKKU 프로그래밍 대회 in 소프트의 밤</title><link>https://ks1ksi.io/blog/2022-skku-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%8C%80%ED%9A%8C-in-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9D%98-%EB%B0%A4/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2022-skku-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%8C%80%ED%9A%8C-in-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9D%98-%EB%B0%A4/</guid><description>2022 SKKU 프로그래밍 대회 in 소프트의 밤 후기. 대회 결과와 각 문제의 풀이 아이디어, 다음 대회 목표를 정리했다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;2022 SKKU 프로그래밍 대회 in 소프트의 밤-1673535718388.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;891&quot; height=&quot;1260&quot; src=&quot;https://ks1ksi.io/_astro/2022%20SKKU%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EB%8C%80%ED%9A%8C%20in%20%EC%86%8C%ED%94%84%ED%8A%B8%EC%9D%98%20%EB%B0%A4-1673535718388.CRHoL9W9_23k4HL.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;2022 SKKU 프로그래밍 대회 in 소프트의 밤-1673535724808.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1720&quot; height=&quot;1702&quot; src=&quot;https://ks1ksi.io/_astro/2022%20SKKU%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EB%8C%80%ED%9A%8C%20in%20%EC%86%8C%ED%94%84%ED%8A%B8%EC%9D%98%20%EB%B0%A4-1673535724808.BfbZZohv_Z1zcOqx.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;2022년 10월 27일에 진행한 SKKU 프로그래밍 대회.
하나정도는 더 풀어볼만 했는데 막판에 집중력을 잃고 4솔.. &lt;del&gt;(이론상 입선)&lt;/del&gt;
그래도 올해 초에 참가했던 대회보다는 한 문제 더 풀었다.
내년에는 5솔 이상 하고 10등 안에 들 수 있지 않을까?&lt;/p&gt;
&lt;h2 id=&quot;a-안녕-클레오파트라-세상에서-제일가는-포테이토칩&quot;&gt;A 안녕 클레오파트라 세상에서 제일가는 포테이토칩&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/25904&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;내야 하는 목소리 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;X&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07847em;&quot;&gt;X&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 1씩 늘리면서 확인해보면 된다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번 사람까지 도달한 경우 1번 사람부터 다시 진행할 수 있도록 인덱스를 바꿔준다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(n);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; num &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; num;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cur &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[cur] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cur&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            break&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cur&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (cur &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n) cur &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;b-장인은-도구를-탓하지-않는다&quot;&gt;B 장인은 도구를 탓하지 않는다&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/25905&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;망치 9개를 사용하면 되고, 곱셈 연산이므로 순서에 관계없이 강화 확률이 가장 낮은 망치를 제외한 나머지 망치 9개를 선택하면 된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ld&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; double&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; fixed &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; setprecision&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ld&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sort&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ld ans &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        ans &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ans &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ans &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;c-수렵의-시간이다&quot;&gt;C 수렵의 시간이다!&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/25906&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;현재 가진 돈으로 착용할 수 있는 모든 방어구의 조합을 시도한다. 이 때 &lt;em&gt;&lt;strong&gt;방어구를 착용하지 못하는 경우&lt;/strong&gt;&lt;/em&gt;도 고려해야 한다. 입력받은 방어구에 아무런 효과도 없고 가격도 0인 더미 방어구 한개씩을 추가해주면 편하게 구현할 수 있다.
만약 강화까지 가능하다면, 현재 착용한 방어구에 대해 전부 시도해본다. 스킬 레벨 증가량을 올릴 스킬과 내릴 스킬도 전부 시도해본다.
실수할 여지가 굉장히 많은 문제다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;skills&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt;&gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;items&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; calculate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; money&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;item1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;item2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;item3) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; item1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; item2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; item3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (tc &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; money) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ret &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; item1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; item2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; item3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        ret &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; skills&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i][&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;min&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;skills&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i])];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (money &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tc) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // down&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;            lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; // up&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[j]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; k&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                    tmp &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; skills&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[k][&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;min&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;skills&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[k]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[k])];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                ret &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; max&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(ret&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; tmp);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[j]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;            lv&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ret;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; skills) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sz;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sz;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;push_back&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sz; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;            v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;push_back&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(x);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; items) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sz;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sz;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;resize&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(sz&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;            v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;second&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;push_back&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sz; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sz; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;second&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;push_back&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(x);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ans &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(); i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(); j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(); k&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                ans &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; max&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(ans&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; calculate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(t&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;][i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;][j]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;][k]));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ans &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;d-양과-늑대&quot;&gt;D 양과 늑대&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/25907&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;첫 번째 날에는 항상 양이 도착하고, 마지막 날에는 항상 늑대의 수가 양의 수보다 많고, 하루에 늑대 혹은 양이 한 마리씩 도착하기 때문에 1번째 날부터 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날중 적어도 하루 이상 늑대와 양의 수가 같아진다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mo&gt;&amp;#x3C;&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;lo &amp;#x3C;= hi&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7335em;vertical-align:-0.0391em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고,  &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid = (lo+hi)/2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라 하자.&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날에 양과 늑대의 수가 같다면 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날이 정답이다.&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번쨰 날에 양이 더 많다면, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid+1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7778em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날과 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;hi&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날 사이에 정답이 존재한다.&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날에 늑대가 더 많다면 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;lo&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날과 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mid-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7778em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번째 날 사이에 정답이 존재한다.
인터랙티브 문제라 출력 이후 버퍼를 &lt;code&gt;flush&lt;/code&gt; 해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; hi &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cnt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; hi) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; hi) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;? &quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; endl;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cnt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (cnt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid) lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (cnt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid) hi &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;! &quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; endl;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            break&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;e-수열의-합&quot;&gt;E 수열의 합&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/25908&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sum_{i=S}^{T}{a_i}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.2809em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9812em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3117em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sum_{i=1}^{T}{a_i}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.2809em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9812em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.13889em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3117em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; - &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sum_{i=1}^{S-1}{a_i}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.2809em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9812em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mbin mtight&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3117em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 이므로 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sum_{i=1}^{N}{a_i}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.2809em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9812em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3117em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 을 구하면 된다.
 어떤 양의 정수 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;는 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/msubsup&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sum_{i=1}^{N}{a_i}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.2809em;vertical-align:-0.2997em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mop op-symbol small-op&quot; style=&quot;position:relative;top:0em;&quot;&gt;∑&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.9812em;&quot;&gt;&lt;span style=&quot;top:-2.4003em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mrel mtight&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.2029em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2997em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3117em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 &lt;strong&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;과 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;N&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 사이에 존재하는 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 배수의 개수만큼&lt;/strong&gt; 기여한다. 홀수이면 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mfrac&gt;&lt;mo stretchy=&quot;false&quot;&gt;⌋&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(-1) \times \lfloor \frac{N}{d} \rfloor&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.2173em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;⌊&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8723em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;⌋&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 만큼, 짝수이면 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mfrac&gt;&lt;mo stretchy=&quot;false&quot;&gt;⌋&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;(1) \times \lfloor \frac{N}{d} \rfloor&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;×&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.2173em;vertical-align:-0.345em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;⌊&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mopen nulldelimiter&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mfrac&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8723em;&quot;&gt;&lt;span style=&quot;top:-2.655em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.23em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;frac-line&quot; style=&quot;border-bottom-width:0.04em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.394em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.345em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose nulldelimiter&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;⌋&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 만큼 기여한다. 배수를 일일히 구하면 시간 초과를 받을 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; solve&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ret &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        ret &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;i)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ret;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; s &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; solve&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(t) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; solve&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(s&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;f-수확의-계절이다&quot;&gt;F 수확의 계절이다!&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/25909&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 고정시켜 놓고, 주어진 입력을 따라가면 총 몇 개의 작물을 수확할 수 있는지 나온다. Parametric Search 가능. 세트 수 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\times&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;×&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 진행 횟수 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;= M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.3669em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이 최대 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;1,000,000&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이므로 매번 길을 따라가면 시간 초과를 받게 되고, 미리 좌표마다 언제 도착하는지 전처리를 할 필요가 있다.
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;-1,000,000 \le x \le 1,000,000&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7719em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이고, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;-1,000,000 \le y \le 1,000,000&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8304em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8389em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라서 2차원 배열을 만들 수 없다. &lt;code&gt;map&lt;/code&gt;에 좌표와 방문 시점을 기록한다. 매번 2차원 배열에 기록했는데 &lt;code&gt;map&lt;/code&gt;을 쓰는 방식도 알아둬야겠다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(n);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    map&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    map&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;char&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mm;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    mm&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&apos;N&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    mm&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&apos;S&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    mm&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&apos;E&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    mm&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt;&apos;W&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [dy&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dx] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; mm&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[a];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            y &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dy;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            x &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dx;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;            m&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[{y&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x}]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace_back&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;t);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; hi &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1000000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; hi) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cnt &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; hi) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(); j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                    if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[j] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                    else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                        cnt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                        i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;                        break&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (cnt &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k) hi &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        else&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; lo &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; mid &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; hi &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>ps</category><category>skku</category></item><item><title>2022 성균관대학교 프로그래밍 경진대회</title><link>https://ks1ksi.io/blog/2022-%EC%84%B1%EA%B7%A0%EA%B4%80%EB%8C%80%ED%95%99%EA%B5%90-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C/</link><guid isPermaLink="true">https://ks1ksi.io/blog/2022-%EC%84%B1%EA%B7%A0%EA%B4%80%EB%8C%80%ED%95%99%EA%B5%90-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C/</guid><description>2022 성균관대학교 프로그래밍 경진대회 후기. 첫 프로그래밍 대회 참가 경험과 문제 풀이 감상을 짧게 남긴 글.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;2022 성균관대학교 프로그래밍 경진대회-1673535690327.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2694&quot; height=&quot;1331&quot; src=&quot;https://ks1ksi.io/_astro/2022%20%EC%84%B1%EA%B7%A0%EA%B4%80%EB%8C%80%ED%95%99%EA%B5%90%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-1673535690327.BONMSZLR_kbmjx.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;22년 2월에 싸지방에서 진행한 대회. 살면서 처음으로 프로그래밍 대회에 참가했는데, 백준에서 태그 까고 시간제한 없이 문제 푸는거랑은 완전 다른 느낌.
어? 세그먼트 트리? 하고 뚝딱뚝딱 짰는데 알고보니 그냥 누적합 문제였다.&lt;/p&gt;</content:encoded><category>ps</category><category>skku</category></item><item><title>Bulk Insert</title><link>https://ks1ksi.io/blog/bulk-insert/</link><guid isPermaLink="true">https://ks1ksi.io/blog/bulk-insert/</guid><description>Bulk Insert 성능 개선 기록. JPA TABLE 키 생성 전략과 배치 삽입 병목을 JDBC 기반 insert로 줄인 과정을 정리한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;JPA Bulk Insert-1674903588761.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1196&quot; height=&quot;310&quot; src=&quot;https://ks1ksi.io/_astro/JPA%20Bulk%20Insert-1674903588761.16qZ4szU_Z1GymFQ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;교내 학생들이 푼 백준 문제를 모두 DB에 넣는 배치 프로그램을 작성했는데 속도가 너무 느리다. 이를 개선해보자.&lt;/p&gt;
&lt;p&gt;우선 PK 생성 전략이 TABLE으로 되어 있어서,  IDENTITY로 변경했다. 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀸스를 흉내내는 전략인데, 최적화 되어있지 않은 테이블을 직접 사용하기 때문에 성능이 나오지 않는다. IDENTITY 전략은 기본 키 생성을 데이터베이스에 위임하는 전략이다. (DDL로 기본키에 AUTO_INCREMENT 걸기)&lt;/p&gt;
&lt;p&gt;이렇게 하면 JPA로 BATCH INSERT를 할 수없다. 잠시 JPA를 놓아주고 JDBC를 사용해보자.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; skku&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;skkujoon&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;repository&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; lombok&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;RequiredArgsConstructor&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; org&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;jdbc&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;JdbcTemplate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; org&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;stereotype&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;Repository&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; skku&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;skkujoon&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;domain&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;Problem&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; skku&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;skkujoon&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;domain&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;User&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; java&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;sql&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;PreparedStatement&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; java&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ArrayList&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; java&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; * Only for batch insert&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; * &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;@author&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; ks1ksi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;RequiredArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; JdbcRepository&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; final&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; JdbcTemplate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; jdbcTemplate;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; insertUsers&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;User&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt; users) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        String&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sql &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;insert into user (handle, bio, solved_count, tier, rating, ranking, global_rank) values (?, ?, ?, ?, ?, ?, ?)&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        jdbcTemplate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;batchUpdate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(sql&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                users&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                users&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                (ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; u) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getHandle&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getBio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getSolvedCount&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getTier&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getRating&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getRanking&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getGlobalRank&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; insertProblems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;Problem&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt; problems) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        String&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sql &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;insert into problem (problem_number, title_ko, level, solved_by_skku, solvable, partial) values (?, ?, ?, ?, ?, ?)&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        jdbcTemplate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;batchUpdate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(sql&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                problems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                problems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                (ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setLong&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getProblemNumber&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getTitleKo&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getLevel&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getSolvedBySkku&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setBoolean&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;isSolvable&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setBoolean&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;isPartial&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; insertUserProblems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;User&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; user&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;Problem&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt; problems) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        String&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sql &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;insert into user_problem (user_id, problem_id) values (?, ?)&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        jdbcTemplate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;batchUpdate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(sql&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                problems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                problems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                (ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setLong&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; user&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getId&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setLong&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getId&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; updateProblems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;Problem&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt; problems) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        String&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; sql &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &quot;update problem set solved_by_skku = solved_by_skku + 1 where problem_id = ?&quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        jdbcTemplate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;batchUpdate&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(sql&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                problems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                problems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                (ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                    ps&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;setLong&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;getId&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;                });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;Bulk Insert-1674963763722.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1346&quot; height=&quot;250&quot; src=&quot;https://ks1ksi.io/_astro/Bulk%20Insert-1674963763722.CqmEVNst_ZG0DzU.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;7시간 넘게 걸리던걸 1시간으로 줄였다. solved.ac api 호출 제한이 있어서 시간을 더 줄이기는 힘들 것 같다.&lt;/p&gt;</content:encoded><category>cs</category><category>db</category><category>java</category></item><item><title>JOIN</title><link>https://ks1ksi.io/blog/join/</link><guid isPermaLink="true">https://ks1ksi.io/blog/join/</guid><description>SQL JOIN 정리. Cross, Natural, Inner, Outer, Self Join의 문법과 주의점을 예시 중심으로 정리한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;cross-join&quot;&gt;Cross Join&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; table1, table2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;join&lt;/code&gt; 조건 생략. 데카르트 곱.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;natural-join&quot;&gt;Natural Join&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; departments&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;natural join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; locations&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;두 테이블에 공통 컬럼이 있는 경우 묵시적으로 조인.&lt;/li&gt;
&lt;li&gt;컬럼명 겹쳐서 엉뚱한 결과가 나올 수 있으니 주의.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;inner-join&quot;&gt;Inner Join&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;inner join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; departments d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(e.department_id &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; d.department_id)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;inner&lt;/code&gt; 키워드 생략 가능.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ANSI&lt;/strong&gt; 표준 문법.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;on&lt;/code&gt; 절에 조인 조건 작성.(&lt;code&gt;where&lt;/code&gt; 절에도 작성 가능)&lt;/li&gt;
&lt;li&gt;컬럼명이 같은 경우 다음과 같이 &lt;code&gt;using&lt;/code&gt; 절을 사용해도 무방함.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;inner join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; departments&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(department_id)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;oracle-방식&quot;&gt;Oracle 방식&lt;/h3&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t1.col1, t1.col2, t2.col1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; table1 t1, table2 t2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;where&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t1.col3 &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; t2.col3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;from&lt;/code&gt; 절에 필요로 하는 테이블을 모두 적는다. (&lt;code&gt;alias&lt;/code&gt; 사용 가능)&lt;/li&gt;
&lt;li&gt;적절한 조건을 &lt;code&gt;where&lt;/code&gt; 절에 부여한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;outer-join&quot;&gt;Outer Join&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;left outer join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; departments d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(e.department_id &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; d.department_id)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;left(right) outer join&lt;/code&gt;: 왼쪽(오른쪽)의 모든 튜플은 결과 테이블에 나타남.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;full outer join&lt;/code&gt;: 양쪽 모두 결과 테이블에 나타남.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;outer&lt;/code&gt; 키워드 생략 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;self-join&quot;&gt;Self Join&lt;/h2&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; e.name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;사원 이름&apos;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;, m.name &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &apos;상사 이름&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; employees m&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(e.manager_id &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; m.employee_id)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;같은 테이블에 &lt;code&gt;alias&lt;/code&gt; 다르게 주고 &lt;code&gt;join&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>cs</category><category>db</category></item><item><title>OSTEP 05 Process API</title><link>https://ks1ksi.io/blog/ostep-05-process-api/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-05-process-api/</guid><description>OSTEP Process API 정리. fork, wait, exec 시스템 콜과 쉘, 파이프, 시그널 등 프로세스 API의 동작을 요약한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;1-fork-시스템-콜&quot;&gt;1. &lt;code&gt;fork()&lt;/code&gt; 시스템 콜&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687712682168.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;895&quot; height=&quot;707&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687712682168.Buuv5ocw_ZnVRfb.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;현재 실행중인 프로세스의 복사본을 생성&lt;/strong&gt;한다. 운영체제가 새로운 프로세스를 생성하고 이 새로운 프로세스는 &lt;strong&gt;원본 프로세스의 메모리 공간을 복사&lt;/strong&gt;하여 가지게 된다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;부모 프로세스에는 새로 생성된 자식 프로세스의 PID를 반환&lt;/strong&gt;하고, &lt;strong&gt;자식 프로세스에는 0을 반환&lt;/strong&gt;한다. &lt;strong&gt;반환값이 다르기 때문에 부모, 자식 프로세스가 서로 다른 작업을 하도록 코드를 짤 수 있다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rc&lt;/code&gt;에 어떤 값이 리턴되었는지 확인하면, 현재 실행중인 프로세스가 부모 프로세스인지, 자식 프로세스인지 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687712698353.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;534&quot; height=&quot;149&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687712698353.D9AVoWVo_2d7EWh.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;CPU Scheduler가 실행할 프로세스를 선택하는데 이 때 자식 프로세스가 먼저 실행될 수 있다. 항상 부모 프로세스가 먼저 실행되는 것은 아니다.&lt;/p&gt;
&lt;h2 id=&quot;2-wait-시스템-콜&quot;&gt;2. &lt;code&gt;wait()&lt;/code&gt; 시스템 콜&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687712816426.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;914&quot; height=&quot;583&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687712816426.CQ6d6dPf_1JNUFn.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;부모 프로세스가 자식 프로세스가 종료될 때까지 기다리게 하는 시스템 콜. &lt;strong&gt;이 함수를 호출하면 부모 프로세스는 자식 프로세스가 종료될 때까지 블록된다.&lt;/strong&gt; 자식 프로세스가 종료되면 운영 체제는 부모 프로세스에게 제어를 반환하고. 자식 프로세스의 종료 상태를 부모 프로세스에게 전달한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687712855061.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;710&quot; height=&quot;137&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687712855061.Xo4NqihV_13o5bo.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;두 가지 case 모두 자식 프로세스가 먼저 출력한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;부모 프로세스가 먼저 실행되는 경우 -&gt; 바로 &lt;code&gt;wait()&lt;/code&gt;을 호출. 이 시스템 콜은 자식 프로세스가 종료될 때까지 리턴하지 않는다. -&gt; 자식 프로세스가 먼저 출력한다.&lt;/li&gt;
&lt;li&gt;자식 프로세스가 먼저 실행되는 경우 -&gt; 자식 프로세스가 먼저 출력한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;3-exex-시스템-콜&quot;&gt;3. &lt;code&gt;exex()&lt;/code&gt; 시스템 콜&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687713059554.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;919&quot; height=&quot;728&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687713059554.CqnJoYgS_12iPAl.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;현재 실행중인 프로세스의 메모리 공간을 새로운 프로그램으로 대체하는 시스템 콜. 이 함수를 호출하면 운영체제는 &lt;strong&gt;현재 프로세스의 메모리 공간을 세로운 프로그램으로 대체하고, 새로운 프로그램의 메인 함수를 실행한다.&lt;/strong&gt; 자기 자신이 아닌 다른 프로그램을 실행해야 할 때 사용한다. &lt;strong&gt;exex() 함수가 성공하면 기존 프로그램은 리턴하지 않는다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687713142622.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;681&quot; height=&quot;151&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687713142622.CuQcqF76_22zrBX.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;execvp()&lt;/code&gt; 시스템 콜을 호출하면, 자식 프로세스의 메모리 공간이 새로운 프로그램인 &lt;code&gt;wc&lt;/code&gt;로 대체되고, 원래 자식 프로세스는 리턴되지 않는다.&lt;/p&gt;
&lt;h2 id=&quot;4-왜-이런-api를&quot;&gt;4. 왜 이런 API를?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;UNIX의 쉘을 구현하기 위해서는 &lt;code&gt;fork()&lt;/code&gt;와 &lt;code&gt;exec()&lt;/code&gt;을 분리해야 한다. 그래야만 쉘이 &lt;code&gt;fork()&lt;/code&gt; 를 호출하고 &lt;code&gt;exec()&lt;/code&gt;를 호출하기 전에 코드를 실행할 수 있다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;쉘은 프롬프트를 표시하고 사용자가 무언가 입력하기를 기다린다. 그리고 명령어를 입력한다. 대부분의 쉘은 파일 시스템에서 실행 파일의 위치를 찾고 명령어를 실행하기 위하여 &lt;code&gt;fork()&lt;/code&gt;를 호출하여 새로운 자식 프로세스를 만든다. 그런 후 &lt;code&gt;exec()&lt;/code&gt;의 변형 중 하나를 호출하여 프로그램을 실행시킨 후 &lt;code&gt;wait()&lt;/code&gt;을 호출하여 명령어가 끝나기를 기다린다. 자식 프로세스가 종료되면 쉘은 &lt;code&gt;wait()&lt;/code&gt;으로부터 리턴하고 다시 프롬프트를 출력하고 다음 명령어를 기다린다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687713360756.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;918&quot; height=&quot;776&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687713360756.DuILHcyA_o1Aw.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 05 Process API-1687713373694.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;495&quot; height=&quot;119&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2005%20Process%20API-1687713373694.DgQ-iWzg_12Xnou.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;p4&lt;/code&gt;를 실행하면 화면에 아무런 일도 일어나지 않는다.
그러나 실제로는 다음과 같은 일이 발생하였다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;p4&lt;/code&gt;는 &lt;code&gt;fork()&lt;/code&gt;를 호출하여 새로운 자식 프로세스를 생성한다.&lt;/li&gt;
&lt;li&gt;그리고 &lt;code&gt;wait()&lt;/code&gt; 호출 후 대기한다.&lt;/li&gt;
&lt;li&gt;자식 프로세스는 출력을 재지정한다. (2번, 3번 어떤 일이 먼저 발생하는지 알 수 없음)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;execvp()&lt;/code&gt;를 호출하여 &lt;code&gt;wc&lt;/code&gt;프로그램을 실행시킨다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;UNIX 파이프가 이와 유사한 방식으로 구현되지만, &lt;code&gt;pipe()&lt;/code&gt; 시스템 콜을 통해 생성된다. 한 프로세스의 출력과 다른 프로세스의 입력이 동일한 파이프에 연결된다. 한 프로세스의 출력은 자연스럽게 다음 프로세스의 입력으로 사용되고, 명령어 체인으로 사용된다.&lt;/p&gt;
&lt;h2 id=&quot;5-기타-api&quot;&gt;5. 기타 API&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kill()&lt;/code&gt; 시스템 콜은 프로세스에게 시그널을 보낸다. 시그널은 프로세스의 중단, 삭제 등의 작업에 사용된다. 시그널이라는 메커니즘은 외부 사건을 프로세스에게 전달하는 토대이다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ps&lt;/code&gt; 명령어는 어떤 프로세스가 실행중인지 알아보기 위해 사용된다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;top&lt;/code&gt; 역시 시스템에 존재하는 프로세스와 그 프로세스가 cpu 및 다른 자원들을 얼마나 사용하고 있는지를 보여준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;참고: &lt;a href=&quot;https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/&quot;&gt;OSTEP 교재&lt;/a&gt;&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 06 Direct Execution</title><link>https://ks1ksi.io/blog/ostep-06-direct-execution/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-06-direct-execution/</guid><description>OSTEP Direct Execution 정리. 제한적 직접 실행, 사용자/커널 모드, trap, timer interrupt와 context switch를 설명한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;여러 작업들이 동시에 실행되는 것처럼 보이도록 하는 방법 -&gt; CPU 시간을 나누어 쓰면 된다. 한 프로세스를 잠시동안 실행하고, 다른 프로세스를 또 잠깐 실행하고 하면서 물리적인 CPU를 공유한다.
이런 &lt;strong&gt;가상화 기법&lt;/strong&gt;을 구현하기 위해서 몇가지 문제를 해결해야 한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;성능 저하 -&gt; 시스템에 과중한 오버헤드를 주지 않으면서 가상화를 구현할 수 있을까?&lt;/li&gt;
&lt;li&gt;제어 문제 -&gt; CPU에 대한 통제를 유지 + 효율적으로 프로세스를 실행 -&gt; 제어권을 일으면 한 프로세스가 영원히 실행을 계속하게 될지도 모름.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;1-기본-원리-제한적-직접-실행limited-direct-execution&quot;&gt;1. 기본 원리: 제한적 직접 실행(Limited Direct Execution)&lt;/h2&gt;
&lt;p&gt;직접 실행 -&gt; 프로그램을 CPU 상에서 &lt;strong&gt;그냥&lt;/strong&gt; 실행시킨다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 06 Direct Execution-1687714891040.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;806&quot; height=&quot;579&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2006%20Direct%20Execution-1687714891040.7IAlJwTC_1p6vlU.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;이렇게 하면 프로그램이 &lt;strong&gt;운영체제가 원치않는 일을 하게 될 수 있다&lt;/strong&gt;.
또 &lt;strong&gt;어떻게 프로그램의 실행을 중단하고 다른 프로세스로 전환시킬지&lt;/strong&gt; 고민도 해야 한다. -&gt; CPU 가상화에 필요한 시분할(time sharing) 기법.&lt;/p&gt;
&lt;p&gt;따라서 &lt;strong&gt;제한적&lt;/strong&gt;으로 프로그램을 실행시켜야 한다. 프로그램 실행에 제한을 두지 않으면 운영체제는 아무것도 제어할 수 없는 단순한 라이브러리가 된다.&lt;/p&gt;
&lt;h2 id=&quot;2-문제점-1-제한된-연산&quot;&gt;2. 문제점 1: 제한된 연산&lt;/h2&gt;
&lt;p&gt;물리적인 CPU에서 직접 실행하면 빠르게 실행된다. 하지만 &lt;strong&gt;프로세스가 특수한 종류의 연산 (디스크 입출력 요청 및 CPU, 메모리 추가할당 요청 등)을 수행하길 원한다면?&lt;/strong&gt;
예를 들어  파일에 대한 접근 권한을 부여하기 전에, 권한을 확인하는 파일 시스템을 만든다고 하자. 이 때 프로세스가 디스크에 대해 입출력하는 것을 제한하지 않으면 프로세스는 전체 디스크를 읽고 쓸 수 있기 때문에 검사하는 의미가 없다.&lt;/p&gt;
&lt;p&gt;이 때문에 &lt;strong&gt;사용자 모드(user mode)와 커널 모드 (kernel mode)&lt;/strong&gt; 가 도입되었다.
user mode에서는 수행할 수 있는 작업에 제한을 두고, 제한된 작업은 kernel mode에서만 수행할 수있도록 했다. 예를 들어, 파일 입출력과 같은 작업은 kernel mode에서만 수행된다.&lt;/p&gt;
&lt;p&gt;user mode인 프로세스가 입출력과 같은 작업을 실행하고 싶다면 제공되는 &lt;strong&gt;시스템 콜&lt;/strong&gt;을 사용한다. 커널은 시스템 콜을 통하여 자신의 주요 기능을 사용자 프로그램에게 제공한다. 이러한 기능에는 파일 시스템 접근, 프로세스 생성 및 제거, 다른 프로세스와의 통신 및 메모리 할당 등이 포함된다.&lt;/p&gt;
&lt;p&gt;시스템 콜을 실행하기 위해 프로그램은 &lt;strong&gt;trap&lt;/strong&gt;이라는 특수 명령어를 실행해야 한다. 이 명령어는 커널 안으로 분기하는 동시에 &lt;strong&gt;kernel mode&lt;/strong&gt;로 현재 특권 수준을 상향 조정한다.
이렇게 kernel mode로 진입하면 운영체제는 모든 명령어를 실행할 수 있고, 완료되면 &lt;strong&gt;return from trap&lt;/strong&gt; 특수 명령어를 통해 다시 &lt;strong&gt;user mode&lt;/strong&gt;로 특권 수준을 하향한다.&lt;/p&gt;
&lt;p&gt;커널은 부팅 시에 &lt;strong&gt;트랩 테이블(trap table)&lt;/strong&gt; 을 만들고 이를 이용하여 시스템을 통제한다. 운영체제가 하는 초기 작업 중 하나는 하드웨어에게 예외 사건이 일어났을 때 어떤 코드를 실행해야 하는지 알려주는 일이다. 예를 들어, 하드 디스크 인터럽트가 발생하면, 키보드 인터럽트가 발생하면, 또는 프로그램이 시스템 콜을 호출 하면 무슨 코드를 실행해야 하는지 알려준다. 운영체제는 특정 명령어를 사용하여 하드웨어에게 트랩 핸들러(trap handler)의 위치를 알려준다. 하드웨어는 이 정보를 전달받으면 해당 위치를 기억하고 있다. 따라서 시스템 콜과 같은 예외적인 사건이 발생했을 때 하드웨어는 무엇을 해야 할지 (즉, 어느 코드로 분기하여 실행할지) 알 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;운영체제에서 인터럽트는 하드웨어나 소프트웨어에서 발생하는 예기치 않은 이벤트를 의미합니다. 이벤트는 현재 실행 중인 프로그램의 흐름을 중단하고 운영체제에게 처리를 요청합니다. 인터럽트는 시스템의 일부분에 발생하는 중단 신호로 이해할 수 있습니다. 인터럽트는 여러 가지 상황에서 발생할 수 있습니다. 몇 가지 주요한 인터럽트 유형은 다음과 같습니다&lt;/p&gt;
&lt;p&gt;하드웨어 인터럽트: 하드웨어 장치에서 발생하는 이벤트로, 예를 들어 타이머 인터럽트, 입출력 장치에서의 완료 신호, 하드웨어 오류 등이 있습니다.
소프트웨어 인터럽트: 프로그램 실행 중 명령에 의해 발생하는 이벤트로, 주로 시스템 콜이나 예외 상황에 의해 발생합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 06 Direct Execution-1687803828132.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1079&quot; height=&quot;1229&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2006%20Direct%20Execution-1687803828132.w8Eat55k_1AKiFe.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;3-문제점-2-프로세스-간-전환&quot;&gt;3. 문제점 2: 프로세스 간 전환&lt;/h2&gt;
&lt;p&gt;운영체제는 실행 중인 프로세스를 계속 실행할 것인지, 멈추고 다른 프로세스를 실행할 것인지 결정해야 한다. 이는 까다로운 문제이다.&lt;/p&gt;
&lt;p&gt;CPU에서 프로세스가 실행 중이라는 것은 운영체제는 실행중이지 않다는 것을 의미한다. 운영체제가 실행하고 있지 않다면 어떻게 이런 일들을 할 수 있을까?&lt;/p&gt;
&lt;h3 id=&quot;협조-방식-시스템-콜-기다리기&quot;&gt;협조 방식: 시스템 콜 기다리기&lt;/h3&gt;
&lt;p&gt;협조 방식은 일부 과거 시스템에서 사용된 방법으로, 운영체제가 프로세스들이 합리적으로 행동할 것이라고 가정한다.
프로세스들은 주기적으로 CPU 제어를 운영체제에게 양보해야 한다는 가정하에 동작한다.
주로 시스템 콜을 호출하여 CPU 제어를 운영체제에게 넘겨준다.&lt;/p&gt;
&lt;h3 id=&quot;비협조-방식-운영체제가-전권을-행사&quot;&gt;비협조 방식: 운영체제가 전권을 행사&lt;/h3&gt;
&lt;p&gt;프로세스가 협조하지 않거나 시스템 콜을 호출하지 않아 운영체제에게 제어를 넘기지 않을 경우, 운영체제는 추가적인 도움 없이 제어를 획득하기 어렵다.
이를 해결하기 위해 타이머 인터럽트 기능을 사용한다. 타이머 인터럽트는 정기적으로 발생하여 운영체제에게 CPU 제어를 양도합니다.&lt;/p&gt;
&lt;h3 id=&quot;문맥-교환-context-switching&quot;&gt;문맥 교환 (Context Switching)&lt;/h3&gt;
&lt;p&gt;문맥 교환은 프로세스 전환이 일어날 때 현재 실행 중인 프로세스의 상태를 저장하고 다음에 실행될 프로세스의 상태를 복원하는 과정이다.
문맥 교환은 운영체제의 스케줄러에 의해 결정된다.
레지스터 값과 스택 포인터 등의 상태를 저장하고 복원하여 제어를 전환다.&lt;/p&gt;
&lt;h3 id=&quot;타이머-인터럽트와-문맥-교환&quot;&gt;타이머 인터럽트와 문맥 교환&lt;/h3&gt;
&lt;p&gt;타이머 인터럽트는 정기적으로 발생하여 운영체제에게 CPU 제어를 양도하는 역할을 한다.
타이머 인터럽트가 발생하면 현재 실행 중인 프로세스의 레지스터 값을 저장하고, 다음에 실행될 프로세스의 레지스터 값을 복원한다.
이를 통해 운영체제는 다른 프로세스로 전환하여 실행을 계속할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 06 Direct Execution-1687804532825.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;993&quot; height=&quot;1149&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2006%20Direct%20Execution-1687804532825.Brj1qRKd_Ifavx.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 06 Direct Execution-1687804564886.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;879&quot; height=&quot;747&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2006%20Direct%20Execution-1687804564886.0ParL_M2_Z1vVUIa.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;4-concurrency&quot;&gt;4. Concurrency?&lt;/h2&gt;
&lt;p&gt;인터럽트 처리 중 다른 인터럽트가 발생하면 어떻게 할 것인지, 시스템 콜 처리 중 timer interrupt가 발생하면 어떤 것을 먼저 처리할지?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Disable Interrupt -&gt; 다른 인터럽트 처리 중일 때 발생하는 인터럽트 무시&lt;/li&gt;
&lt;li&gt;Priority -&gt; 인터럽트에 우선순위를 두어 순차적으로 처리&lt;/li&gt;
&lt;li&gt;Locking Mechanism -&gt; Lock 기법 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/&quot;&gt;OSTEP 교재&lt;/a&gt; 참고&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 08 Multi-level Feedback Queue, MLFQ</title><link>https://ks1ksi.io/blog/ostep-08-multi-level-feedback-queue-mlfq/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-08-multi-level-feedback-queue-mlfq/</guid><description>OSTEP MLFQ 정리. 우선순위 큐, 라운드 로빈, 우선순위 하향과 상향 조정으로 응답 시간과 반환 시간을 개선하는 스케줄링을 요약한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;MLFQ가 해결하고자 하는 문제는 두 가지이다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;짧은 작업을 먼저 실행시켜 &lt;strong&gt;반환 시간&lt;/strong&gt;을 최적화하고자 한다.&lt;/li&gt;
&lt;li&gt;대화형 사용자에게 응답이 빠른 시스템이라는 느낌을 주도록 &lt;strong&gt;응답 시간&lt;/strong&gt;을 최적화하고자 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;어떻게 하면 작업의 실행 시간에 대한 선행 정보 없이 응답 시간과 반환 시간을 동시에 최소화할 수 있을까?&lt;/p&gt;
&lt;h2 id=&quot;1-mlfq-기본-규칙&quot;&gt;1. MLFQ: 기본 규칙&lt;/h2&gt;
&lt;p&gt;MLFQ는 여러 개의 큐로 구성되며, 각 큐에는 다른 우선순위가 부여된다. 실행 준비가 된 프로세스는 이 중 하나의 큐에 존재하며, MLFQ는 실행할 프로세스를 결정하기 위해 우선순위를 사용한다. 같은 우선순위를 가진 작업들 사이에서는 라운드 로빈 스케줄링 알고리즘이 사용된다.&lt;/p&gt;
&lt;p&gt;MLFQ의 두 가지 기본 규칙은 다음과 같다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;규칙 1: Priority(A) &gt; Priority(B) 이면, A가 실행된다 (B는 실행되지 않는다).&lt;/li&gt;
&lt;li&gt;규칙 2: Priority(A) = Priority(B) 이면, A와 B는 &lt;strong&gt;RR 방식&lt;/strong&gt;으로 실행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 08 Multi-level Feedback Queue, MLFQ-1687808739461.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;515&quot; height=&quot;477&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2008%20Multi-level%20Feedback%20Queue_%20MLFQ-1687808739461.CAQnpGIa_184nn8.webp&quot; &gt;&lt;/p&gt;
&lt;h2 id=&quot;2-시도-1-우선순위의-변경&quot;&gt;2. 시도 1: 우선순위의 변경&lt;/h2&gt;
&lt;p&gt;MLFQ는 작업의 우선순위를 동적으로 변경한다. 작업이 키보드 입력을 기다리며 반복적으로 CPU를 양보하면 MLFQ는 해당 작업의 우선순위를 높게 유지한다. 반면에 작업이 긴 시간 동안 CPU를 집중적으로 사용하면 MLFQ는 해당 작업의 우선순위를 낮춘다.&lt;/p&gt;
&lt;p&gt;우선순위 변경에 대한 추가 규칙은 다음과 같다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;규칙 3: &lt;strong&gt;작업이 시스템에 진입하면, 가장 높은 우선순위&lt;/strong&gt;, 즉 맨 위의 큐에 놓여진다.&lt;/li&gt;
&lt;li&gt;규칙 4a: &lt;strong&gt;주어진 타임 슬라이스를 모두 사용하면 우선순위는 낮아진다&lt;/strong&gt;. 즉, 한 단계 아래 큐로 이동한다.&lt;/li&gt;
&lt;li&gt;규칙 4b: &lt;strong&gt;타임 슬라이스를 소진하기 전에 CPU를 양도하면 같은 우선순위를 유지&lt;/strong&gt;한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;예시-1-한-개의-긴-실행-시간을-가진-작업&quot;&gt;예시 1: 한 개의 긴 실행 시간을 가진 작업&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 08 Multi-level Feedback Queue, MLFQ-1687808781509.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;715&quot; height=&quot;437&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2008%20Multi-level%20Feedback%20Queue_%20MLFQ-1687808781509.DtAom8o1_iSU5z.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;긴 실행 시간을 가진 작업이 도착했을 때, 작업은 최고 우선순위로 진입한다. 타임 슬라이스가 지나면 스케줄러는 작업의 우선순위를 한 단계 낮추어 해당 작업을 아래 큐로 이동시킨다. 이 과정이 반복되어 작업은 결국 가장 낮은 우선순위를 가지게 된다.&lt;/p&gt;
&lt;h3 id=&quot;예시-2-짧은-작업과-함께&quot;&gt;예시 2: 짧은 작업과 함께&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 08 Multi-level Feedback Queue, MLFQ-1687808800094.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;533&quot; height=&quot;413&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2008%20Multi-level%20Feedback%20Queue_%20MLFQ-1687808800094.alNDfIrM_Z1gSmXl.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;2개의 작업이 존재하는 경우를 가정해보자. A는 오래 실행되는 CPU 위주 작업이고 B는 짧은 대화형 작업이다. A는 이미 실행 중이고 B는 이제 도착했다고 가정하면, B는 높은 우선순위를 부여받아 빨리 실행되고 바로 종료된다. 이후에 A는 낮은 우선순위에서 실행을 재개한다.&lt;/p&gt;
&lt;h3 id=&quot;예시-3-입출력-작업에-대해서는-어떻게&quot;&gt;예시 3: 입출력 작업에 대해서는 어떻게?&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 08 Multi-level Feedback Queue, MLFQ-1687808844209.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;831&quot; height=&quot;439&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2008%20Multi-level%20Feedback%20Queue_%20MLFQ-1687808844209.BU34UQKi_1kMiH2.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;입출력 작업을 수행하는 경우, &lt;strong&gt;프로세스가 타임 슬라이스를 소진하기 전에 CPU를 양도하면 같은 우선순위를 유지하게 된다.&lt;/strong&gt; 이 규칙은 대화형 작업이 키보드나 마우스로부터 사용자 입력을 대기하며 자주 입출력을 수행하면 타임 슬라이스가 종료되기 전에 CPU를 양도하게 될 것이라는 점을 반영한 것이다. 이 경우, MLFQ는 해당 작업을 빠르게 실행시키기 위해 우선순위를 높게 유지한다.&lt;/p&gt;
&lt;h3 id=&quot;현재-mlfq의-문제점&quot;&gt;현재 MLFQ의 문제점&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;기아 상태가 발생할 수 있다. 시스템에 대화형 작업이 많이 존재하면, 그들이 모든 CPU 시간을 소모하고, 긴 실행 시간 작업은 CPU 시간을 할당받지 못하여 굶어 죽는다.&lt;/li&gt;
&lt;li&gt;스케줄러가 자신에게 유리하게 작동하도록 프로그램을 다시 작성할 수 있다. 타임 슬라이스가 끝나기 전에 아무 입출력 요청을 내려 CPU를 양도하도록 짠다면?&lt;/li&gt;
&lt;li&gt;프로그램이 시간 흐름에 따라 특성이 바뀔 수 있다. (CPU 위주 작업 -&gt; 대화형 작업)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;3-시도-2-우선순위-상향-조정&quot;&gt;3. 시도 2: 우선순위 상향 조정&lt;/h2&gt;
&lt;p&gt;새로운 규칙은 다음과 같다.&lt;/p&gt;
&lt;p&gt;규칙 5: 일정 기간 S가 지나면, 시스템의 모든 작업을 최상위 큐로 이동시킨다.&lt;/p&gt;
&lt;p&gt;새 규칙은 두 가지 문제를 한 번에 해결한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;프로세스는 굶지 않는다는 것을 보장받는다. 최상위 큐에 존재하는 동안 작업은 다른 높은 우선순위 작업들과 라운드 로빈 방식으로 CPU를 공유하게 되고 서비스를 받게 된다.&lt;/li&gt;
&lt;li&gt;CPU 위주의 작업이 대화형 작업으로 특성이 변할 경우 우선순위 상향을 통해 스케줄러가 변경된 특성에 적합한 스케줄링 방법을 적용한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;4-시도-3-더-나은-시간-측정&quot;&gt;4. 시도 3: 더 나은 시간 측정&lt;/h2&gt;
&lt;p&gt;스케줄러를 자신에게 유리하게 동작시키는 것을 어떻게 막을 수 있는가?
규칙 4를 재정의하자.&lt;/p&gt;
&lt;p&gt;규칙 4: 주어진 단계에서 시간 할당량을 소진하면 (CPU를 몇 번 양도하였는지 상관없이), 우선순위는 낮아진다 (즉, 아래 단계의 큐로 이동한다).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 08 Multi-level Feedback Queue, MLFQ-1687809290188.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1101&quot; height=&quot;449&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2008%20Multi-level%20Feedback%20Queue_%20MLFQ-1687809290188.CN8n2Zgc_ZVPt7d.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;방지책이 마련되면 프로세스의 입출력 행동과 무관하게 아래 단계 큐로 천천히 이동하게 되어 CPU를 자기 몫 이상으로 사용할 수 없게 된다.&lt;/p&gt;
&lt;h2 id=&quot;5-mlfq-조정과-다른-쟁점들&quot;&gt;5. MLFQ 조정과 다른 쟁점들&lt;/h2&gt;
&lt;p&gt;몇 개의 큐가 존재해야 하는가? 큐당 타임 슬라이스의 크기는 얼마로 해야 하는가? 기아를 피하고 변화된 행동을 반영하기 위하여 얼마나 자주 우선순위가 상향 조정되어야 하는가?&lt;/p&gt;
&lt;p&gt;큐의 우선순위에 따라 타임 슬라이스의 크기를 다르게 설정한다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;OSTEP 08 Multi-level Feedback Queue, MLFQ-1687809532148.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;655&quot; height=&quot;419&quot; src=&quot;https://ks1ksi.io/_astro/OSTEP%2008%20Multi-level%20Feedback%20Queue_%20MLFQ-1687809532148.Bld7DERJ_oNnS7.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Solaris의 MLFQ 구현 테이블의 기본 값&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;큐의 개수는 60&lt;/li&gt;
&lt;li&gt;각 큐의 타임 슬라이스 크기는 가장 높은 우선순위 큐가 20ms 에서 가장 낮은 우선순위 큐가 수백ms 까지 천천히 증가&lt;/li&gt;
&lt;li&gt;우선순위 상향 조정은 약 1초 마다 일어난다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;6-요약&quot;&gt;6. 요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;규칙 1 : 우선순위 (A)&gt; 우선순위 (B) 일 경우, A가 실행, B는 실행되지 않는다.&lt;/li&gt;
&lt;li&gt;규칙 2 : 우선순위 (A) = 우선순위 (B), A와 B는 RR 방식으로 실행된다.&lt;/li&gt;
&lt;li&gt;규칙 3 : 작업이 시스템에 들어가면 최상위 큐에 배치된다.&lt;/li&gt;
&lt;li&gt;규칙 4 : 작업이 지정된 단계에서 배정받은 시간을 소진하면 (CPU를 포기한 횟수와 상관없이), 작업의 우선순위는 감소한다 (즉, 한 단계 아래 큐로 이동한다).&lt;/li&gt;
&lt;li&gt;규칙 5 : 일정 주기 S가 지난 후, 시스템의 모든 작없을 최상위 큐로 이동시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/&quot;&gt;OSTEP 교재&lt;/a&gt; 참고&lt;/p&gt;</content:encoded><category>cs</category><category>os</category></item><item><title>OSTEP 교재</title><link>https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/</link><guid isPermaLink="true">https://ks1ksi.io/blog/ostep-%EA%B5%90%EC%9E%AC/</guid><description>OSTEP 운영체제 교재와 한국어 번역, KAIST 강의 자료 링크를 모아둔 참고 자료 글.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://pages.cs.wisc.edu/~remzi/OSTEP/&quot;&gt;영어책&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/remzi-arpacidusseau/ostep-translations/tree/master/korean&quot;&gt;한글책&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://oslab.kaist.ac.kr/ostepslides/&quot;&gt;KAIST OSTEP 강의, 교안&lt;/a&gt;&lt;/p&gt;</content:encoded><category>os</category><category>cs</category></item><item><title>SELECT</title><link>https://ks1ksi.io/blog/select/</link><guid isPermaLink="true">https://ks1ksi.io/blog/select/</guid><description>SQL SELECT 실행 흐름 정리. WHERE, GROUP BY, HAVING, ORDER BY의 역할과 조건 적용 순서를 간단히 요약한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;DISTINCT&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) 컬럼명(ALIAS)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; 테이블명&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; 조건식&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; 컬럼명&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;HAVING&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; 조건식&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; 컬럼명 혹은 표현식 (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;ASC&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; 혹은 &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt;로 먼저 조건을 걸고, &lt;code&gt;GROUP BY&lt;/code&gt;로 그룹을 나누고, 나눈 그룹에서 또 &lt;code&gt;HAVING&lt;/code&gt;으로 조건 걸기.&lt;/p&gt;</content:encoded><category>cs</category><category>db</category></item><item><title>SW 마에스트로 14기 합격 후기</title><link>https://ks1ksi.io/blog/sw-%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C-14%EA%B8%B0-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</link><guid isPermaLink="true">https://ks1ksi.io/blog/sw-%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C-14%EA%B8%B0-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0/</guid><description>SW 마에스트로 14기 합격 후기. 자소서, 1·2차 코딩테스트, 면접 질문과 준비 과정, 합격 후 소감을 정리했다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;SW 마에스트로 14기 합격 후기-1679681733083.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;2076&quot; height=&quot;572&quot; src=&quot;https://ks1ksi.io/_astro/SW%20%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C%2014%EA%B8%B0%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1679681733083.DTiCl5er_ZbGckX.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;예전부터 굉장히 하고싶었던 소프트웨어 마에스트로에 붙어버렸다!
후기 써야지 써야지 하다 결국 한달이 밀려버렸다.&lt;/p&gt;
&lt;h2 id=&quot;자소서&quot;&gt;자소서&lt;/h2&gt;
&lt;p&gt;면접 시간이 굉장히 짧아서 3천자 꽉 채워서 내기보다는, 핵심만 간결하게 적어서 내는게 더 좋아보인다. 쓸데없는 말, 면접때 대답하지 못할 말은 적지 말자.&lt;/p&gt;
&lt;h3 id=&quot;자기소개1&quot;&gt;[자기소개1]&lt;/h3&gt;
&lt;p&gt;소프트웨어분야 전문성을 키우기 위해 남들과 달리 특별한 노력을 한 경험을 서술하여 주시기 바랍니다. (최소 400자, 최대 3,000자 입력가능) – 1021자&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;문제 해결 능력을 기르기 위해 알고리즘 문제를 열심히 푼 경험&lt;/li&gt;
&lt;li&gt;내가 필요했던 서비스를 개발한 경험&lt;/li&gt;
&lt;li&gt;그 서비스를 개발하는 과정에서 발생한 문제와, 이를 해결한 경험&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;자기소개2&quot;&gt;[자기소개2]&lt;/h3&gt;
&lt;p&gt;귀하의 장래희망을 서술하여 주시기 바랍니다. (최소 400자, 최대 3,000자 입력가능) – 833자&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;어떤 개발자가 되고 싶은지&lt;/li&gt;
&lt;li&gt;수많은 분야 중에서 왜 백엔드 개발자를 선택했는지&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;연수계획서-1&quot;&gt;[연수계획서 1]&lt;/h3&gt;
&lt;p&gt;귀하께서는 2023년도 「SW마에스트로」 과정에서 동료 연수생들과 협력하여 새로운 프로젝트를 완성하여야 합니다. 어떤 능력을 갖춘 연수생들과 어떠한 프로젝트를 어떻게 수행할 것인지 귀하의 구체적인 계획을 서술하여 주시기 바랍니다. (최소 400자, 최대 3,000자 입력가능) – 738자&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서로 다른 관심사를 가진 사람들끼리 모여 프로젝트를 진행하고 싶다.&lt;/li&gt;
&lt;li&gt;교육과 관련된 서비스를 개발하고 싶다.&lt;/li&gt;
&lt;li&gt;정확히 어떤 서비스인지&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;연수계획서-2&quot;&gt;[연수계획서 2]&lt;/h3&gt;
&lt;p&gt;2023년도 「SW마에스트로」 과정에서는 연수생에게 장학금, IT기기, 프로젝트 활동비 등을 지원할 예정이며, 본인이 희망하는 온라인 강의와 프로젝트 수행을 도와주는 멘토를 통해 귀하의 SW능력을 향상 및 발전시킬 수 있는 기회를 제공하고 있습니다. 앞으로 귀하께서 본 과정을 통해 이루고자하는 목표가 무엇인지 구체적으로 서술하여 주시기 바랍니다. (최소 400자, 최대 3,000자 입력가능) – 645자&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;사람들이 많이 사용하는 서비스 기획부터 배포까지 해보고싶다.&lt;/li&gt;
&lt;li&gt;지원금 주는걸로 서버비 왕창 쓸거다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;1차-코딩테스트&quot;&gt;1차 코딩테스트&lt;/h2&gt;
&lt;p&gt;작년에는 알고리즘, SQL, 웹(HTML, CSS, JS) 나왔는데 올해부터는 웹 문제가 사라지고 알고리즘과 SQL 문제만 나왔다. 웹 문제 나오면 깔끔하게 버리려고 했는데 기분이 굉장히 좋았다. 알고리즘 4문제 + SQL 1문제.&lt;/p&gt;
&lt;h3 id=&quot;1번&quot;&gt;1번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;단순 구현&lt;/li&gt;
&lt;li&gt;그냥 시키는대로 하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2번&quot;&gt;2번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;구현&lt;/li&gt;
&lt;li&gt;십자가 모양 구하는 문제였나? 해당 좌표를 지나는 가로줄 세로줄 구분해서 &lt;code&gt;pair&amp;#x3C;int, int&gt;&lt;/code&gt;에 집어넣으면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3번&quot;&gt;3번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;조합 탐색&lt;/li&gt;
&lt;li&gt;도미노 문제. 그리디로 풀어야 할 것 같지만 도미노 없애는 조합 다 구해서 완전탐색 하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4번&quot;&gt;4번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;BFS&lt;/li&gt;
&lt;li&gt;현재 젓가락 상태를 &lt;code&gt;set&amp;#x3C;string&gt;&lt;/code&gt;에 집어넣고 같은 상태는 방문하지 않도록 한다. 시험볼땐 약간 애매하게 풀었다. DFS + &lt;code&gt;map&amp;#x3C;string, int&gt;&lt;/code&gt;로 TC는 다 돌게 했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;5번-sql&quot;&gt;5번 (SQL)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;정규식?&lt;/li&gt;
&lt;li&gt;SQL 문자열 함수도 잘 모르고 정규식도 몰라서 풀지 않았다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;시험 중간에 서버가 터져서 추가시간이 주어졌다. 덕분에 1번부터 4번까지 다 풀었다.
근데 나중에 보니까 전원 2차 코딩테스트까지 올려줬더라. 억울해..&lt;/p&gt;
&lt;h2 id=&quot;2차-코딩테스트&quot;&gt;2차 코딩테스트&lt;/h2&gt;
&lt;p&gt;똑같이 알고리즘 4문제 + SQL 1문제. 확실히 1차보다 어려웠다.&lt;/p&gt;
&lt;h3 id=&quot;1번-1&quot;&gt;1번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;문자열&lt;/li&gt;
&lt;li&gt;화살표 앞에서부터 쭉 읽으면서 주어진 조건대로 처리하면 된다. Case 두개로 나뉘는 부분만 살짝 조심하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2번-1&quot;&gt;2번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;그리디 + 이분탐색?&lt;/li&gt;
&lt;li&gt;가장 충전량 많은 충전소 하나 고르고, 그 충전소보다 앞에 있는 충전소중에 가장 충전량 많은 충전소 고르고.. 이 과정을 충전량순으로 정렬해서 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(NlogN)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.01968em;&quot;&gt;Nl&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 수행할 수 있다. 각 충전소에서 몇 초 기다려야 하는지는 이분탐색으로 구하면 될 것 같았는데 시간이 모자라서 대충 주석만 써두고 제출했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3번-1&quot;&gt;3번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;큐&lt;/li&gt;
&lt;li&gt;문제가 비문학마냥 길고 낚시도 있지만 그냥 나오지 못한사람들 다 &lt;code&gt;queue&lt;/code&gt;에 때려박고 나올 수 있을 때 처리해주면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4번-1&quot;&gt;4번&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;플로이드? DP?&lt;/li&gt;
&lt;li&gt;정해가 뭔지 모르겠다. 이번 코딩테스트에서 가장 어려운 문제였다. 각 노드간 최단거리는 무조건 구해야 하니 플로이드는 맞는 것 같은데.. 최단거리 구하고 그 최단거리로 DP 어떻게 슥삭 하면 될 것 같은데.. 생각만 하다 결국 손도 못 댄 문제다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;5번-sql-1&quot;&gt;5번 (SQL)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;JOIN, UNION, IFNULL&lt;/li&gt;
&lt;li&gt;프로그래머스에 있는 모든 SQL문제를 다 풀고 자신감이 흘러넘쳐서 SQL부터 달려들었다. 근데 &lt;code&gt;UNION&lt;/code&gt; 까먹어서 결국 서브쿼리 떡칠로 풀어버렸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1차 4솔(1, 2, 3, 4) + 2차 3솔(1, 3, 5)로 코테 통과하고, 면접장에 가게 되었다.&lt;/p&gt;
&lt;h2 id=&quot;면접&quot;&gt;면접&lt;/h2&gt;
&lt;p&gt;면접은 목금토 총 3일동안 진행됐고, 나는 3월 16일 목요일이었다. 하필 첫날 면접에, 수업이랑 겹쳤다. 목요일만 아니면 됐는데..&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SW 마에스트로 14기 합격 후기-1682698684769.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;1316&quot; height=&quot;1270&quot; src=&quot;https://ks1ksi.io/_astro/SW%20%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C%2014%EA%B8%B0%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1682698684769.CxuY47qB_GkHkQ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;작년 13기부터 면접때 3분 포트폴리오 발표가 추가되었다고 한다. Notion에 자기 포트폴리오를 작성해서 내면 된다. 자기소개 + 활동내역 + 프로젝트 2개 써서 냈다.&lt;/p&gt;
&lt;p&gt;노션 페이지 속에 프로젝트 페이지를 만들고 들어가서 볼 수 있도록 구성했는데, 좋지 않은 선택이었다. 면접장 발표 컴퓨터가 좀 느려서 페이지 열어도 로딩 한참 걸린다. 그냥 한 페이지 안에 다 때려박자.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SW 마에스트로 14기 합격 후기-1682699238482.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;3000&quot; height=&quot;4000&quot; src=&quot;https://ks1ksi.io/_astro/SW%20%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C%2014%EA%B8%B0%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1682699238482.Bt6-FDhk_Z1aG7qM.webp&quot; &gt;
&lt;img alt=&quot;SW 마에스트로 14기 합격 후기-1682699244680.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;3000&quot; height=&quot;4000&quot; src=&quot;https://ks1ksi.io/_astro/SW%20%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C%2014%EA%B8%B0%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1682699244680.Jm7XATBh_ZH51y5.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;나는 3분과 1번이었다. 우리 분과는 대부분 공통 질문이었다. 개인 질문을 많이 하지는 않았다. 819기 선임이랑 면접준비를 한게 도움이 많이 됐다.&lt;/p&gt;
&lt;h3 id=&quot;공통-질문&quot;&gt;공통 질문&lt;/h3&gt;
&lt;ul&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;li&gt;소마에서 하고싶은 프로젝트&lt;/li&gt;
&lt;li&gt;MBTI(성격) 뭔지 말해보고 소마에 어떻게 녹여낼 것인지&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;개인-질문&quot;&gt;개인 질문&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;백엔드 개발자라고 하셨는데 MSA가 뭔지 설명해주세요.&lt;/li&gt;
&lt;li&gt;스프링 말고 다른거 써보셨어요?&lt;/li&gt;
&lt;li&gt;팀원이 스프링 말고 노드 쓰자고 하면 어떻게 할 예정인가요?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1번이라 자꾸 공통질문 나부터 시켜서 생각할 시간 없이 막 대답했다. 개인 질문도 내 자소서 + 포폴 + 코테 위주로 준비했는데 그런거 하나도 안물어보고 쓴적도 없는 MSA같은거 물어봐서 그냥 막 대답했다. 왜 붙었는지 모르겠다. 다른 분과는 포트폴리오 기술질문 엄청 deep하게 물어봤다고 한다.&lt;/p&gt;
&lt;p&gt;면접에 온 사람은 5분과 × 5명 × 5타임 × 3일 = 총 375명이다.
이중 260명을 선발했다. 원래 235명 선발 예정이었지만, 탈주자를 고려해 선발한 것 같다. 작년에는 300명 넘게 뽑았는데 너무 많이 뽑아서 올해는 좀 줄였다고 한다.
여담인데 우리부대 사람 4명이나 소마 붙었다. 역시 공군 전산병..&lt;/p&gt;
&lt;p&gt;아무튼 붙어버렸다. 사지방에서 하루종일 백준 풀던게 효과가 있었나보다. 열심히 해야겠다. 지금 예비 연수 기간인데도 너무 힘들다. 시간표도 참담한데 여기서 어떻게든 몸 비틀어서 연수센터 나가는 나.. 다음학기는 아마 휴학 혹은 최소학점만 수강할 예정이다.&lt;/p&gt;
&lt;p&gt;4월 7일 ~ 8일 오리엔테이션도 다녀왔다.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SW 마에스트로 14기 합격 후기-1682700563172.jpeg&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;  width=&quot;4000&quot; height=&quot;3000&quot; src=&quot;https://ks1ksi.io/_astro/SW%20%EB%A7%88%EC%97%90%EC%8A%A4%ED%8A%B8%EB%A1%9C%2014%EA%B8%B0%20%ED%95%A9%EA%B2%A9%20%ED%9B%84%EA%B8%B0-1682700563172.tCs8tB3G_20dwH4.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;밤새고 발표도 했다. 피곤 MAX&lt;/p&gt;</content:encoded><category>life</category><category>dev</category></item><item><title>그래프 최단경로 알고리즘 정리</title><link>https://ks1ksi.io/blog/%EA%B7%B8%EB%9E%98%ED%94%84-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC/</link><guid isPermaLink="true">https://ks1ksi.io/blog/%EA%B7%B8%EB%9E%98%ED%94%84-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC/</guid><description>그래프 최단경로 알고리즘 정리. 다익스트라, 벨만 포드, 플로이드 워셜의 사용 조건과 시간복잡도, 구현 포인트를 비교한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;다익스트라-dijkstra&quot;&gt;다익스트라 (Dijkstra)&lt;/h2&gt;
&lt;p&gt;시작 정점에서, 다른 모든 정점까지의 최단거리를 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;log&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(E\log V)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;lo&lt;span style=&quot;margin-right:0.01389em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.22222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 구할 수 있다. 모든 간선을 한 번씩 확인하기 때문에 인접 리스트로 구현. 최단거리가 여러 번 갱신된 경우 (&lt;code&gt;cost &gt; dist[cur]&lt;/code&gt;) 스킵. cost가 낮은 간선부터 확인.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;priority_queue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; greater&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; pq;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; dijkstra&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; start&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; end) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    fill&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;MAX&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; INF);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[start] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; start);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;empty&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        auto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [cost&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cur] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;top&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pop&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (cost &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[cur]) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [ncost&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; next] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; adj&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[cur]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[next] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[cur] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ncost) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[next] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[cur] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ncost;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;                pq&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[next]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; next);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[end];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;벨만-포드-bellman---ford&quot;&gt;벨만 포드 (Bellman - Ford)&lt;/h2&gt;
&lt;p&gt;시작 정점에서, 다른 모든 정점까지의 최단거리를 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(EV)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.22222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;에 구할 수 있다. 다익스트라 알고리즘과는 달리 &lt;strong&gt;음의 간선&lt;/strong&gt;이 존재해도 주어진 시간 안에 최단거리를 구할 수 있다. 최단경로는 아무리 길어도 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;V-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.22222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;개의 간선을 포함하고 있을 것이다. 따라서 간선 완화를 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;V-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.22222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번 진행한다. 만약 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;V-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.22222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;번 진행 이후에도 최단거리가 짧아진다면, 이는 &lt;strong&gt;음의 사이클&lt;/strong&gt;을 가지고 있는 것이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; start &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;fill&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;MAX&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; INF);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[start] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; neg &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; N; k&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; N; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; INF) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; adj&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;			auto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [cost&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; next] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;			if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[next] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cost) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;				dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[next] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; cost;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;				if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; N&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) neg &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;			}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;플로이드-와샬-floyd---warshall&quot;&gt;플로이드 와샬 (Floyd - Warshall)&lt;/h2&gt;
&lt;p&gt;모든 정점에서, 다른 모든 정점까지의 최단거리를 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;O(N^3)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0641em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.02778em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.10903em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 에 구할 수 있다.
반복문 순서에 유의한다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;dist(i, j)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05724em;&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;dist(i, k) + dist(k, j)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03148em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03148em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05724em;&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 비교하는데, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;k&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03148em;&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 고정시켜놓고 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i, j&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.854em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05724em;&quot;&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;를 움직인다. 다이나믹 프로그래밍의 일종.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (r&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;][b&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;	dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[b&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;][a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i][j]) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i][j] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i][j] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;// i -&gt; j vs i -&gt; k -&gt; j&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; k &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; k&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;		for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;			dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i][j] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; min&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i][j]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i][k] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[k][j]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>ps</category><category>graph</category></item><item><title>백준  2261번 가장 가까운 두 점</title><link>https://ks1ksi.io/blog/%EB%B0%B1%EC%A4%80--2261%EB%B2%88-%EA%B0%80%EC%9E%A5-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EB%91%90-%EC%A0%90/</link><guid isPermaLink="true">https://ks1ksi.io/blog/%EB%B0%B1%EC%A4%80--2261%EB%B2%88-%EA%B0%80%EC%9E%A5-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EB%91%90-%EC%A0%90/</guid><description>백준 2261번 가장 가까운 두 점 풀이. x좌표 스위핑과 y좌표 기준 set을 이용해 후보 점만 검사하며 최단 거리를 갱신한다.</description><pubDate>Sun, 02 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2261&quot;&gt;문제 링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;좌표 기준으로 정렬 후 앞에서부터 스위핑.
지금까지 찾은 최단 거리를 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, 이번에 거리를 잴 점을 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;p&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;라 할 때, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;좌표, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;좌표가 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;p&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;와 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;이상 차이나는 점은 확인할 필요가 없다.
&lt;code&gt;set&lt;/code&gt;에 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;좌표 기준으로 점을 넣어 두면서, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;좌표가 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;보다 멀리 있는 점은 삭제한다. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;p_y - d \le q_y \le p_y + d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8694em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8304em;vertical-align:-0.136em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9221em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;≤&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8694em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.03588em;&quot;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 인 점 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;q&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.03588em;&quot;&gt;q&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;의 범위를 &lt;code&gt;lower_bound()&lt;/code&gt;로 찾아서 최단 거리를 계산한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground); overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;#include&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;#x3C;bits/stdc++.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; std;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ld&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; long&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; double&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; Compare&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    bool&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; operator&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; p2) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; make_pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; make_pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; square&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; powdist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt; p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;&gt; p2) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; square&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; square&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;p1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; p2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ios_base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;sync_with_stdio&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    cin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;tie&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    vector&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(n);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [a&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; v) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        cin &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;    sort&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;begin&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    set&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;pair&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; ll&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; Compare&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; st;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    ll dist &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; powdist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    st&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;    st&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; n; i&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        while&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (j &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; square&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[j]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;first) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dist) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;            st&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;erase&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[j&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        ll d &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; sqrt&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(dist) &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        auto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; start &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; st&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;lower_bound&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; d});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        auto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; end &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; st&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;upper_bound&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;second &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; d});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;auto&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; it &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; start; it &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; end; it&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;            dist &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; min&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(dist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt; powdist&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;it));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;        st&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-function)&quot;&gt;emplace&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;[i]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;    cout &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; dist;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;set&lt;/code&gt;는 &lt;code&gt;operator()&lt;/code&gt;를 오버로딩하는 &lt;code&gt;Compare&lt;/code&gt; 구조체를 받는다. 적절한 코드를 작성하여 &lt;code&gt;set&lt;/code&gt;에 있는 원소가 정렬되는 순서를 조절할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/Iv-KOgzQ-G8&quot;&gt;IOI KOREA 유튜브의 나정휘 선생님 강의&lt;/a&gt;를 참고했다.&lt;/p&gt;
&lt;p&gt;다음주 목요일 (5월 4일)에 나정휘 선생님이 우리학교에 ICPC 대비 강연은 하러 오신다는데 넘 신기하다. 블로그 잘 보고 있다고 얘기해야겠다.&lt;/p&gt;</content:encoded><category>boj</category><category>ps</category></item></channel></rss>