ํฐ์คํ ๋ฆฌ ๋ทฐ
IPC(Inter-Process Cmmuniciation)๋ ํ๋ก์ธ์ค๋ค ์ฌ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ํ์, ๊ทธ์ ๋ํ ๋ฐฉ๋ฒ ๋๋ ๊ฒฝ๋ก๋ฅผ ์๋ฏธํ๋ค.
pipe์ ์ข ๋ฅ
pipe๋ ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ํ๋ก์ธ์ค์ ๋ฐ๋ผ write, read๋ฅผ ํ ์ ์๋ค. ๋ํ ๊ด๋ จ๋ ํ๋ก์ธ์ค๊ฐ ์ฌ์ฉํ๋ pipe์ ๊ด๋ จ ์๋ ํ๋ก์ธ์ค ๊ฐ์๋ ์ฌ์ฉ ๊ฐ๋ฅํ named pipe๋ก ๋๋๋ค.
pipe
int process_pipe(pid_t pid, int *pipe_p, char *buf)
{
int status;
if (pid == 0) {
/* child process */
close(pipe_p[1]);
read(pipe_p[0], buf, sizeof(buf));
printf("%d get msg %s\n", pid, buf);
close(pipe_p[0]);
return 0;
} else if (pid > 0) {
/* parent process */
close(pipe_p[0]);
strncpy(buf, "input some data...", sizeof(buf) - 1);
printf("%d send msg %s\n", pid, buf);
write(pipe_p[1], buf, strlen(buf));
close(pipe_p[1]);
pid = wait(&status);
return 0;
}
return -1;
}
- pipe ๋์คํฌ๋ฆฝํฐ 0๋ฒ์ read, 1๋ฒ์ write์ด๋ค.
- ์์ ์์๋ ๋ถ๋ชจ ํ๋ก์ธ์ ๊ฒฝ์ฐ write๋ฅผ ํ๊ณ , ์์ ํ๋ก์ธ์ค๋ read๋ฅผ ํ๋ค.
- ์ฐ๊ด๋ ํ๋ก์ธ์ค, ์ฆ pipe ๋์คํฌ๋ฆฝํฐ๋ฅผ ์๊ณ ์๋ ํ๋ก์ธ์ค ๋ผ๋ฆฌ ์ํธ ๊ฐ์ ์ ๋ณด๋ฅผ ๊ตํํ ์ ์๋ค.
named pipe
#define FILENAME "./test"
static int reader()
{
int fd;
char buf[128];
unlink(FILENAME);
fd = open(FILENAME, O_RDONLY);
if (fd < 0) {
perror("open()");
return -1;
}
read(fd, buf, sizeof(buf));
close(fd);
return 0;
}
static int writer()
{
int fd;
char buf[128];
unlink(FILENMAE);
if (mkfifo(FILENAME, 0644)) {
perror("mkfifo()");
return -1;
}
fd = open(FILENAME, O_WRONLY);
if (fd < 0) {
perror("open()");
return -1;
}
strcpy(buf, "test write", sizeof(buf));
write(fd, buf, strlen(buf));
close(fd);
return 0;
}
named pipe๋ ํ์ผ์ ์ ๊ทผ ๊ฐ๋ฅํ ๊ฒฝ์ฐ, ํ๋ก์ธ์ค ๊ฐ์ ์ ๋ณด๋ฅผ ๊ณต์ ํ ์ ์๋ค. ์ฃผ์ํ ์ ์ open์ O_NONBLOCK flag๋ฅผ ์ค์ ํ์ง ์์ผ๋ฉด, ์๋ฐฉํฅ(read/write)์ผ๋ก ์ด๋ฆด ๋ blocking ๋๋ค๋ ์ ์ด๋ค.
Message Queue
๋ฉ์์ง ํ๋ ์ ํ์ ๊ฐ์ด SysV์ POSIX ๋ฐฉ์์ผ๋ก ๋๋๋ค.
- POSIX ๋ฐฉ์์ File I/O ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ฏ๋ก, I/O Multiplexing์ด ๊ฐ๋ฅํ๋ค.
- SysV๋ ๋ฉ์์ง ํ์ ์ ๊ตฌ๋ถํ๋ฏ๋ก, ํ๋์ write์ ๋ค์์ reader๋ก ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
- pipe์ ๋ฌ๋ฆฌ byte stream์ด ์๋ ๋ฉ์์ง ๋จ์๋ก ์ฒ๋ฆฌ ๋๋ค.
- FIFO๋ก ์ฒ๋ฆฌ๋๋ฉฐ, MQ์ ์ ๊ทผ ๊ฐ๋ฅํ๋ค๋ฉด ์ฐ๊ด์ด ์๋ ํ๋ก์ธ์ค๋ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
#define MQ_NAME "/test_mq"
// MQ ์ด๋ฆ์ /๋ก ์์ํ์ฌ์ผ ํจ.
#define BUF_SIZE 8192
static int init_mq()
{
mqd_t mqd;
struct mq_attr attr;
mqd = mq_open(MQ_NAME, O_RDWR | O_CREAT, 0644, NULL);
if (mqd == -1) {
perror("mq_open()");
return -1;
}
memset(&attr, 0, sizeof(attr));
if (mq_getattr(mqd, &attr) == -1) {
close(mqd);
return -1;
}
return mqd;
}
static int sender()
{
int mqd = init_mq();
char buf[BUF_SIZE];
if (mqd == -1) {
perror("init_mq()");
return -1;
}
memset(buf, 0, sizeof(buf));
sprintf(buf, sizeof(buf), "TEST...");
if (mq_send(mqd, buf, sizeof(buf), 0) == -1) {
perror("sender()");
return -1;
}
return 0;
}
static int receiver()
{
int mqd;
char buf[BUF_SIZE];
mqd = init_mq();
if(mqd == -1) {
perror("init_mq()");
return -1;
}
memset(buf, 0, sizeof(buf));
if (mq_receive(mqd, buf, sizeof(buf), NULL) == -1) {
perror("receiver()");
return -1;
}
printf("recv msg %s\n", buf);
return 0;
}
POSIX MQ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๊ฐ๋จํ ๊ตฌํํ๋ฉด ์์ ๊ฐ๋ค.
- MQ ๊ด๋ฆฌ์ ๊ด๋ จ๋ ํจ์๋ mq_open, mq_close, mq_unlink๊ฐ ์๋ค.
- ์ก์์ ์ ์ํด์๋ mq_send, mq_receive๋ฅผ ์ฌ์ฉํ๋ค.
- ์ด ์ธ์ mq_setarr, mq_getarr, mq_notify๊ฐ ์๋ค.
- mq_open, mq_send, mq_receive๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ struct mq_attr์ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ฉํ๋ค.
- ๋ง์ฝ MQ์ ๋ด์ฉ์ด ์๋๋ฐ receive๋ฅผ ํ๊ฒ ๋๋ฉด blocking ๋๋ค.
- ์ฌ์ฉ๋๋ MQ๋ `/dev/mqueue`์ ํ์ ๋๋ ํ ๋ฆฌ์ ์์ฑ๋๋ค.
Socket
๋๋ฉ์ธ์ ํตํด ์์ผ์ ๊ตฌ๋ถํ๋ฉฐ, 3๊ฐ์ง๋ก ์ ์ํ ์ ์๋ค.
- Unix Domain Socket
- Host-only socket
- file path๋ฅผ address๋ก ์ฌ์ฉํ๋ค.
- IPv4 Socket
- IPv6 Socket
Socket type
Socket์ ํ์ ์ 2๊ฐ์ง๋ก ๊ตฌ๋ถ๋๋ค.
- Stream
- ์๋ฐฉํฅ์ผ๋ก ์ฐ๊ฒฐ(Connect-Orient)๋์ด์ผ ํ๋ค.
- ์ ์ก ๋จ์๋ byte stream์ด๋ค.
- TCP์ ํน์ฑ์ ๊ฐ์ง๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
- ๊ทธ๋ฆผ ์์์ ๋ณด๋ฉด Socket ์์ฑ ํ, ์ฐ๊ฒฐ ๊ณผ์ ์ด ํ์ํ๋ค.
- Datagram
- ์ํธ ์ฐ๊ฒฐ(Connectionless)๋์ง ์์๋ ๋๋ค.
- ์ ์ก ๋จ์๋ Message์ด๋ค.
- UDP์ ํน์ฑ์ ๊ฐ์ง๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
- ๊ทธ๋ฆผ ์์์ ๋ณด๋ฉด, Socket ์์ฑ ํ, ๋ณ๋์ ์ฐ๊ฒฐ ๊ณผ์ ์ด ํ์ ์๋ค.
Server side
// Socket(Stream) Server Side
#define SOCK_PATH "test"
int receiver(int sock, void *buf, size_t buflen, int flag)
{
int ret;
int cur_read = 0;
while (cur_read < buflen) {
ret = recv(sock, (char *)buf + cur_read, buflen, flag);
if (ret == -1) {
return ret;
}
cur_read += ret;
}
return 0;
}
static int server()
{
int sock;
int peer;
int ret;
struct sockaddr_un addr;
char buf[1024];
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
perror("socket()");
return -1;
}
/* addr init */
memset(&addr, 0, sizeof(addr));
addr.sun_familiy = AF_UNIX;
strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
if bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un) == -1) {
perror("bind()");
goto err;
}
listen(sock, 3);
peer = accept(sock, NULL, NULL);
if (peer < 0) {
perror("accept()");
goto err;
}
ret = receiver(peer, buf, sizeof(buf), 0);
if (ret == -1) {
perror("recv()");
goto err;
}
printf("from to client %s\n", buf);
close(sock);
return 0;
err:
close(sock);
return -1;
}
Host side
// Socket(Stream) Client Side
#define SOCKET_PATH "test"
int sender(int sock, void *buf, size_t buflen, int flag)
{
int ret;
int cur_write = 0;
while (cur_write < buflen) {
ret = send(sock, (char *)buf + cur_write, buflen, flag);
if (ret == -1) {
return ret;
}
cur_write += ret;
}
return 0;
}
static int client()
{
int sock;
int ret;
char buf[64];
struct sockaddr_un addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket()");
return -1;
}
/* addr init */
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
perror("connect()");
goto err;
}
memset(buf, 0, sizeof(buf));
sprintf(buf, sizeof(buf), "Send TEST..");
ret = sender(sock, buf, sizeof(buf), 0);
if (ret < 0) {
perror("send()");
goto err;
}
close(sock);
return 0;
err:
close(sock);
return -1;
}
Shared Memory
pipe, MQ, Socket์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ์ฌ ํ๋ก์ธ์ค ๊ฐ์ ์ ๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ํ์์ด๋ค. ์ด์ ๋ฌ๋ฆฌ SHM์ ํ๋ก์ธ์ค ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๊ณต์ ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋๋ค.
file mapping
#define FILE_NAME "test"
static int prosumer()
{
int fd;
int *maped;
int i;
fd = open(FILE_NAME, O_RDWR | O_CREATE, 0644);
if (fd == -1) {
perror("open()");
return -1;
}
// ํ์ผ์ ์์ฑํ์ฌ์ผ ํ๋ฏ๋ก fruncate๋ฅผ ํธ์ถ.
if (ftruncate(fd, 4096) == -1) {
perror("fruncate()");
goto err;
}
maped = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (maped == MAP_FAILED) {
perror("mmap()");
goto err;
}
for (i = 0; i < 100; i++) {
maped[i] = i + 1;
}
munmap(maped, 4096);
close(fd);
return 0;
err:
close(fd);
return -1;
}
#define FILE_NAME "test"
static int consumer()
{
int fd;
int maped;
int i;
fd = open(FILE_NAME, O_RDWR);
if (fd == -1) {
perror("open()");
return -1;
}
maped = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (maped == MAP_FAILED) {
perror("mmap()");
close(fd);
return -1;
}
for (i = 0; i < 100; i++) {
printf("%d\n", maped[i]);
}
munmap(maped, 4096);
close(fd);
}
์์ ์ฝ๋๋ mmap์ ํตํด ๋์ผํ ํ์ผ์ 2๊ฐ์ ํ๋ก์ธ์ค์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋นํ๋ ๊ฒ์ด๋ค.
- prosumer
- ํ์ผ์ ์์ฑํ์ฌ์ผ ํ๋ฏ๋ก, open ํ ftruncate๋ฅผ ํธ์ถํ๋ค.
- mmap์ ์ฑ๊ณตํ๋ฉด, ๊ฐ์ ๊ธฐ๋กํ์ฌ ๋ค๋ฅธ ํ๋ก์ธ์ค์์ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ค.
- consumer
- ํ์ผ ์์ฑ์ด ํ์ ์๊ณ , open์ ํตํด ์ ๊ทผํ๋ฉด ๋๋ค.
- mmap์ ์ฑ๊ณตํ๋ฉด, ๊ฐ์ ์ฝ์ด ์จ๋ค.
- mmap์ ํตํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๋ ๊ฒฝ์ฐ, munmap์ ํตํด ํ ๋น ํด์ ํด์ฃผ์ด์ผ ํ๋ค.
SysV SHM
๋ ์ด์์ ํ๋ก์ธ์ค๊ฐ ํน์ ํ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๊ณต์ ํ๋ ๊ฒ์ ๋งํ๋ค. ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋์์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ์ด ๋ณด์ฅ๋์ง ์์ ์ ์์ผ๋ฏ๋ก ๋๊ธฐํ๊ฐ ํ์ํ๋ค.
(์๋์ ์ฝ๋๋ค์ ๋ณ๋์ ๋๊ธฐํ ๊ณผ์ ์ด ํ์ ์๋ ์ฝ๋์ด๋ค.)
#define SHMKEY "test"
static int prosumer()
{
int fd;
key_t key;
int *maped;
int i;
key = ftok(SHMKEY, SHMKEY_PROJID);
if (key == -1) {
perror("ftok()");
return -1;
}
shm_id = shmget(key, 4096, IPC_CREAT | 0644);
if (shm_id == -1)
{
perror("shmget()");
return -1;
}
maped = shmat(shm_id, NULL, 0);
if (maped == (void *)-1) {
perror("shmat()");
return -1;
}
for (i = 0; i < 100; i++) {
maped[i] = i + 1;
}
shmdt(maped);
return 0;
}
#define SHMKEY "test"
static int prosumer()
{
int fd;
key_t key;
int *maped;
int i;
key = ftok(SHMKEY, SHMKEY_PROJID);
if (key == -1) {
perror("ftok()");
return -1;
}
shm_id = shmget(key, 4096, IPC_CREAT | 0644);
if (shm_id == -1)
{
perror("shmget()");
return -1;
}
maped = shmat(shm_id, NULL, 0);
if (maped == (void *)-1) {
perror("shmat()");
return -1;
}
for (i = 0; i < 100; i++) {
maped[i] = i + 1;
}
shmdt(maped);
return 0;
}
์์ ๊ฐ์ด ํค๋ฅผ ํตํด, ๋์ผํ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ ๊ทผํ์ฌ ํน์ ํ๋ก์ธ์ค์ ์ ๋ณด๋ฅผ ์ฐ๊ฑฐ๋, ์ฝ์ ์ ์๋ค.
- File mapping๊ณผ ๋ฌ๋ฆฌ ํค๋ฅผ ์์ฑํ๊ณ ํค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก SHM์ attach ํ๋ค.
- ์ฌ์ฉ์ด ๋๋๋ฉด SHM์ detatch ํ๋ค.
POSIX SHM
POSIX SHM์ ๊ฒฝ์ฐ, File mapping๊ณผ ์ฝ๋๊ฐ ์ ์ฌํ๋ค.
- Prosumer์ ๊ฒฝ์ฐ, `fd = shm_open("/test", O_RDWR | O_CREATE, 0644)`๋ก ๋ณ๊ฒฝํ๋ฉด ๋๋ค.
- Consumer์ ๊ฒฝ์ฐ, `fd = shm_open("/test", O_RDWR)`๋ก ๋ณ๊ฒฝํ๋ฉด ๋๋ค.
- ์์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ฉด, SHM์ด ์์ฑ๋๋ ์์น๋ `/dev/shm/test`๊ฐ ๋๋ค.
'๐โโ๏ธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด > C' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
C: ํ์ผ ๋ค๋ฃจ๊ธฐ (0) | 2021.06.12 |
---|---|
C: Signal (0) | 2021.06.11 |
C: thread safe and reentrant (0) | 2021.01.26 |
C: Memory Layout of C Programs (0) | 2021.01.26 |
C: Storage class specifier (0) | 2020.11.27 |