π 곡λΆνλ μ§μ§μνμΉ΄λ μ²μμ΄μ§?
[νλ‘μΈμ€μ μ€λ λ λ€μ€ μ²λ¦¬] νλ‘μΈμ€ κ° ν΅μ (IPC) with μ λμ€ μμ€ν V/XSI (λ©μμ§ ν, μΈλ§ν¬μ΄, 곡μ λ©λͺ¨λ¦¬) λ³Έλ¬Έ
[νλ‘μΈμ€μ μ€λ λ λ€μ€ μ²λ¦¬] νλ‘μΈμ€ κ° ν΅μ (IPC) with μ λμ€ μμ€ν V/XSI (λ©μμ§ ν, μΈλ§ν¬μ΄, 곡μ λ©λͺ¨λ¦¬)
μ§μ§μνμΉ΄ 2024. 1. 12. 18:36<μμμ§ λμ μ¬λ¬ΌμΈν°λ·μ μν 리λ μ€ νλ‘κ·Έλλ° with λΌμ¦λ² 리νμ΄ μμ μ μ°Έκ³ ν΄μ μμ±νμμ΅λλ€ :-)>
β μ λμ€ μμ€ν V
AT&T 벨 μ°κ΅¬μμμ λ§λ€λ μ λμ€ κ³μ΄μ ν΅μΉν¨
νμ¬ λ¦¬λ μ€λ μ λμ€ μμ€ν V κ³μ΄μ μ λμ€μμ μ 곡νλ μμ€ν νΈμΆκ³Ό BSD κ³μ΄μ μ λμ€μμ μ 곡νλ μμ€ν νΈμΆμ λͺ¨λ μ 곡νλ€
μμ€ν Vμ IPC λ POSIX IPC κ° λ±μ₯ν μ΄νλ‘ XSI (X System Interface) λ‘ λΆλ¦¬μ°κ³ μλ€
κ΅¬λΆ | λ΄μ© |
λ©μμ§ ν (Message Queue) | λ©μμ§ λ¨μλ‘ I/O λ₯Ό μννλλ°, λ€λ₯Έ IPC μ λ¬λ¦¬ μλ²μ ν΄λΌμ΄μΈνΈκ° κ°μ μκ°μ μ‘΄μ¬ν νμκ° μλ€ |
μΈλ§ν¬μ΄ (Semaphore) | λ°μ΄ν° μ μ‘μ λͺ©μ μΌλ‘ λ§λ€μ΄μ§ IPC κ° μλ νλ‘μΈμ€ λκΈ°νμ νμν 곡μ λ³μμ κ°μ 곡μ λ 리μμ€ μ νμ μν μΈλ§ν¬μ΄μ μ°Έμ‘°μ μ‘°μ§μ μν΄ λ§λ€μ΄μ§ IPC |
곡μ λ©λͺ¨λ¦¬ (Shared Memory) | λͺ¨λ IPC λ λΉλ²ν λ©λͺ¨λ¦¬ 볡μ¬λ‘ μΈν μ±λ₯ λ¬Έμ κ° μ κΈ°λλλ°, 곡μ λ©λͺ¨λ¦¬λ 컀λκ³Ό νλ‘μΈμ€ μ¬μ΄μ λ©λͺ¨λ¦¬ 볡μ¬λ₯Ό 2ν μ€μμΌλ‘μ¨ λΉμ½μ μΌλ‘ IPC μ±λ₯μ ν₯μμν¬ μ μλ€ κ³΅μ λ©λͺ¨λ¦¬μλ μΈλ§ν¬μ΄ κ°μ λκΈ°ν λ©μ»€λμ¦μ΄ λ³λλ‘ μꡬλλ€ |
βοΈ λ©μμ§ ν
μ λμ€ μμ€ν Vμ νλ‘μΈμ€ μ¬μ΄μμ μλ‘ ν΅μ μ νκΈ° μν΄ μ¬μ©λλ λ©μ»€λμ¦
μ μΆλ ₯ λ°μ΄ν°λ₯Ό 컀λ λ΄λΆμ λ©μμ§ λ¦¬μ€νΈ ννλ‘ λ³΄κ΄νλλ°, λ©μμ§ νμ μ μ νμ μΌλ‘ λ©μμ§μ κ²μμ΄ κ°λ₯νλ€
FIFO μ λΉμ·νμ§λ§ λ©μμ§λ μ€κ°μ μ μ₯μ΄ λκΈ° λλ¬Έμ λ©μμ§λ₯Ό 보λ΄λ νλ‘μΈμ€μ λ©μμ§λ₯Ό λ°λ νλ‘μΈμ€κ° λμΌν μμ μ μ£Όκ³ λ°μ νμκ° μλ€
λ©μμ§ νμμλ msqid_ds ꡬ쑰체λ₯Ό μ¬μ©νλ©°, νΈμΆμ μ€ν¨νλ©΄ -1μ λ°ννλ€
λ©μμ§ νλ₯Ό μ¬μ©νκΈ° μν΄μλ νμ¬ λ©μμ§λ₯Ό μ£Όκ³ λ°μ μ μλ μ±λμ΄ νμνλ° msgget() ν¨μλ₯Ό μ΄μ©ν΄μ νλ, νΈμΆμ μ±κ³΅νλ©΄ μ±λμ ID κ° λ°νλλ€
λ©μμ§ νμ λν μ±λμ νλν νμλ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μμΌ νλλ°,
λ©μμ§ λ³΄λ΄λ msgsnd() ν¨μ νΈμΆμ μ±κ³΅νλ©΄ 0 λ°ν
λ©μμ§ λ°λ msgrcv() ν¨μ νΈμΆμ μ±κ³΅νλ©΄ μ½μ λ°μ΄ν°μ λ°μ΄νΈ μκ° λ°νλλ€
λ°μ΄ν° μ£Όκ³ λ°λ msgbuf ꡬ쑰체
μ±λμ μ μ΄νκ±°λ μμ νλ msgctl() ν¨μ
// λ©μμ§ νλ₯Ό μ΄μ©ν ν΅μ server
// μλ²μ ν΄λΌμ΄μΈνΈλ λμΌν ν€ κ° κ°μ ΈμΌ νλ€ (51234 λ‘ μ€μ ν¨)
#include <stdio.h>
#include <unistd.h>
#include <sys/msg.h>
#define MSQKEY 51234
struct msgbuf {
long mtype; /* λ©μμ§μ νμ
: 0 μ΄μμ μ μ«κ° */
char mtext[BUFSIZ]; /* λ©μμ§μ λ΄μ© : 1λ°μ΄νΈ μ΄μμ λ¬Έμμ΄ */
};
int main(int argc, char **argv)
{
key_t key;
int n, msqid;
struct msgbuf mb;
key = MSQKEY;
/* λ©μμ§ νμ μ±λμ μμ±νλ€. */
if((msqid = msgget(key, IPC_CREAT | IPC_EXCL | 0666)) < 0) {
perror("msgget()");
return -1;
}
/* λ©μμ§ νμμ λ°μ΄ν°λ₯Ό κ°μ Έμ¨λ€. */
while((n = msgrcv(msqid, &mb, sizeof(mb), 0, 0)) > 0) {
switch (mb.mtype) {
/* λ©μμ§ νμ
(mtype)μ΄ 1μ΄λ©΄ νλ©΄μ κ°μ Έμ¨ λ°μ΄ν°λ₯Ό μΆλ ₯νλ€. */
case 1:
write(1, mb.mtext, n);
break;
/* λ©μμ§ νμ
(mtype)μ΄ 2μ΄λ©΄ λ©μμ§ νμ μ±λμ μμ νλ€. */
case 2:
if(msgctl(msqid, IPC_RMID, (struct msqid_ds *) 0) < 0) {
perror("msgctl()");
return -1;
}
break;
}
}
return 0;
}
/*
μλ²λ λ©μμ§ νλ₯Ό μν μ±λμ μμ±νκ³ λ©μμ§ νλ‘λΆν° λ°μ΄ν°λ₯Ό κ°μ Έμμ mtype κ°μ΄ 1μ΄λ©΄ νλ©΄μ κ°μ Έμ¨ λ°μ΄ν° μΆλ ₯
mtype κ°μ΄ 2μ΄λ©΄ λ©μμ§ νμ λν μ±λμ μμ νλ€
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ gcc -o msg_server msg_server.c
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ ./msg_server &
*/
// λ©μμ§ νλ₯Ό μ΄μ©ν ν΅μ client
// μλ²μ ν΄λΌμ΄μΈνΈλ λμΌν ν€ κ° κ°μ ΈμΌ νλ€ (51234 λ‘ μ€μ ν¨)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/msg.h>
#define MSQKEY 51234
struct msgbuf {
long mtype;
char mtext[BUFSIZ];
};
int main(int argc, char **argv)
{
key_t key;
int rc, msqid;
char* msg_text = "hello world\n";
struct msgbuf *mb;
mb = (struct msgbuf*)malloc(sizeof(struct msgbuf) + strlen(msg_text));
key = MSQKEY;
if((msqid = msgget(key, 0666)) < 0) { /* λ©μμ§ νμ μ±λμ κ°μ Έμ¨λ€. */
perror("msgget()");
return -1;
}
/* mtypeμ 1λ‘ μ€μ νκ³ hello worldλΌλ λ¬Έμμ΄μ 보λΈλ€. */
mb->mtype = 1;
strcpy(mb->mtext, msg_text);
rc = msgsnd(msqid, mb, strlen(msg_text)+1, 0); /* λ©μμ§ νλ‘ λ°μ΄ν°λ₯Ό 보λΈλ€. */
if(rc == -1) {
perror("msgsnd()");
return -1;
}
/* mtypeμ 2λ‘ μ€μ νκ³ λ³΄λΈλ€. */
mb->mtype = 2;
memset(mb->mtext, 0, sizeof(mb->mtext));
if(msgsnd(msqid, mb, sizeof(mb->mtext), 0) < 0) {
perror("msgsnd()");
return -1;
}
return 0;
}
/*
ν΄λΌμ΄μΈνΈλ mtype μ 1λ‘ μ€μ νκ³ λ¬Έμμ΄μ μλ²λ‘ 보λ΄κ³
λ€μ mtype μ 2λ‘ μ€μ νκ³ μλ²λ‘ λ©μμ§λ₯Ό 보λΈλ€
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ gcc -o msg_client msg_client.c
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ ./msg_client
*/
gcc -o msg_server msg_server.c
./msg_server &
gcc -o msg_client msg_client.c
./msg_client
βοΈ IPC κ΄λ ¨ λͺ λ Ήμ΄
μ λμ€ μμ€ν vμ μ€μ λ IPC μ±λμ νμΈνκ³ μΆμ κ²½μ°μλ ipcs λͺ λ μ΄ μ¬μ©νλ€
-q : λ©μμ§ ν
-s : μΈλ§ν¬μ΄
-m : 곡μ λ©λͺ¨λ¦¬
ipcs [-q | -m | -s]
μ±λμ μμ±νκ³ μΆμ κ²½μ°
ipcmk [-M size] [-S nsems] [-Q] [-p mode]
μ€μ λ μ±λμ μμ νκ³ μΆμ κ²½μ°
μ±λμ ID λ μ±λμ ν€ μ΄μ©ν΄μ μμ ν μ μμ
ipcrm [-q | -m | -s { μ±λμ_ID }+ ] [-Q | -M | -S] { μ±λμ_Key }+ ]
λ©μμ§ν μλ² μ€νν ν ipcs λͺ λ Ήμ΄ μννλ©΄ ν€μ λ©μμ§ νμ ID κ° νμλλ€
-q μ΅μ κ³Ό λ©μμ§ νμ ID μ΄μ©ν΄μ ν΄λΉ μ±λ μμ ν μ μλ€
ipcs
ipcrm -q msqidμ μΌμ
βοΈ μΈλ§ν¬μ΄ (Semaphore)
λ κ°μ μμμ ν¨μλ‘ μ‘°μλλ μ μ λ³μ
λ€μ€ νλ‘κ·Έλλ° νκ²½μμ 곡μ μμμ λν μ κ·Όμ μ ννλ λ°©λ²
λ€μμ μμμ λκ³ κ²½μνλ νλ‘μΈμ€λ€ μ¬μ΄μμ νμν λκΈ°ν κΈ°λ²μΌλ‘ μμμ μλ₯Ό κΈ°λ‘νλ μΈλ§ν¬μ΄ λ³μμ P (κ°μ), V (μ¦κ°) μ°μ°μ μ΄μ©νμ¬ λκΈ°ν νλ€
μΈλ§ν¬μ΄ μλ£ κ΅¬μ‘°λ semid_ds ꡬ쑰체
μΈλ§ν¬μ΄λ₯Ό μ¬μ©νκΈ° μν΄ μ±λ μμ± semget() ν¨μ μννλ©°, μ±κ³΅νλ©΄ μ±λμ ID λ°νλκ³ μ€ν¨νλ©΄ -1
μΈλ§ν¬μ΄λ₯Ό μ¦κ°νκ±°λ κ°μλ₯Ό νκΈ° μν΄ semop() ν¨μ μννλ©°, μ±κ³΅νλ©΄ 0 λ°νλκ³ μ€ν¨νλ©΄ -1
μΈλ§ν¬μ΄λ₯Ό μ€μ ν λ sembuf ꡬ쑰체 μ¬μ©
μΈλ§ν¬μ΄λ₯Ό μ μ΄νκ±°λ μμ ν λμλ semctl() ν¨μ
// μΈλ§ν¬μ΄λ₯Ό μννκΈ° μν κ³Όμ
// μΈλ§ν¬μ΄μ P μ°μ°κ³Ό V μ°μ°μ λν ν¨μ
// λ ν¨μλ₯Ό μ΄μ©ν΄μ μΈλ§ν¬μ΄μ λμ μμ보기
#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>
int cnt = 0;
static int semid;
void p() /* μΈλ§ν¬μ΄μ P μ°μ° */
{
struct sembuf pbuf;
pbuf.sem_num = 0;
pbuf.sem_op = -1;
pbuf.sem_flg = SEM_UNDO;
if(semop(semid, &pbuf, 1) == -1) /* μΈλ§ν¬μ΄μ κ°μ μ°μ°μ μννλ€. */
perror("p : semop()");
}
void v() /* μΈλ§ν¬μ΄μ V μ°μ° */
{
struct sembuf vbuf;
vbuf.sem_num = 0;
vbuf.sem_op = 1;
vbuf.sem_flg = SEM_UNDO;
if(semop(semid, &vbuf, 1) == -1) /* μΈλ§ν¬μ΄μ μ¦κ° μ°μ°μ μννλ€. */
perror("v : semop()");
}
int main(int argc, char **argv)
{
union semun { /* semun 곡μ©μ²΄ */
int val;
struct semid_ds *buf;
unsigned short int *arrary;
} arg;
/* μΈλ§ν¬μ΄μ λν μ±λ μ»κΈ° */
if((semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666)) == -1) {
perror("semget()");
return -1;
}
arg.val = 1; /* μΈλ§ν¬μ΄ κ°μ 1λ‘ μ€μ */
if(semctl(semid, 0, SETVAL, arg) == -1) {
perror("semctl() : SETVAL");
return -1;
}
while(1) {
if(cnt >= 8) {
cnt--;
p();
printf("decrease : %d\n", cnt);
break;
} else {
cnt++;
v();
printf("increase : %d\n", cnt);
usleep(100);
}
}
/* μΈλ§ν¬μ΄μ λν μ±λ μμ */
if(semctl(semid, 0, IPC_RMID, arg) == -1) {
perror("semctl() : IPC_RMID");
return -1;
}
return 0;
}
/*
μΈλ§ν¬μ΄λ₯Ό μν μ±λμ μμ±νκ³ μΈλ§ν¬μ΄ ν κ°λ₯Ό μμ±νλ€
μ½λ λ΄μμ μΈλ§ν¬μ΄μ λν Pμ°μ°κ³Ό Vμ°μ°μ μννλλ°,
Vμ°μ°μΌλ‘ μΈλ§ν¬μ΄κ° μ¦κ°λκ³ λ μ΄νμ Pμ°μ°μ ν΅ν΄ κ°μλ μ μλ€
λ μ°μ°μ μ€ν μμλ₯Ό λ°κΎΈλ©΄ Pμ°μ°μμλ μ¬μ©ν μ μλ μΈλ§ν¬μ΄κ° μκΈΈ λκΉμ§ λκΈ°νλ€
8κ°κΉμ§ μΈλ§ν¬μ΄κ° μ¦κ°ν ν λ€μ μΈλ§ν¬μ΄κ° κ°μνλ κ²μ νμΈν μ μλ€
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ gcc -o sem sem.c
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ ./sem
*/
gcc -o sem sem.c
./sem
βοΈ κ³΅μ λ©λͺ¨λ¦¬
νλ‘μΈμ€ κ°μ λ©λͺ¨λ¦¬λ₯Ό 곡μ νλ λ°©μ
λ©λ¦¬ λ³΅μ¬ νμλ₯Ό μ€μ¬μ μ±λ₯ ν₯μμ μ΄λλ€
μ¬λ¬ νλ‘μΈμ€λ€μ΄ λμμ κ°μ λ©λͺ¨λ¦¬μ μ£Όμλ‘ μ κ·Όν μ μκΈ° λλ¬Έμ μΈλ§ν¬μ΄ κ°μ λκΈ°ν κΈ°λ²μ΄ νμνλ€
리λ μ€μμλ 곡μ λ©λͺ¨λ¦¬λ₯Ό μν ν¨μλ€μ μ 곡νλ€
곡μ λ©λͺ¨λ¦¬λ₯Ό μ¬μ©νκΈ° μν΄μλ 곡μ λ©λͺ¨λ¦¬μ λν μ±λμ μμ±νκ±°λ κΈ°μ‘΄μ μ±λμ κ°μ ΈμμΌ νλ€
shmget() ν¨μλ‘ μνμ μ±κ³΅νλ©΄ ν΄λΉ μ±λμ λν ID λ°ν, μλ¬κ° λ°μνλ©΄ -1 λ°ν
곡μ λ©λͺ¨λ¦¬μ μ¬μ©μ μν΄μλ 곡μ λ©λͺ¨λ¦¬λ₯Ό νμ¬ νλ‘μΈμ€μ μ°κ²°νκ³ λ©λͺ¨λ¦¬μ μμ μ£Όμλ₯Ό κ°μ Έμ€λλ° shmat() ν¨μλ₯Ό μ¬μ©νλ€
μ¬μ©μ΄ λλ 곡μ λ©λͺ¨λ¦¬λ νμ¬μ νλ‘μΈμ€μμ μ°κ²°μ ν΄μ ν΄μΌ νλλ° shmdt() ν¨μλ₯Ό μ¬μ©νλ€
μ°κ²°λ μ±λμ μ μ΄νκ±°λ ν΄μ νκ³ μΆμ κ²½μ°μλ shmctl() ν¨μμ΄λ©° μ±κ³΅νλ©΄ 0, μ€ν¨νλ©΄ -1μ λ°ννλ€
// 곡μ λ©λͺ¨λ¦¬
// 2κ°μ νλ‘μΈμ€λ₯Ό λ§λ€μ΄μ λΆλͺ¨ νλ‘μΈμ€μ μμ νλ‘μΈμ€κ° κ°μ λ©λͺ¨λ¦¬ κ³΅κ° μ¬μ©νκΈ°
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#define SHM_KEY 0x12345 /* 곡μ λ©λͺ¨λ¦¬λ₯Ό μν ν€ */
int main(int argc, char **argv)
{
int i, pid, shmid;
int *cVal;
void *shmmem = (void *)0;
if((pid = fork()) == 0) { /* μμ νλ‘μΈμ€λ₯Ό μν μ€μ */
/* 곡μ λ©λͺ¨λ¦¬ 곡κ°μ κ°μ Έμ¨λ€. */
shmid = shmget((key_t)SHM_KEY, sizeof(int), 0);
if(shmid == -1) {
perror("shmget()");
return -1;
}
/* 곡μ λ©λͺ¨λ¦¬λ₯Ό μ¬μ©νκΈ° μν΄ νλ‘μΈμ€μ λ©λͺ¨λ¦¬μ λΆμΈλ€. */
shmmem = shmat(shmid, (void *)0, 0666 | IPC_CREAT);
if(shmmem == (void *)-1) {
perror("shmat()");
return -1;
}
cVal = (int *)shmmem;
*cVal = 1;
for(i = 0; i < 3; i++) {
*cVal += 1;
printf("Child(%d) : %d\n", i, *cVal);
sleep(1);
}
} else if(pid > 0) { /* λΆλͺ¨ νλ‘μΈμ€λ‘ 곡μ λ©λͺ¨λ¦¬μ λ΄μ©μ νμ */
/* 곡μ λ©λͺ¨λ¦¬ 곡κ°μ λ§λ λ€. */
shmid = shmget((key_t)SHM_KEY, sizeof(int), 0666 | IPC_CREAT);
if(shmid == -1) {
perror("shmget()");
return -1;
}
/* 곡μ λ©λͺ¨λ¦¬λ₯Ό μ¬μ©νκΈ° μν΄ νλ‘μΈμ€μ λ©λͺ¨λ¦¬μ λΆμΈλ€. */
shmmem = shmat(shmid, (void *)0, 0);
if(shmmem == (void *)-1) {
perror("shmat()");
return -1;
}
cVal = (int *)shmmem;
for(i = 0; i < 3; i++) {
sleep(1);
printf("Parent(%d) : %d\n", i, *cVal);
}
}
shmctl(shmid, IPC_RMID, 0);
return 0;
}
/*
2κ°μ νλ‘μΈμ€λ₯Ό μμ±ν ν shmget() ν¨μλ₯Ό μ΄μ©ν΄μ 곡μ λ©λͺ¨λ¦¬ λν μ±λμ κ°μ Έμμ
shmat() ν¨μλ₯Ό μ΄μ©ν΄ 곡μ λ©λͺ¨λ¦¬λ₯Ό νμ¬μ νλ‘μΈμ€μ 곡κ°μ λΆμΈλ€
μμ νλ‘μΈμ€μμλ λ³μμ κ°μ μ¦κ°μν€κ³ μ΄λ₯Ό νλ©΄μ μΆλ ₯μν€κ³ 1μ΄κ° μ¬λ¦½ λͺ¨λ
λΆλͺ¨ νλ‘μΈμ€λ 1μ΄κ° μ¬λ¦½ λͺ¨λμ λ€μ΄κ° ν κΉ¨μ΄λμ 곡μ λ©λͺ¨λ¦¬μ λν λ΄μ©μ μΆλ ₯νλ€
μμ νλ‘μΈμ€μμ 곡μ λ©λͺ¨λ¦¬λ‘ μ€μ ν΄λμ λ΄μ©μ λΆλͺ¨ νλ‘μΈμ€μμλ κ°μ λ©λͺ¨λ¦¬λ₯Ό 곡μ νμ¬ λμΌν κ°μ΄ μΆλ ₯λλ€
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ gcc -o shm shm.c
@gani0325 β /workspaces/IoT_Linux_RaspberryPi/Process_Signal (main) $ ./shm
*/
gcc -o shm shm.c
./shm