-
뇌자극 TCP/IP 11강 요약C_C++ 프로그래밍/뇌를 자극하는 TCP_IP 2019. 6. 2. 19:22
IPC = Inter process Communications
네트워크 프로그래밍이 아닌 시스템 프로그래밍에 가까운 부분이다.
소켓 함수는 20개 내외로 제한적이기 때문에, 응용 프로그램 개발을 할 시에는 시스템 프로그래밍 기술이 매우 중요하다.
네트워크 프로그램도 시스템 위에서 작동한다.
프로세스간의 통신을 위해서 사용한다.안정적인 작동이 가능한다.최근에는 쓰레드 기반을 사용한다. (IPC가 너무 난해하기 때문에)System V IPC 계열과 POSIX IPC가 존재한다.
PIPE단방향의 데이터 통신용으로 사용한다.=> 양방향을 사용하기 위해서는 2개를 생성부모 프로세스와 자식 프로세스간의 통신을 위해서 사용한다.이름이 없는 파이프와 이름이 있는 파이프로 나뉨#include<unistd.h>int pipe(int filedes[2]);Named PIPE (이름이 있는 파이프)마치 파일처럼 사용할 수 있다. (이름이 존재)
Unix Domain Socket유닉스 영역의 통신에서만 사용한다.유닉스 영역에 서버/클라이언트 환경을 만들 수 있다.소켓과 거의 동일하다.중대형 어플리케이션 만들기 위해서 용이하다. (mysql)struct sockaddr_un sockaddr;socket(AF_UNIX, SOCK_STREAM, 0);sprintf(sockaddr.sun_path, "filename.sock");공유 메모리
PIPE와 Unix Domain Socket는 메시지 기반의 IPC로 공유 메모리를 사용할 수 있다.메모리 공간을 공유하며, 빠르고 효율적이다.
하지만, 접근제어가 필요하게 된다 => Mutex 혹은 Semaphores가 필요함
공유 메모리 생성shmget 함수로 공유 메모리 생성이 가능하다.shmid = shmget((key_t) key, int size, int shmflg);1. key : 공유 메모리는 커널에서 관리를 한다. 각 프로세스는 이를 이용해 접근할 공유 메모리를 식별한다.2. size : 커널에게 요청할 메모리의 크기3. shmflgIPC_CREAT : 공유 메모리를 새로 생성한다.IPC_EXCL : IPC_CREAT와 함께 사용하며, key 값을 가지는 공유 메모리 영역이 존재하면 에러가 난다.공유 메모리 첨부와 분리하기shmdt(const void *shmaddr)
shmaddr : 분리할 공유 메모리를 가리키는 포인터로 shmat에서 사용했던 shmaddr를 그대로 사용한다.
shmat(int shmid, const void *shmaddr, int shmflg)
shmid : shmget 함수로 만든 공유 메모리 식별자
shmaddr : 공유 메모리 영역을 가리키는 주소이다. NULL인 경우 운영체제가 알아서 찾아서 반환해준다.
shmflg : 쓰기 전용을 지정할 수는 없고, 값을 지정하게 되면 읽기 전용이 된다.
공유 메모리 사용 예제produce.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;
// 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;
}하지만, 공유 데이터에 서로 접근하여 사용하게 되기 때문에접근 제어가 필요하게 된다.=> critical section (임계영역)이 필요세마포어 (Semaphores) 생성int semget(key_t key, int nsems, int semflg);key : 공유 메모리와 같이 식별하여 생성할 수 있다.nsems : 세마포어는 배열로 만들어진다. 이때 그 크기를 지정한다.semflg : 세마포어의 생성 방식을 결정한다.IPC_CREAT : 커널에 key 값의 세마포어가 없다면 새로 생성한다.IPC_EXCL : IPC_CREAT와 함께 사용한다. key가 이미 존재하면 에러 발생세마포어 임계영역 관리
int semop(int semid, struct sembuf *sops, unsigned nsops)
semid : semget 함수로 생성한 세마포어 식별자이다.
sops : 세마포어 제어를 위해 사용하는 세마포어 구조체이다.
nsops : 세마포어 집합의 개수이다. 하나만 접근이 가능할려면 1을 사용
간단한 세마포어 예제producer.c#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