본문으로 이동
주 메뉴
주 메뉴
사이드바로 이동
숨기기
둘러보기
대문
최근 바뀜
임의 문서로
~ldmsys
검색
검색
외관
로그인
개인 도구
로그인
현재 모든 문서는 작성 중입니다. 보시는 데 불편함이 있더라도 양해 부탁드립니다.
운영체제 기본/프로세스와 스레드 문서 원본 보기
문서
토론
한국어
읽기
원본 보기
역사 보기
도구
도구
사이드바로 이동
숨기기
작업
읽기
원본 보기
역사 보기
일반
여기를 가리키는 문서
가리키는 글의 최근 바뀜
문서 정보
외관
사이드바로 이동
숨기기
←
운영체제 기본/프로세스와 스레드
문서 편집 작업을 수행할 권한이 없습니다. 다음 이유를 확인해주세요:
요청한 작업은 다음 권한을 가진 사용자에게 제한됩니다:
사용자
.
문서의 원본을 보거나 복사할 수 있습니다.
[[운영체제 기본|목차]] · 이전: [[운영체제 기본/장치 제어와 입출력|장치 제어와 입출력]] · 다음: [[운영체제 기본/동시성|동시성]] [[운영체제 기본/추상화#프로세스가 제공하는 실행 환경|프로세스는 프로그램에 제공하는 논리적인 머신]]이다. CPU의 실행 흐름은 스레드로, 메모리는 가상 주소 공간으로, 장치 접근은 파일과 입출력 객체로 구성된다. '''프로세스'''는 이 자원과 보호 경계를 묶고, '''스레드'''는 그 안에서 명령을 실행한다.<ref name="process-model">[https://mit-pdos.github.io/xv6-riscv-book/first.html MIT PDOS, xv6: Operating system organization], 프로세스와 격리.</ref> 이 구분을 통해 자원의 소유와 실행 순서를 별도로 관리할 수 있다. 프로그램 하나를 프로세스 하나, 스레드 하나로 실행할 수도 있고, 같은 자원을 여러 스레드가 공유하게 할 수도 있다. == 실행 파일만으로는 실행 상태를 표현할 수 없다 == 실행 파일에는 코드와 초기 데이터가 있다. 실행 중에는 다음 명령의 위치, 레지스터 값, 함수 호출 스택, 동적으로 할당한 메모리, 열린 입출력 대상 등도 필요하다. 같은 실행 파일을 두 번 실행하더라도 이 상태는 다를 수 있다. 운영체제는 실행을 중단했다가 다시 이어갈 수 있도록 실행 문맥을 관리한다. 스레드마다 레지스터와 스택이 필요한 이유도 여기에 있다. 같은 함수를 실행하더라도 각 호출의 인자와 지역 변수, 돌아갈 위치는 달라야 한다. 실행 문맥을 새로 만드는 일과 실행할 프로그램을 바꾸는 일도 구분된다. Unix 계열에서는 프로세스를 생성하는 연산과 기존 프로세스의 실행 이미지를 교체하는 연산이 분리되어 있다. 생성과 실행을 나누면 새 프로그램을 시작하기 전에 입출력 연결이나 실행 환경을 구성할 수 있다. 대신 어떤 상태를 상속하고 어떤 상태를 초기화할지 명확한 규칙이 필요하다. <ref name="source-1">[https://man7.org/linux/man-pages/man2/fork.2.html fork(2)].</ref><ref name="source-2">[https://man7.org/linux/man-pages/man2/execve.2.html execve(2)].</ref> == 격리를 늘리면 전달 비용이 생긴다 == 여러 요청을 처리하는 서버를 생각해 보자. 요청별 작업을 서로 다른 주소 공간에 두면 한 작업의 잘못된 메모리 쓰기가 다른 작업의 사적인 메모리를 직접 덮어쓰지 않는다. 요청 하나의 실패가 다른 요청으로 번지는 범위를 줄일 수 있다. 대신 결과나 공통 데이터를 주고받을 통신 경로가 필요하다. 메시지에 담을 데이터 표현을 정해야 하고, 구현에 따라 복사와 직렬화, 커널 경계 통과 비용이 발생한다. 공유 메모리로 복사를 줄일 수 있지만, 그 영역에는 다시 접근 규칙과 동기화가 필요하다. 같은 프로세스 안에서 스레드를 늘리면 주소 공간과 열린 파일 등을 공유하므로 포인터로 같은 객체를 다룰 수 있다. 연결과 전달이 간단해지는 대신, 잘못된 쓰기와 공유 상태의 오염도 다른 스레드에 영향을 준다. 스레드별 스택은 독립적인 실행 상태이지, 서로 접근할 수 없는 보호 경계는 아니다. <ref name="source-3">[https://man7.org/linux/man-pages/man7/pthreads.7.html pthreads(7)].</ref> 따라서 프로세스와 스레드의 선택은 생성 비용만으로 결정되지 않는다. 공유할 데이터의 양, 장애를 격리할 범위, 통신 비용, 동기화 복잡도를 함께 고려해야 한다. 별도 프로세스도 같은 파일이나 공유 메모리를 변경한다면 경쟁 문제가 생긴다. == CPU를 나누는 방법 == 실행 가능한 흐름이 CPU보다 많으면 순서를 정해야 한다. 운영체제는 한 스레드의 문맥을 보관하고 다른 스레드의 문맥을 복원해 실행을 넘긴다. 이것이 '''컨텍스트 스위치(Context Switch)'''이다. 논리 CPU 하나에서는 여러 흐름이 번갈아 진행하고, 여러 논리 CPU에서는 병렬 실행도 가능하다. 실행 중인 작업이 자발적으로 CPU를 내놓게 하는 방식은 전환 지점이 명확하다. 그러나 오래 실행하거나 양보하지 않는 작업이 다른 작업을 지연시킬 수 있다. '''선점'''은 운영체제가 실행을 중단시켜 다른 작업에 기회를 주는 방식이다. 응답성과 공정성을 확보하는 데 유리하지만, 프로그램은 예상하지 못한 지점에서 실행 순서가 바뀔 수 있음을 전제로 해야 한다. 일반적인 선점형 시분할에서는 [[운영체제 기본/장치 제어와 입출력#타이머 인터럽트와 선점|타이머 인터럽트]]가 실행 중인 작업의 협조 없이 CPU 제어권을 되찾을 기회를 만든다. 인터럽트가 발생할 때마다 반드시 다른 스레드로 전환하는 것은 아니다. 전환 간격을 짧게 하면 실행 가능한 다른 작업이 빨리 기회를 얻을 수 있다. 반면 문맥 저장·복원 비용이 늘고, 캐시와 주소 변환 캐시를 다시 채우는 비용이 발생할 수 있다. 길게 실행시키면 이런 비용을 줄일 여지가 있지만 짧은 작업의 응답 시간이 길어질 수 있다. 처리량, 응답 시간, 공정성, 마감 시간 준수는 서로 다른 목표다. 대화형 작업과 일괄 계산, 실시간 작업에 같은 선택이 최선일 수는 없다. <ref name="source-4">[https://man7.org/linux/man-pages/man7/sched.7.html sched(7)].</ref> == 기다리는 작업에 CPU를 주지 않는 이유 == 네트워크 응답이 도착하지 않았거나 필요한 입출력이 끝나지 않았다면 CPU를 더 준다고 작업이 진행되지는 않는다. 이때 실행 흐름을 대기 상태로 두고, 진행할 수 있는 다른 작업에 CPU를 주는 편이 자원 사용에 유리하다. 입출력을 기다리며 잠든 작업은 무엇이 다시 실행 가능하게 만드는가? 장치가 [[운영체제 기본/장치 제어와 입출력#입출력 완료와 깨우기|인터럽트로 완료를 통지]]하는 구성에서는 커널이 완료 상태를 확인하고 해당 요청을 기다리던 작업을 깨운다. 타이머 인터럽트가 선점 기회를 만드는 것과, 장치 인터럽트가 대기 조건의 변화를 알리는 것은 역할이 다르다. 장치의 상태를 폴링하여 완료를 알아내는 방식도 있다. 상태 전이는 다음과 같다. <pre> 실행 가능 ── 선택 ──> 실행 중 ↑ │ └──── 선점 ────────┤ │ 입출력·사건 대기 v 대기 중 │ 입출력 완료 등 └────────> 실행 가능 </pre> '''깨우기는 대기 중인 작업을 실행 가능 상태로 바꾸는 일'''이다. 장치 인터럽트가 발생했다고 곧바로 그 작업으로 컨텍스트 스위치를 하는 것은 아니다. 다시 실행 가능한 후보가 되었으며, 실제 실행 시점은 스케줄링에 달려 있다. 따라서 작업의 완료 시간에는 계산 시간뿐 아니라 실행 기회를 기다리는 시간과 외부 조건을 기다리는 시간도 포함된다. 대기를 사용하는 설계는 다른 작업에 CPU를 돌려줄 수 있지만, 멈추고 깨우는 처리와 스케줄링 비용이 있다. 아주 짧은 대기라면 잠시 상태를 반복 확인하는 편이 유리할 수도 있다. 이 선택과 공유 상태의 정확성 문제는 [[운영체제 기본/동시성|동시성]]에서 다룬다. == 관련 각론 == * [[운영체제 기본/x86-64 Linux의 부팅/PID 1 생성|PID 1 생성]]: 기존 부트 태스크와 새 실행 문맥이 갈라지는 과정. == 참고 문헌 == <references />
운영체제 기본/프로세스와 스레드
문서로 돌아갑니다.
검색
검색
운영체제 기본/프로세스와 스레드 문서 원본 보기
새 주제