Skip to content

Instantly share code, notes, and snippets.

@loggerhead
Created April 14, 2017 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loggerhead/0b4e199973a80ce8c199ac4da5474690 to your computer and use it in GitHub Desktop.
Save loggerhead/0b4e199973a80ce8c199ac4da5474690 to your computer and use it in GitHub Desktop.
Practices of IPC
#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