IPC = Inter process Communications
네트워크 프로그래밍이 아닌 시스템 프로그래밍에 가까운 부분이다.
소켓 함수는 20개 내외로 제한적이기 때문에, 응용 프로그램 개발을 할 시에는 시스템 프로그래밍 기술이 매우 중요하다.
네트워크 프로그램도 시스템 위에서 작동한다.
PIPE
Unix Domain Socket
공유 메모리
PIPE와 Unix Domain Socket는 메시지 기반의 IPC로 공유 메모리를 사용할 수 있다.메모리 공간을 공유하며, 빠르고 효율적이다.
하지만, 접근제어가 필요하게 된다 => Mutex 혹은 Semaphores가 필요함
shmdt(const void *shmaddr)
shmaddr : 분리할 공유 메모리를 가리키는 포인터로 shmat에서 사용했던 shmaddr를 그대로 사용한다.
shmat(int shmid, const void *shmaddr, int shmflg)
shmid : shmget 함수로 만든 공유 메모리 식별자
shmaddr : 공유 메모리 영역을 가리키는 주소이다. NULL인 경우 운영체제가 알아서 찾아서 반환해준다.
shmflg : 쓰기 전용을 지정할 수는 없고, 값을 지정하게 되면 읽기 전용이 된다.
produce.c
#include<sys/shm.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv){
int shmid;
int *cal_num;
void *share_mem = NULL;
// 0666 => 110110110 rwxrwxrwx
shmid = shmget((key_t)1234, sizeof(int), 0666|IPC_CREAT);
if(shmid == -1){
perror("shmget fail");
return 1;
}
// *share_mem --> attached mem
share_mem = shmat(shmid, NULL, 0);
if(share_mem == (void *)-1){
perror("shmat fail");
return 1;
}
cal_num = (int *)share_mem;
while(1){
*cal_num = *cal_num + 2;
sleep(1);
}
return 1;
}
consumer.c
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv){
int shmid;
int *cal_num;
void *share_mem = NULL;
shmid = shmget((key_t)1234, sizeof(int), 0);
if(shmid == -1){
perror("shmget fail");
return 1;
}
// *share_mem --> attached mem
share_mem = shmat(shmid, NULL, 0);
if(share_mem == (void *) -1){
perror("shmat fail");
return 1;
}
cal_num = (int *) share_mem;
while(1){
sleep(1);
printf("Read Data : %d\n", *cal_num);
}
return 1;
}
세마포어 임계영역 관리
int semop(int semid, struct sembuf *sops, unsigned nsops)
semid : semget 함수로 생성한 세마포어 식별자이다.
sops : 세마포어 제어를 위해 사용하는 세마포어 구조체이다.
nsops : 세마포어 집합의 개수이다. 하나만 접근이 가능할려면 1을 사용
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
union semun{
int val;
};
int main(int argc, char **argv){
int shmid;
int semid;
int *cal_num;
void *share_mem = NULL;
union semun sem_union;
struct sembuf semopen = {0,-1,SEM_UNDO};
struct sembuf semclose = {0,1,SEM_UNDO};
// Get share memory
shmid = shmget((key_t)1234, sizeof(int), 0666|IPC_CREAT);
if(shmid == -1){
return 1;
}
// let's make semaphores
semid = semget((key_t)3477, 1, IPC_CREAT|0666);
if(semid == -1){
return 1;
}
// connect to share mem
share_mem = shmat(shmid, NULL, 0);
if(share_mem == (void *) -1){
return 1;
}
// *cal_num --> share_memory
cal_num = (int *)share_mem;
sem_union.val = 1;
// init semaphores
if(-1 == semctl(semid, 0, SETVAL, sem_union)){
return 1;
}
while(1){
int local_var = 0;
// critical section
if(semop(semid, &semopen, 1) == -1){
return 1;
}
local_var = *cal_num + 1;
sleep(1);
*cal_num = local_var;
printf("%d\n", *cal_num);
semop(semid, &semclose, 1);
// end
}
return 1;
}
consumer.c
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/sem.h>
#include<sys/shm.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
int main(int argc, char **argv){
int shmid;
int semid;
int *cal_num;
void *share_mem = NULL;
// semaphores open ans close data
struct sembuf semopen = {0, -1, SEM_UNDO};
struct sembuf semclose = {0, 1, SEM_UNDO};
// connect share mem
shmid = shmget((key_t)1234, sizeof(int), 0666);
if(shmid == -1){
perror("shmget fail");
return 1;
}
// acees key = 3477, access = 0, auth 666
semid = semget((key_t)3477, 0, 0666);
if(semid == -1)
{
perror("semget fail");
return 1;
}
// connet share mem
share_mem = shmat(shmid, NULL, 0);
if(share_mem == (void *)-1){
perror("shmat fail");
return 1;
}
// cal_num ==> share memory
cal_num = (int *) share_mem;
while(1){
// local int
int local_val = 0;
// critical section open
if(semop(semid, &semopen, 1) == -1){
perror("semop error :");
}
local_val = *cal_num+1;
sleep(2);
*cal_num = local_val;
printf("count %d\n", *cal_num);
semop(semid, &semclose, 1);
// close
}
return 1;
}
시그널 함수
시그널 함수를 사용하여 프로세스의 종료를 무시할 수 있는 등
다양한 처리가 가능하지만, 마지막 시그널만 기억한다. (덮어쓰기)
=> 리얼타임 시그널을 사용하면 시그널의 장점을 유지하면서 대기열까지 제공한다.
※ 본 글은 개인 포트폴리오 혹은 공부용으로 사용하기 때문에, 무단 복사 유포는 금지하지만, 개인 공부 용도로는 얼마든지 사용하셔도 좋습니다
'C_C++ 프로그래밍 > 뇌를 자극하는 TCP_IP' 카테고리의 다른 글
[원격 프로시서 호출] [RPC 개념] RPC란 무엇인가?? (0) | 2019.06.16 |
---|---|
시그널 함수의 종류 (0) | 2019.06.02 |
뇌자극 TCP/IP 10강 요약 (0) | 2019.06.02 |
뇌자극 TCP/IP 9강 요약 (0) | 2019.05.29 |
댓글