本来打算使用pipe进行父子进程之间的数据交互(应用场景是父进程向多个子进程分发数据,子进程进行处理);但是担心pipe的性能,转而使用mmap实现。
废话少叙,上代码。
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#define SHMFILE "shm.data"
typedef struct cell_t {
int state;
#define CELL_READY 1
#define CELL_CLEAR 0
int size;
char data[64];
} cell_t;
int main(void) {
signal( SIGCHLD, SIG_IGN );
int i, ret = 0;
int fd = open(SHMFILE, O_CREAT | O_RDWR | O_TRUNC, 0600);
if ( fd < 0 ) {
fprintf(stderr, "fail to open %s -- %s\n", SHMFILE, strerror(errno));
return 2;
}
int n_cells = 8;
int shm_size = sizeof(cell_t) * n_cells;
off_t off = lseek(fd, shm_size, SEEK_END);
if ( off != (off_t)shm_size ) {
fprintf(stderr, "fail to seek %s (got:%ld want:%d) -- %s\n", SHMFILE, off, shm_size, strerror(errno));
return 3;
}
ret = write(fd, "", 1);
if ( ret < 0 ) {
fprintf(stderr, "fail to write %s -- %s\n", SHMFILE, strerror(errno));
return 5;
}
cell_t* cell = (cell_t *) mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if ( cell == NULL ) {
fprintf(stderr, "fail to mmap %s -- %s\n", SHMFILE, strerror(errno));
return 7;
}
for (i=0; i<n_cells; i++) {
memset( cell + i, 0, sizeof(cell_t) );
}
int id = 3;
int pid = fork();
if (pid < 0) {
fprintf(stderr, "fail to fork child -- %s\n", strerror(errno));
return 1;
}
else if (pid == 0) {
// child process
pid = getpid();
fprintf(stdout, "\tC#%d I am here ...\n", pid);
cell_t* c = &cell[id];
for ( i=0; i<5; i++ ) {
if ( c->state == CELL_READY ) {
fprintf(stdout, "\tC#%d size=%d data='%s'\n", pid, c->size, c->data);
c->state = CELL_CLEAR;
break;
}
sleep(1);
}
fprintf(stdout, "\tC#%d byebye\n", pid);
munmap(cell, shm_size);
close(fd);
exit(0);
}
pid = getpid();
fprintf(stdout, "P#%d I am here ...\n", pid);
sleep(1);
{
cell_t* c = &cell[id];
char* data = "Hello,World.";
c->size = strlen(data);
memmove( c->data, data, c->size );
c->state = CELL_READY;
fprintf(stdout, "P#%d cell->state=%d\n", pid, c->state);
sleep(5);
fprintf(stdout, "P#%d cell->state=%d\n", pid, c->state);
}
fprintf(stdout, "P#%d byebye\n", pid);
munmap(cell, shm_size);
close(fd);
return 0;
}