Created
April 14, 2017 08:23
-
-
Save loggerhead/0b4e199973a80ce8c199ac4da5474690 to your computer and use it in GitHub Desktop.
Practices of IPC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <sys/un.h> | |
#include <sys/msg.h> | |
#include <sys/shm.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#define HELLO "How are you?" | |
// path must exists | |
#define KEY_PATH "/tmp/" | |
#define KEY_ID 1 | |
void wait_a_second() { | |
usleep(1000); | |
} | |
// generate IPC key | |
key_t get_key() { | |
return ftok(KEY_PATH, KEY_ID); | |
} | |
void write_fd(int fd) { | |
write(fd, HELLO, sizeof(HELLO)); | |
close(fd); | |
} | |
void read_fd(int fd) { | |
char buf[1024]; | |
read(fd, buf, sizeof(buf)); | |
printf("%s\n", buf); | |
close(fd); | |
} | |
void pipe_demo() { | |
// read, write | |
int fds[2]; | |
if (pipe(fds) == -1) { | |
return; | |
} | |
pid_t pid = fork(); | |
if (pid < 0) { | |
return; | |
} | |
// child -> father | |
if (pid == 0) { | |
printf("child wakeup\n"); | |
// close read end | |
close(fds[0]); | |
write_fd(fds[1]); | |
// father | |
} else { | |
printf("father wakeup\n"); | |
// close write end | |
close(fds[1]); | |
read_fd(fds[0]); | |
} | |
} | |
void popen_demo() { | |
FILE *fp = popen("echo hi", "r"); | |
char buf[1024]; | |
fread(buf, 1, sizeof(buf), fp); | |
fclose(fp); | |
printf("%s\n", buf); | |
} | |
void fifo_demo() { | |
const char *path = KEY_PATH "fifo_demo"; | |
mkfifo(path, 0600); | |
pid_t pid = fork(); | |
if (pid < 0) { | |
return; | |
} | |
if (pid == 0) { | |
int fd = open(path, O_WRONLY); | |
write_fd(fd); | |
} else { | |
int fd = open(path, O_RDONLY); | |
read_fd(fd); | |
} | |
} | |
void msgqueue_demo() { | |
struct MyMsg { | |
long mtype; | |
char mtext[32]; | |
}; | |
// similar to file permissions | |
const int flag = 0600; | |
int msg_queue_id = msgget(get_key(), flag | IPC_CREAT | IPC_EXCL); | |
// setting msg_queue | |
struct msqid_ds msqid_ds; | |
msgctl(msg_queue_id, IPC_STAT, &msqid_ds); | |
msqid_ds.msg_qbytes = 1024; | |
msgctl(msg_queue_id, IPC_SET, &msqid_ds); | |
pid_t pid = fork(); | |
if (pid < 0) { | |
return; | |
} | |
if (pid == 0) { | |
struct MyMsg msg = { | |
.mtype = 1, | |
.mtext = HELLO, | |
}; | |
int msg_queue_id = msgget(get_key(), flag); | |
msgsnd(msg_queue_id, &msg, sizeof(msg.mtext), 0); | |
} else { | |
struct MyMsg msg; | |
int msg_queue_id = msgget(get_key(), flag); | |
msgrcv(msg_queue_id, &msg, sizeof(msg.mtext), 0, 0); | |
printf("%s\n", msg.mtext); | |
} | |
} | |
void share_memory_demo() { | |
// similar to file permissions | |
const int flag = 0600; | |
const int size = 16 * 1024; | |
int shmid = shmget(get_key(), size, flag | IPC_CREAT | IPC_EXCL); | |
// setting share memory | |
struct shmid_ds shmid_ds; | |
shmctl(shmid, IPC_STAT, &shmid_ds); | |
shmid_ds.shm_perm.mode = 0644; | |
shmctl(shmid, IPC_SET, &shmid_ds); | |
pid_t pid = fork(); | |
if (pid < 0) { | |
return; | |
} | |
if (pid == 0) { | |
int shmid = shmget(get_key(), 0, flag); | |
// read & write | |
void *shmptr = shmat(shmid, 0, 0); | |
strncpy(shmptr, HELLO, size); | |
shmdt(shmptr); | |
} else { | |
int shmid = shmget(get_key(), 0, flag); | |
// read only | |
void *shmptr = shmat(shmid, 0, SHM_RDONLY); | |
// wait_a_second child write to shared memory | |
wait_a_second(); | |
char buf[1024]; | |
strncpy(buf, shmptr, sizeof(buf)); | |
printf("%s\n", (char *) shmptr); | |
shmdt(shmptr); | |
} | |
// reduce reference count | |
shmctl(shmid, IPC_RMID, NULL); | |
} | |
// spec http://beej.us/guide/bgipc/output/html/multipage/mmap.html | |
void mmap_demo() { | |
const size_t memlen = 16 * 1024; | |
char *mem = mmap(NULL, memlen, PROT_WRITE | PROT_READ, MAP_ANON | MAP_SHARED, 0, 0); | |
pid_t pid = fork(); | |
if (pid < 0) { | |
return; | |
} | |
if (pid == 0) { | |
strncpy(mem, HELLO, sizeof(HELLO)); | |
} else { | |
wait_a_second(); | |
char buf[1024]; | |
strncpy(buf, mem, sizeof(HELLO)); | |
printf("%s\n", buf); | |
} | |
munmap(mem, memlen); | |
} | |
void unix_domain_socket_demo() { | |
struct sockaddr_un un = { | |
.sun_family = AF_UNIX, | |
.sun_path = KEY_PATH "unix_domain_socket_demo.socket", | |
}; | |
socklen_t addrlen = sizeof(un); | |
pid_t pid = fork(); | |
if (pid < 0) { | |
return; | |
} | |
if (pid == 0) { | |
int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
wait_a_second(); | |
connect(fd, (struct sockaddr *) &un, addrlen); | |
write_fd(fd); | |
close(fd); | |
} else { | |
int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
bind(fd, (struct sockaddr *) &un, addrlen); | |
listen(fd, 5); | |
int child_fd = accept(fd, NULL, NULL); | |
read_fd(child_fd); | |
close(child_fd); | |
close(fd); | |
} | |
} | |
// TODO: 信号量 | |
int main(int argc, char *argv[]) | |
{ | |
/* pipe_demo(); */ | |
/* popen_demo(); */ | |
/* fifo_demo(); */ | |
// they are similar | |
/* msgqueue_demo(); */ | |
/* share_memory_demo(); */ | |
/* mmap_demo(); */ | |
/* unix_domain_socket_demo(); */ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment