프로세스 두번째 시간이다.
저번에 프로세스가 뭔지부터 어떻게 생성되는지에 대해 알아보았다.
이번에는 프로세스끼리 어떻게 통신하는지 알아보겠다.
가보자고
3.4 Interprocess Communication(IPC)
프로세스들은 서로 데이터를 공유하냐에 따라 independent인지 coorperating인지 나뉜다.
📢 IPC는 coorperating인 프로세스들이 데이터를 공유할 때 사용하는 메커니즘이다.
IPC에는 2가지 방법이 존재한다.
첫번째, shared memory 방식 (왼쪽, (a))
두번째, message passing 방식이다. (오른쪽, (b))

이 2가지 방법에 대해 자세히 알아보도록 하자!!!!
3.5 IPC in Shared-Memory Systems
Shared memory를 먼저 알아보자.

- Shared memory를 구성하기 위해서는 communicating process가 필요하다.
- Share 할 부분에 대해 각 process는 process의 protection을 제거해야 한다. (이때, system call이 한 번 필요하다)
- 이렇게 protection을 제거하고 나면, OS의 control없이(system call 안 하고) 프로세스간 read & write가 가능해진다.
결론적으로 성능이 더 좋아진다!!
[Example]
shared-memory의 대표적인 예시로 producer-consumer problem을 해결했다는 것이 있다. 먼저 producer-consumer problem에 대해 설명하자면,
Producer-Consumer problem
- producer: data를 생산함
- consumer: data를 소비함
이 2개가 별도의 process이다. 즉 process간 통신을 필요로 한다.
그래서! 여기에 shared-memory를 적용한다면~?
shared-memory에 data를 저장할 수 있는 buffer를 만들어놓고, producer는 buffer를 채우고, consumer는 buffer를 비우면 된다.
이 동작이 동기화되어 사용되면 shared-memory system!
그러면 이걸 코드로 구현해보자!
#define BUFFER_SIZE 10
//버퍼 크기 10으로 정의
typedef struct{
...
} item; //item이라는 구조체 타입을 정의
item buffer[BUFFER_SIZE]; //circular array로 구
int in = 0; /* producer가 data를 삽입할 위치
producer가 data 삽입할때마다 증가 */
int out = 0; /* consumer가 data를 꺼낼 위치
consumer가 data 꺼낼때마다 증가 */
circular array를 정의하고, 2개의 pointer가 있다.
다음으로 producer와 consumer process의 코드도 살펴볼까?
item next_produced;
while(true){
/* produce an item in next_produced */
while(((in+1) % BUFFER_SIZE) == out) //buffer가 full이 아닌동안
{
/* do nothing*/
}
buffer[in] = next_produced; //data 삽입
in = (in + 1) % BUFFER_SIZE; //in 증가시키기
}
in = (in+1) % BUFFER_SIZE 는 circular array이기 때문에 in 인덱스를 증가하고, buffer 크기를 넘어서면 0으로 돌아가도록 해준다.
item next_consumed;
while(true){
while(in==out)
{
/* do nothing*/
}
next_consumed = buffer[out];
out = (out+1) % BUFFER_SIZE;
/
앞서 producer와 비슷한 방식으로 작동한다.
3.6 IPC in Message-Passing Systems
이번에는 message-passing 방법에 대해서도 알아보겠따.
Shared-memory 방법은 address space 공유가 필요했던 반면에, message-passing 방법은 address space를 공유하지 않고도 통신이 가능하다.
message-passing은 2가지 operation이 있다. 바로 send(message)와 receive(message)이다.
만약 두 개의 process P와 Q가 있다고 하고, 이 process들이 통신한다면 producer는 send(message), receiver는 receive(message) 를 이용하면 된다.
그러면 두 개의 process간에 communication link가 필요하다! communication link를 구현하는 방법은 다양하다..
- direct communication or indirect communication
- Synchronous communication or asynchronous communication
- automatic buffering or explicit buffering
각각의 방법에 대해서 소개해보겠다.
Direct communication
direct방식은 또 symmetry와 asymmetry로 나뉜다. (하 그만좀 나눠)
direct 방식의 특징은 process간의 communication link가 자동으로 생성되고, process pair 당 오직 1개의 link만 존재한다는 것이다.
단점으로는 send, receive process를 지정해야하므로 process를 변경해야 할 때 다 찾아서 변경해야하는 번거로움이 있다. 즉, modularity에 한계가 있다.
📌
[Symmetry direct communication]
먼저 direct symmetry는 send process와 receive process 모두 명시해야 한다. 이렇게 명시하고, 각 process에 따른 동작을 수행한다.
send(P, message) : process P에게 message를 전송
receive(Q, message): process Q로부터 message를 수신
[Asymmetry direct communication]
asymmetry는 send process에 대해서는 명시해야 하지만, receive에 대해서는 process를 지정하지 않는다. 즉, 어떤 process에서도 다 receive할 수 있다.
send(P, message) : process P에게 message를 전송
receive(id, message): 모든 process로부터 message를 수신
Indirect communication
process 사이의 통신이 아닌, mailbox 또는 port를 이용해 message가 전달되는 방법이다.
*mailbox(port) : message를 넣을 수도, 가져갈 수도 있는 일종의 buffer
한 개의 communication link가 2개의 process에서 존재하는 것이 아니라, 여러개의 process에서 존재할 수 있음,
또한 2개의 process에 여러 link가 존재할 수도 있다!
send(A, message) : mailbox A에 message를 전송
receive(A, message) : mailbox A 로부터 message를 수신
Synchronization
blocking이 sychronous, non-blocking이 asychronous방식이라고 할 수 있다.
- blocking send: sender는 message가 수신될때까지 sending이 막힘
- non-blocking send: sender는 message를 보내고 계속해서 다른일 수행
- blocking receive: receiver는 message가 수신 가능할 때 까지 대기
- non-blocking receive: receiver는 valid한 message 혹은 null message를 받음
아까 언급했던 producer-cosumer problem을 message-passing에서는 blocking send, blocking receive인 경우에 해결할 수 있다.
Buffering
IPC에서의 일시적인 queue라고 할 수 있겠다.! 3가지 방식이 있다.
- Zero capacity: buffering을 하지 않는것, message를 저장하지 않으므로 waiting message라는 건 존재하지 않고, blocking도 허용하지 않음
- Bounded capacity: 유한한 길이의 message를 가지게 된다. 최대 n개의 message를 가지고, link가 full이 되면 sender 막힌다.
- Unbounded capacity: 무한한 길이의 buffer를 가진다. 절대 blocked 되지 않고, 이론적으로 어렵다. 근데 어느정도 충분한 buffer를 확보하고 일정간격으로 message를 receive한다면 현실적으로 구현할 수 있다!
3.7 Examples of IPC Systems
- Shared-memory: POSIX shared memory
- Message-passing: Pipes
이게 각각의 예시이다 . 조금더 자세히 살펴보자.
Shared-memory: POSIX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main()
{
const int SIZE = 4096; // shared memory의 크기
const char* name = "OS"; // shared memory의 이름
const char* message_0 = "Hello, ";
const char* message_1 = "Shared Memory!\\n";
int shm_fd; // shared memory의 file 설명자
char* ptr; // shared memory의 pointer
// shared memory 객체 생성
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
// shared memory의 크기 설정
ftruncate(shm_fd, SIZE);
// shared memory 객체에 매핑
ptr = (char*) mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
// shared memory에 메시지 작성
sprintf(ptr, "%s", message_0);
ptr += strlen(message_0);
sprintf(ptr, "%s", message_1);
ptr += strlen(message_1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main()
{
const int SIZE = 4096; // shared memory의 크기
const char* name = "OS"; // shared memory의 이름
int shm_fd; // shared memory의 file 설명자
char* ptr; // shared memory의 pointer
// shared memory 객체 생성
shm_fd = shm_open(name, O_RDONLY, 0666);
// shared memory 객체에 매핑
ptr = (char*) mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
// shared memory 객체 읽기
printf("%s", (char*)ptr);
// shared memory 제거
shm_unlink(name);
return 0;
}
consumer니까 readonly임.
Message-passing: Pipes
pipes는 단순한 방법이다. pipe는 두 process가 통신할 수 있는 통로의 역할을 수행한다.
다만 pipes를 구현할 때 고려해야 할 것들이 있다.
- Bidirectional or Undirectional?
- Bidriectional인 경우에만, half duplex or full duplex?
- half duplex: 한쪽 방향으로만 통신
- full duplex: pipe 2개를 사용하여 송수신
- parent-child같은 relationship이 필요한가?
- pipe가 network를 통해 통신하는가?
Pipes는 두가지가 있다. ordinary pipes와 Named pipes이다. 각각에 대해 알아보자!!
[Ordinary pipes]
- Undirectional 통신, 만약 Bidirectional로 통신하고 싶다면, 2개의 pipe를 사용해야함
- 두 process가 producer-consumer 방식으로 통신함
- 생성된 process의 외부에서는 접근할 수 없음
- 일반적으로 parent-child process 간의 통신을 위해 사용

[Named pipes]
- Bidirectional 통신, half-duplex
- parent-child process 관계없이 접근이 가능함
3.8 Communication in Client-Server Systems
Socket
Socket: IP Adress와 Port number가 결합된 식별자, client-server architecture
ex) 146.86.5.20:1625 → IP adress는 146.86.5.20, Port number는 1625

socket도 pair를 이뤄야하고, 각 process마다 socket을 가지고 있어야 한다. 위의 그림에서 host x 가 web server와 통신하기 위해서는 web server의 IP Adress와 port number를 알아야 한다. 모든 connection은 unique해야해서 different port를 가진다.
RPC(Remote Procedure Call)
- 원격 서비스의 가장 일반적인 형태 중 하나이다.
- well structured messages: no longer just packets of data
- function과 parameter를 실행할 수 있게 함
- distributed file system 구현에 효과적임
별도의 원격 제어를 위한 코딩없이 다른 주소 공간에서 함수나 프로시저를 실행할 수 있게 하는 프로시저간의 통신 기술이다.
'OS' 카테고리의 다른 글
[운영체제] Threads & Concurrency (2) (1) | 2024.04.18 |
---|---|
[운영체제] Threads & Concurrency (0) | 2024.04.11 |
[운영체제] Processes (0) | 2024.04.01 |
[운영체제] OS 구조 (0) | 2024.04.01 |
[운영체제] OS 소개(2) (0) | 2024.03.31 |
프로세스 두번째 시간이다.
저번에 프로세스가 뭔지부터 어떻게 생성되는지에 대해 알아보았다.
이번에는 프로세스끼리 어떻게 통신하는지 알아보겠다.
가보자고
3.4 Interprocess Communication(IPC)
프로세스들은 서로 데이터를 공유하냐에 따라 independent인지 coorperating인지 나뉜다.
📢 IPC는 coorperating인 프로세스들이 데이터를 공유할 때 사용하는 메커니즘이다.
IPC에는 2가지 방법이 존재한다.
첫번째, shared memory 방식 (왼쪽, (a))
두번째, message passing 방식이다. (오른쪽, (b))

이 2가지 방법에 대해 자세히 알아보도록 하자!!!!
3.5 IPC in Shared-Memory Systems
Shared memory를 먼저 알아보자.

- Shared memory를 구성하기 위해서는 communicating process가 필요하다.
- Share 할 부분에 대해 각 process는 process의 protection을 제거해야 한다. (이때, system call이 한 번 필요하다)
- 이렇게 protection을 제거하고 나면, OS의 control없이(system call 안 하고) 프로세스간 read & write가 가능해진다.
결론적으로 성능이 더 좋아진다!!
[Example]
shared-memory의 대표적인 예시로 producer-consumer problem을 해결했다는 것이 있다. 먼저 producer-consumer problem에 대해 설명하자면,
Producer-Consumer problem
- producer: data를 생산함
- consumer: data를 소비함
이 2개가 별도의 process이다. 즉 process간 통신을 필요로 한다.
그래서! 여기에 shared-memory를 적용한다면~?
shared-memory에 data를 저장할 수 있는 buffer를 만들어놓고, producer는 buffer를 채우고, consumer는 buffer를 비우면 된다.
이 동작이 동기화되어 사용되면 shared-memory system!
그러면 이걸 코드로 구현해보자!
#define BUFFER_SIZE 10
//버퍼 크기 10으로 정의
typedef struct{
...
} item; //item이라는 구조체 타입을 정의
item buffer[BUFFER_SIZE]; //circular array로 구
int in = 0; /* producer가 data를 삽입할 위치
producer가 data 삽입할때마다 증가 */
int out = 0; /* consumer가 data를 꺼낼 위치
consumer가 data 꺼낼때마다 증가 */
circular array를 정의하고, 2개의 pointer가 있다.
다음으로 producer와 consumer process의 코드도 살펴볼까?
item next_produced;
while(true){
/* produce an item in next_produced */
while(((in+1) % BUFFER_SIZE) == out) //buffer가 full이 아닌동안
{
/* do nothing*/
}
buffer[in] = next_produced; //data 삽입
in = (in + 1) % BUFFER_SIZE; //in 증가시키기
}
in = (in+1) % BUFFER_SIZE 는 circular array이기 때문에 in 인덱스를 증가하고, buffer 크기를 넘어서면 0으로 돌아가도록 해준다.
item next_consumed;
while(true){
while(in==out)
{
/* do nothing*/
}
next_consumed = buffer[out];
out = (out+1) % BUFFER_SIZE;
/
앞서 producer와 비슷한 방식으로 작동한다.
3.6 IPC in Message-Passing Systems
이번에는 message-passing 방법에 대해서도 알아보겠따.
Shared-memory 방법은 address space 공유가 필요했던 반면에, message-passing 방법은 address space를 공유하지 않고도 통신이 가능하다.
message-passing은 2가지 operation이 있다. 바로 send(message)와 receive(message)이다.
만약 두 개의 process P와 Q가 있다고 하고, 이 process들이 통신한다면 producer는 send(message), receiver는 receive(message) 를 이용하면 된다.
그러면 두 개의 process간에 communication link가 필요하다! communication link를 구현하는 방법은 다양하다..
- direct communication or indirect communication
- Synchronous communication or asynchronous communication
- automatic buffering or explicit buffering
각각의 방법에 대해서 소개해보겠다.
Direct communication
direct방식은 또 symmetry와 asymmetry로 나뉜다. (하 그만좀 나눠)
direct 방식의 특징은 process간의 communication link가 자동으로 생성되고, process pair 당 오직 1개의 link만 존재한다는 것이다.
단점으로는 send, receive process를 지정해야하므로 process를 변경해야 할 때 다 찾아서 변경해야하는 번거로움이 있다. 즉, modularity에 한계가 있다.
📌
[Symmetry direct communication]
먼저 direct symmetry는 send process와 receive process 모두 명시해야 한다. 이렇게 명시하고, 각 process에 따른 동작을 수행한다.
send(P, message) : process P에게 message를 전송
receive(Q, message): process Q로부터 message를 수신
[Asymmetry direct communication]
asymmetry는 send process에 대해서는 명시해야 하지만, receive에 대해서는 process를 지정하지 않는다. 즉, 어떤 process에서도 다 receive할 수 있다.
send(P, message) : process P에게 message를 전송
receive(id, message): 모든 process로부터 message를 수신
Indirect communication
process 사이의 통신이 아닌, mailbox 또는 port를 이용해 message가 전달되는 방법이다.
*mailbox(port) : message를 넣을 수도, 가져갈 수도 있는 일종의 buffer
한 개의 communication link가 2개의 process에서 존재하는 것이 아니라, 여러개의 process에서 존재할 수 있음,
또한 2개의 process에 여러 link가 존재할 수도 있다!
send(A, message) : mailbox A에 message를 전송
receive(A, message) : mailbox A 로부터 message를 수신
Synchronization
blocking이 sychronous, non-blocking이 asychronous방식이라고 할 수 있다.
- blocking send: sender는 message가 수신될때까지 sending이 막힘
- non-blocking send: sender는 message를 보내고 계속해서 다른일 수행
- blocking receive: receiver는 message가 수신 가능할 때 까지 대기
- non-blocking receive: receiver는 valid한 message 혹은 null message를 받음
아까 언급했던 producer-cosumer problem을 message-passing에서는 blocking send, blocking receive인 경우에 해결할 수 있다.
Buffering
IPC에서의 일시적인 queue라고 할 수 있겠다.! 3가지 방식이 있다.
- Zero capacity: buffering을 하지 않는것, message를 저장하지 않으므로 waiting message라는 건 존재하지 않고, blocking도 허용하지 않음
- Bounded capacity: 유한한 길이의 message를 가지게 된다. 최대 n개의 message를 가지고, link가 full이 되면 sender 막힌다.
- Unbounded capacity: 무한한 길이의 buffer를 가진다. 절대 blocked 되지 않고, 이론적으로 어렵다. 근데 어느정도 충분한 buffer를 확보하고 일정간격으로 message를 receive한다면 현실적으로 구현할 수 있다!
3.7 Examples of IPC Systems
- Shared-memory: POSIX shared memory
- Message-passing: Pipes
이게 각각의 예시이다 . 조금더 자세히 살펴보자.
Shared-memory: POSIX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main()
{
const int SIZE = 4096; // shared memory의 크기
const char* name = "OS"; // shared memory의 이름
const char* message_0 = "Hello, ";
const char* message_1 = "Shared Memory!\\n";
int shm_fd; // shared memory의 file 설명자
char* ptr; // shared memory의 pointer
// shared memory 객체 생성
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
// shared memory의 크기 설정
ftruncate(shm_fd, SIZE);
// shared memory 객체에 매핑
ptr = (char*) mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
// shared memory에 메시지 작성
sprintf(ptr, "%s", message_0);
ptr += strlen(message_0);
sprintf(ptr, "%s", message_1);
ptr += strlen(message_1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main()
{
const int SIZE = 4096; // shared memory의 크기
const char* name = "OS"; // shared memory의 이름
int shm_fd; // shared memory의 file 설명자
char* ptr; // shared memory의 pointer
// shared memory 객체 생성
shm_fd = shm_open(name, O_RDONLY, 0666);
// shared memory 객체에 매핑
ptr = (char*) mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
// shared memory 객체 읽기
printf("%s", (char*)ptr);
// shared memory 제거
shm_unlink(name);
return 0;
}
consumer니까 readonly임.
Message-passing: Pipes
pipes는 단순한 방법이다. pipe는 두 process가 통신할 수 있는 통로의 역할을 수행한다.
다만 pipes를 구현할 때 고려해야 할 것들이 있다.
- Bidirectional or Undirectional?
- Bidriectional인 경우에만, half duplex or full duplex?
- half duplex: 한쪽 방향으로만 통신
- full duplex: pipe 2개를 사용하여 송수신
- parent-child같은 relationship이 필요한가?
- pipe가 network를 통해 통신하는가?
Pipes는 두가지가 있다. ordinary pipes와 Named pipes이다. 각각에 대해 알아보자!!
[Ordinary pipes]
- Undirectional 통신, 만약 Bidirectional로 통신하고 싶다면, 2개의 pipe를 사용해야함
- 두 process가 producer-consumer 방식으로 통신함
- 생성된 process의 외부에서는 접근할 수 없음
- 일반적으로 parent-child process 간의 통신을 위해 사용

[Named pipes]
- Bidirectional 통신, half-duplex
- parent-child process 관계없이 접근이 가능함
3.8 Communication in Client-Server Systems
Socket
Socket: IP Adress와 Port number가 결합된 식별자, client-server architecture
ex) 146.86.5.20:1625 → IP adress는 146.86.5.20, Port number는 1625

socket도 pair를 이뤄야하고, 각 process마다 socket을 가지고 있어야 한다. 위의 그림에서 host x 가 web server와 통신하기 위해서는 web server의 IP Adress와 port number를 알아야 한다. 모든 connection은 unique해야해서 different port를 가진다.
RPC(Remote Procedure Call)
- 원격 서비스의 가장 일반적인 형태 중 하나이다.
- well structured messages: no longer just packets of data
- function과 parameter를 실행할 수 있게 함
- distributed file system 구현에 효과적임
별도의 원격 제어를 위한 코딩없이 다른 주소 공간에서 함수나 프로시저를 실행할 수 있게 하는 프로시저간의 통신 기술이다.
'OS' 카테고리의 다른 글
[운영체제] Threads & Concurrency (2) (1) | 2024.04.18 |
---|---|
[운영체제] Threads & Concurrency (0) | 2024.04.11 |
[운영체제] Processes (0) | 2024.04.01 |
[운영체제] OS 구조 (0) | 2024.04.01 |
[운영체제] OS 소개(2) (0) | 2024.03.31 |