1. 프로세스 간 통신
1.1. 프로세스 간 통신의 개념
1.2. 프로세스 간 통신의 분류
1.3. 프로세스 간 통신의 종류
2. 공유 자원과 임계 구역
2.1. 공유 자원의 접근
2.2. 임계 구역
2.3. 생산자-소비자 문제
2.4. 임계 구역 해결 조건
3. 임계 구역 해결 방법
3.1. 기본 코드 소개
3.2. 임계 구역 해결 조건을 고려한 코드 설계
3.3. 피터슨 알고리즘
3.4. 데커 알고리즘
3.5. 세마포어
3.6. 모니터
4. [심화학습] 파일, 파이프, 소켓 프로그래밍
4.1. 파일
4.2. 파이프
4.3. 네트워킹
1. 프로세스 간 통신
1.1. 프로세스 간 통신의 개념
IPC(Inter-Process Communication)
프로세스 간 통신이라는 개념으로, 같은 컴퓨터라는 1대의 기기 내의 프로세스끼리 통신한다.
뿐만 아니라, 네트워크로 연결된 다른 컴퓨터에 있는 프로세스와의 통신도 포함되는 개념이다.
프로세스 간 통신에는 크게 2가지 통신이 있다.
1. 운영체제의 도움이 필요없는 통신 방법으로, 전역 변수나 파일을 사용하는 방법이다.
2. 운영체제의 도움이 필요한 통신 방법으로, 파이프, 소켓, 원격 프로시저 호출(RPC)을 사용하는 방법이다.
└ RPC : Remote Procedure Control
└ 프로시저(Procedure) : 함수(function), 메소드(method)와 같은 개념
└ 소켓(Socket)은 IP 주소와 포트의 개념이 합쳐진 물리적인 장치의 개념이다.
프로세스 내부 데이터 통신
하나의 프로세스 내에 2개 이상의 스레드끼리 통신하는 경우
프로세스 내부의 스레드는 전역 변수나 파일을 이용한 통신이 이루어진다.
프로세스 간 데이터 통신
같은 컴퓨터에 있는 여러 프로세스끼리 통신하는 경우
공용 파일이나 운영체제가 제공하는 파이프를 이용한 통신이 이루어진다.
네트워크를 이용한 데이터 통신
여러 컴퓨터가 네트워크로 연결되어 있을 때 다른 컴퓨터의 프로세스끼리 통신하는 경우
네트워킹이라고 하며, 소켓과 원격 프로시저 호출을 이용한 통신이 이루어진다.
1.2. 프로세스 간 통신의 분류
1.2.1. 통신 방향에 따른 분류
양방향 통신(Duplex Communication)
데이터 통신론에서의 '전이중화 통신'과 같은 개념이다.
데이터를 동시에 양쪽 방향으로 전송할 수 있는 구조로, 일반적인 통신 방법을 말한다.
소켓 통신이 양방향 통신에 해당한다.
반양방향 통신(Half-Duplex Communication)
데이터 통신로에서의 '반이중화 통신'과 같은 개념이다.
데이터를 양쪽 방향으로 전송할 수 있지만 동시 전송은 불가능한 구조이다.
단방향 통신(Simplex Communication)
한쪽 방향으로만 데이터를 전송할 수 있는 구조이다.
전역 변수와 파이프가 단방향 통신에 해당한다.
전역 변수를 통한 양방향 통신을 하려면 전역 변수를 2개를 사용해야 한다.
1.2.2. 통신 구현 방식에 따른 분류
전역 변수를 사용하는 통신의 문제는 데이터 확인이다. 언제 데이터가 올지 몰라 계속해서 확인을 해야 한다.
반목문을 이용해 무한 확인을 하며 기다리는 상태를 '바쁜 대기(Busy Waiting)'라고 한다.
이런 바쁜 대기 문제를 해결하기 위해, 데이터가 도착했음을 알려주는 것을 '동기화(Synchronization)'라고 한다.
대기가 있는 통신(Blocking Communication)
동기화 통신(Synchronous Communication)이라고도 한다.
데이터를 받는 쪽은 데이터가 도착할 때까지 자동으로 대기 상태에 머물러 있는 통신 방법이다.
대기가 없는 통신(Non-Blocking Communication)
비동기화 통신(Asynchronous Communication)이라고도 한다.
데이터를 받는 쪽은 바쁜 대기를 사용하여 데이터가 도착했는지 여부를 직접 확인하는 통신 방법이다.
1.3. 프로세스 간 통신의 종류
1.3.1. 전역 변수를 이용한 통신
공동으로 관리하는 메모리를 사용하여 데이터를 주고 받는 통신으로 단방향 통신이다.
데이터를 보내는 쪽이 전역 변수나 파일에 값을 쓰고, 데이터를 받는 쪽이 그 값을 읽어들인다.
보통 직접 관련이 있는 프로세스 간에 사용하지만, extern 변수로 연관이 없는 프로세스 간에도 사용 가능하다.
프로세스 P가 wrtie 하기 직전에, 프로세스 C가 read를 한다면 동기화에 문제가 생긴다.
그래서 프로세스는 바쁜 대기 상태에 계속 있어야 한다는 문제가 있다.
1.3.2. 파일을 이용한 통신
파일을 이용한 통신은 크게 열기(Open) / 쓰기(Write) 읽기(Read) / 닫기(Close)의 세 단계로 이루어진다.
open()를 이용해 파일에 접근한다. 파일이 있는지, 파일이 있다면 쓰기 권한이 있는지도 확인한다.
O_RDWR는 읽기와 쓰기가 가능한 형태로 파일을 열겠다는 의미이다. 이런 내용은 Oflag라고 정의해놨다.
부모-자식 프로세스 간 통신에 많이 사용되며 OS가 프로세스 동기화를 제공하지 않는다.
// fd : file descriptor
1.3.3. 파이프를 이용한 통신
OS가 제공하는 동기화 통신 방식으로, 파일을 이용한 통신처럼 open()과 close()를 사용한다.
전역 변수를 이용한 통신처럼 단방향 통신이다. 양방향 통신을 하려면 2개의 파이프를 사용해야 한다.
파이프는 이름 없는 파이프(Anonymous Pipe)와 이름 있는 파이프(Named Pipe)로 나뉜다.
이름 없는 파이프 : 일반적인 파이프로, 부모-자식 프로세스 간 통신에 사용한다.
이름 있는 파이프 : FIFO라는 파일을 이용해, 서로 관련 없는 프로세스 간 통신에 사용한다.
1.3.4. 소켓을 이용한 통신
프로시저 호출은 컴퓨터에 있는 함수를 호출하는 것이다. 원격이라면 다른 컴퓨터의 함수에 접근하는 개념이다.
이 원격 프로시저 호출은 소켓을 통해서 이루어진다(컴퓨터의 위치를 파악하고 어떤 프로세스를 통한 통신인지).
// 네트워크 프로그래밍을 흔히 소켓 프로그래밍이라고 하는데, 네트워킹의 기본이 소켓이기 때문이다.
소켓은 프로세스 동기화를 지원하고, 양방향 통신이 가능하다.
소켓을 이용해 통신할 때, 송수신 포트 번호가 필요하다.
컴퓨터의 위치를 파악하기 위해 수신 포트 번호는 중요하지만, 송신 포트는 그렇게 큰 의미가 없다.
그래서 송신 포트는 실제로 송신측 단말에서 무작위 번호를 할당해서 보낸다.
1.3.5. 정리
2. 공유 자원과 임계 구역
2.1. 공유 자원의 접근
공유 자원(Shared Resource) : 여러 프로세스가 공동으로 이용하는 변수, 메모리, 파일 등
경쟁 조건(Race Condition) : 2개 이상의 프로세스가 공유 자원을 병행적(동시에)으로 읽거나 쓰는 상황
2.2. 임계 구역
임계 구역(Critical Section) : 공유 자원 접근하는 프로세스의 순서에 따라 실행 결과가 달라지는 프로그램 영역
2.3. 생산자-소비자 문제
물건을 생산해서 원형 버퍼(Circular Buffer)에 넣는 생산자 프로세스가 있고,
물건을 원형 버퍼에서 가져와 소비하는 소비자 프로세스가 있다고 가정해보자.
각각의 프로세스가 동시에 접근해서 자신의 연산을 하고 결과를 버퍼의 전역 변수에 넣는다.
전역 변수가 3이라면 생산자 프로세스의 결과는 4, 소비자 프로세스의 결과는 2가 된다.
이때, 누가 먼저 결과를 넣느냐에 따라서 값이 4가 되거나 2가 되거나 하는 식으로 값이 바뀐다는 것이다.
이것이 생산자-소비자 문제(Producer-Consumer Problem)이다.
2.4. 임계 구역 해결 조건
상호 배제(Mutual Exculsion)
임계 구역 내에는 한 번에 하나의 프로세스만 있어야 한다.
한정 대기(Bounded Waiting)
어떤 프로세스도 무한 대기를 하지 않아야 한다.
진행의 융통성(Progress Flexibility)
어떤 프로세스가 다른 프로세스의 진행을 방해해서는 안 된다.
3. 임계 구역 해결 방법
3.1. 기본 코드 소개
임계 구역을 해결하는 방법은 '잠금(Lock)'을 이용하는 것이다.
잠금 신호와 동기화 신호를 동시에 보냄으로써 한 개의 프로세스만 사용하고 그것을 확인한다.
// typedef : 새로운 타입을 정의하는 C언어 함수
// enum : 열거형으로 boolean의 false, true 타입을 0과 1로 정의
// extern : 외부 프로그램의 변수를 가져다가 사용
3.2. 임계 구역 해결 조건을 고려한 코드 설계
3.2.1. 상호 배제 문제
P1이 작업을 실행할 때 lock을 true로 설정하고 임계 구역에서 작업을 진행한다.
이때 P2가 임계 구역에 접근하려고 한다면 lock이 true라서 while(lock==true)에 걸려서 대기 상태가 된다.
이렇게 상호 배제를 해결한 것처럼 보이지만, 비선점형 스케줄링의 경우가 문제가 발생한다.
P1과 P2가 정해진 타임 슬라이스동안 각각 한 줄씩 코드를 실행한다고 가정하자.
P1이 while문을 확인, P2가 while문을 확인, P1이 lock을 true로 바꿈, P2가 lock을 true로 바꿈
위에 적은 문장의 순서대로 작업이 진행될 것이다. 그럼 결국 두 프로세스가 동시에 임계 구역에 접근한다.
이와 같은 경우에 상호 배제 조건을 충족하지 않는다.
3.2.2. 한정 대기 문제
상호 배제 문제를 해결하기 위해 잠금 장치(공유 변수)를 2개 사용한다.
P1이 작업 중일 때는 lock1을 잠그고, P2가 작업 중일 때는 lock2를 잠가 상호 배제 문제를 해결한다.
이번에도 역시 정해진 타임 슬라이스를 가지고 비선점형 스케줄링을 한다고 가정해보자.
P1이 lock1을 true로 바꿈, P2가 lock2를 true로 바꿈, P1이 while문을 확인 > 무한 대기, P2가 while문을 확인 > 무한 대기
이번에는 두 프로세스가 임계 구역에 접근하지 못하는 무한 대기 상태에 빠진다.
이와 같은 경우에 한정 대기 조건을 충족하지 않는다.
프로세스가 살아있으나 작업이 진행되지 않는 상태를 '교착 상태(Deadlock)'라고 한다.
또한, 프로세스의 수에 따라서 공유 변수가 늘어난다는 확장성의 문제도 포함하고 있다.
3.2.3. 진행의 융통성 문제
한정 대기 문제를 해결하기 위해 잠금 장치를 boolean 값이 아니라 상수 값으로 사용한다.
lock의 값이 n일 때, 프로세스 Pn이 임계 구역에 들어가서 작업을 한다는 의미이다.
마찬가지로 비선점형 스케줄링을 한다고 가정해보자.
P1 작업, lock을 2로 바꿈, P2 작업, lock을 1로 바꿈
여기서 발생하는 문제는 P1의 작업이 마치고 lock을 2로 바꿔서 P1이 다시 접근하지 못 한다는 거다.
무조건적으로 P1과 P2가 번갈아가면서 실행이 되는 모습이 다른 프로세스의 진행을 방해하는 구조이다.
이렇게 프로세스의 진행이 다른 프로세스 때문에 방해받는 것을 '경직된 동기화(Lockstep Synchronization)'라고 한다.
이와 같은 경우에 진행의 융통성 조건을 충족하지 않는다.
// 경직된 동기화 문제가 있다면 SRT 스케줄링은 진행할 수 없다.
3.2.4. 하드웨어적인 해결 방법
'검사와 지정(Test-and-Set)'이라는 코드로 하드웨어의 지원으로 while문과 lock을 하나의 코드로 받아들여 처리한다.
하드웨어적으로 처리하면 편하지만, 바쁜 대기를 사용하여 검사하기 때문에 자원 낭비가 생긴다.
3.3. 피터슨 알고리즘
게리 피터슨(Gary Peterson)이라는 사람이 고안한 알고리즘이다.
한정 대기 문제가 있던 알고리즘에서 공유 변수로 turn이라는 변수를 하나 더 사용한다.
둘 다 Deadlock 상태에 빠져도 turn 변수를 한 번 더 검사함으로써 임계 구역 해결 조건을 모두 충족한다.
하지만 위와 마찬가지로 단 2개의 프로세스에서만 사용 가능하고, 확장하더라도 많은 변수가 필요하다는 단점이 있다.
3.4. 데커 알고리즘
테오도뤼스 데커(Theodours Dekker)라는 사람이 고안한 알고리즘이다.
피터슨 알고리즘과 같은 공유 변수를 사용하지만 동작하는 알고리즘이 조금 다를 뿐 3가지 조건을 모두 만족한다.
피터슨 알고리즘과 데커 알고리즘은 '검사와 지정'같은 하드웨어의 도움이 필요없다는 것이 특징이다.
3.5. 세마포어
복잡하거나 바쁜 대기를 통한 자원 낭비가 있다는 문제를 보안해 나온 알고리즘이다.
에츠허르 다익스트라(Edsger Dijkstra)가 고안했다(최단 경로를 구하는 다익스트라 알고리즘을 고안한 사람이다).
스위치처럼 P()를 통해 작업을 하기 전 잠금 상태로 만든다.
작업을 완료한 뒤에는 V()를 통해 다음 프로세스에게 동기화 신호를 보낸다.
다른 프로세스들은 동기화 신호에 맞춰 행동하면 되기에 직접 lock을 확인하거나 바쁜 대기를 할 필요가 없다.
Semaphore(n)에서 n에 사용가능한 자원의 수를 적는다. 여기서 n은 2이다.
보는 것처럼 사용할 때 자원의 수를 줄이고, 다른 프로세스에게 신호를 넘겨준다.
공유 자원과 프로세스가 여러 개인 경우에도 쉽게 확장이 가능하고 3가지 조건도 모두 만족한다.
세마포어의 가장 큰 문제는 코딩을 잘못하는 것이다.
세마포어 문법을 적지 않거나, 잠금만 두 번한다거나, 잠금과 해제를 역순으로 한다거나 하는 식이다.
3.6. 모니터
위의 세마포어의 문제를 해결한 것이 모니터(Monitor)이다.
사용자가 직접 코딩하지 않고, 모니터라는 시스템 호출을 통해 작업을 진행한다.
└ 시스템 호출 : OS가 시스템 자원을 사용자로부터 숨기고, 요구 사항을 처리할 수 있게 인터페이스만을 제공하는 것
ㆍ 프로세스는 P()와 V()를 직접 사용하지 않고 모니터에 작업 요청을 한다.
ㆍ 모니터 큐에서 작업들이 순서대로 대기를 한다.
ㆍ 큐에 있는 프로세스 순서대로 작업을 처리하고, 결과만 해당 프로세스에 반환한다.
4. [심화학습] 파일, 파이프, 소켓 프로그래밍
4.1. 파일
순차 파일(Sequential File) : 화면에서는 여러 줄로 보여도, 실제 데이터는 한 줄로 길게 저장하는 파일
순차적 접근(Sequential Access) : 순차 파일에 접근하는 방식(Ex. 카세트테이프)
파일 기술자(File Descriptor) : 특정한 파일에 접근하기 위한 추상적인 키
4.2. 파이프
파일은 read()와 write()가 파일 기술자를 공유 하지만, 파이프는 read()와 write()의 기술자가 따로 있다.
그렇기에 파이프는 동기화가 가능하다. 만약 fd[2]와 같이 정의한다면, 하나는 읽기용 하나는 쓰기용이다.
파이프는 대기가 있는 단방향 통신이기 때문에, wait()을 사용할 필요도 없다.
4.3. 네트워킹
네트워킹에서는 양방향 통신과 동기화를 모두 지원한다.
// bind() : 포트를 지정하는 프로시저
// listen() : 요청을 한 클라이언트가 누구인지 확인하는 프로시저
'학교 공부 > 스마트 운영체제' 카테고리의 다른 글
운영체제 07 물리 메모리 관리 (0) | 2022.05.03 |
---|---|
운영체제 06 교착 상태 (0) | 2022.04.19 |
운영체제 04 CPU 스케줄링 (0) | 2022.04.05 |
운영체제 03 프로세스와 스레드 (0) | 2022.03.29 |
운영체제 02 컴퓨터의 구조와 성능 향상 (0) | 2022.03.22 |