CS(Computer Science)/UNIX

UNIX - [시스템 V의 프로세스간 통신 - Message queue]

seongmik 2023. 1. 1. 01:32
728x90
반응형

시스템 V의 프로세스간 통신

유닉스는 처음 개발된 이래 다양한 형태로 발전했다. 크게 BSD 계열과 시스템 V 계열로 구분할 수 있다.

시스템V계열 유닉스에서 개발해 제공하는 프로세스간 통신 방법이 메세지 큐, 공유 메모리, 세마포어 이다.

이 세가지를 묶어서 시스템V IPC 라고 한다. 이것은 SVR2에서 처음 개발되었고, SVR4에서도 제공하고 있으며 현재는 대부분의 유닉스 시스템에서 제공하고 있다.

 

IPC 설비

IPC(Inter-Process Communication)란 프로세스 간 통신을 의미한다.

UNIX의 대표적인 IPC는 message_queue, semaphore, shared memory segment가 있다.

 

key

• key는 message_queue, semaphore, shared memory segment에 대한 identifier (file 이름에 해당)이다.

• 서로 다른 process들도 동일 IPC 객체는 같은 key 값으로 접근할 수 있다.

• 시스템에서 unique한 key값을 사용하여야 한다. → 서로 이름을 공유하기 때문에 꼭 유니크하게 만들어야함!

 

key값 생성

#include<sys/ipc.h>
key_t ftok(const char *path, int id);
// 해당 파일의 st_dev, st_ino와 id로 key값 생성
//* path: 파일 시스템에 이미 존재하는 임의의 파일 경로명 -> 중요!!!! 이미 존재하는 파일 경로!
//* id: 키값을 생성할 때 지정하는 임의의 번호 (1~256)

ftok함수를 이용하면 시스템에서 파일 이름과 지정한 id를 조합해서 유니크한 key를 생성한다.

 

IPC 객체 상태 구조

struct ipc_perm{
		uid_t cuid : 생성자의 uid;
		gid_t cgid : 생성자의 gid;
		uid_t uid : 소유자 uid;
		gid_t gid : 소유자 gid;
		mode_t mode : permission (execution은 의미 없음);
};

 

IPC 정보 검색 및 삭제

ipc관련 정보 검색

$ipcs

ipc삭제

$ipcrm -m shmid or -q msqid or -s semid

# -m : shmid인 경우
# -q : msqid인 경우
# -s : semid인 경우

 

message passing

message queue를 통한 message 전달

msgget : queue 생성 → msgQueue만드는데 실패하면 send랑 receive도 실패

msgsnd : message 보내기

msgrcv : message 받기

 

msgget 시스템 호출

구조체

#include <sys/msg.h>
int msgget(key_t key, int permflags);

// key : message queue의 key 값
// permflags = queue에 대한 access permission
// 1. IPC_CREAT :
//            해당 queue가 없으면, 생성한 후 return; 있으면, return
//            이 flag가 설정 되지 않은 경우에는, queue가 존재하는 경우에만 return
// 2. IPC_EXCL :
//            해당 queue가 존재하지 않는 경우만 성공, 아니면 –1 return
//            return 값 : 음수가 아닌 queue identifier -> 파일디스크립터 같은거

 

msgsnd 시스템 호출

#include <sys/msg.h>
int msgsnd(int mqid, const void *message, size_t size, int flags);

// mqid : message queue identifier
// message 의 주소 : 보낼 message가 저장된 주소
// size : message의 크기
// flags = IPC_NOWAIT
		// send가 불가능하면 즉시 return (queue가 가득 찬 경우)
		// flag가 설정 되지 않으면 (0이면), 성공 시까지 blocking
// return 값은 0 or –1

message의 구조

struct mymsg{
		long mtype; // message type (양의 정수) 0은 불가능!!!
		char mtext[SOMEVALUE]; // message 내용 : 원하는 아무 데이터나 가능
};
  • long type의 정수 값을 갖는 mtype과 임의의 message의 내용으로 구성
  • message의 size는 message 내용의 크기만.

 

msgrcv 시스템 호출

사용법

#include <sys/msg.h>
int msgrcv(int mqid, void *message, size_t size, long msg_type, int flags);

/*
mqid : message queue identifier
message 주소 : 받은 message를 저장할 저장 장소의 주소 
size : 준비된 저장 장소의 크기
msg_type =
		0 : queue의 첫 message
		> 0 : 해당 값을 갖는 첫 message
		< 0 : mtyep값이 절대값 보다 작거나 같은 것 중 최소값을 갖는 첫 message

-> 기본적으로 blocking receive
flags = IPC_NOWAIT
		receive가 불가능하면 즉시 return (queue에 해당 msg가 없는 경우)
		return 값은 –1; errno = EAGAIN
		flag가 설정 되지 않으면 (값이 0이면), 성공 시까지 blocking
flags = MSGNOERROR
		message가 size보다 길면 초과분을 자른다. -> 이렇게 받으면 잘랐는지 아닌지 알 수 없음
		flag가 설정 되지 않으면 size 초과 시 error
return 값 :
		receive 성공 시 : 받은 message의 길이
		실패시:-1
		access permission 때문에 실패한 경우 errorno=EACCESS
*/

→ 파이프와 메세지 큐의 차이점 : 파이프는 msg_type을 사용해서 메세지 큐 하나로 여러 사람한테 가는 메세지가 섞여있어도 구분해서 사용가능하다.

→ 또한 메세지 큐는 select같은 함수를 사용하지 않아도 여러 프로세스에게 데이터를 받는지 체크해서 blocking 할지말지 문제를 해결할 수 있다.

→ msg_type으로 receiver가 특정한 msg만 msgQueue에서 받아오게 설정할 수 있다.!!!!!

 

message 송수신의 예

struct q_entry{
		long mtype;
		int mnum;
};
struct q_entry msg;

qid=msgget(0111, 0600|IPC_CREAT);
while(msgrcv(qid, &msg, sizeof(int), 1, 0)>0) {
		msg.mtype=2;
		msg.mnum=msg.mnum+8;
		msgsnd(qid, &msg, sizeof(int), 0);
}

메세지 큐에 메세지의 타입과 내용을 지정한 후, msgsnd 함수를 사용해서 넣는다.

 

msgctl 시스템 호출

msgctl 호출

  • message queue에 대한 정보 획득
  • message queue 제거

사용법

#include <sys/msg.h>
int msgctl(int mqid, int command, struct msqid_ds *msq_stat);

/*
mqid : message queue identifier
command =
		IPC_STAT : msg queue의 상태 정보 확인
		IPC_RMID : msg_queue 삭제
msqid_ds 구조:
		struct ipc_perm msg_perm; // 소유권
		msgqnum_t msg_qnum;       // msg수
		msglen_t msg_qbytes;      // bytes수
		pid_t msg_lspid;          // last sender
		pid_t msg_lrpid;          // last receiver
		time_t msg_stime;         // last sending time
		time_t msg_rtime;         // last receipt time
		time_t msg_ctime;         // last s/r time
*/

 

728x90
반응형

'CS(Computer Science) > UNIX' 카테고리의 다른 글

UNIX - [Shared memory]  (0) 2023.01.02
UNIX - [Semaphore]  (0) 2023.01.01
UNIX - [PIPE - 2]  (0) 2022.12.31
UNIX - [PIPE]  (3) 2022.12.30
UNIX - [MEMORY MAPPING]  (0) 2022.12.30