ipc.h
#include <sys/types.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifndef _IPC_H_ #define _IPC_H_ union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *_buf; }; int sem_create(key_t key); int sem_open(key_t key); int sem_p(int semid); int sem_v(int semid); int sem_d(int semid); int sem_setval(int semid, int val); int sem_getval(int semid); int sem_getmode(int semid); int sem_setmode(int semid, char* mode); #endif //_IPC_H_
ipc.c
#include "ipc.h" int sem_create(key_t key) { int semid = semget(key,1,0666 | IPC_CREAT | IPC_EXCL); if (-1 == semid) { printf("sem create faild "); exit(1); } return semid; } int sem_open(key_t key) { int semid = semget(key,0,0); if (-1 == semid) { printf("sem open faild "); exit(1); } return semid; } int sem_p(int semid) { struct sembuf sb = {0,-1,0}; int ret = semop(semid,&sb,1); if(-1 == ret) { printf("sem p faild "); exit(1); } return ret; } int sem_v(int semid) { struct sembuf sb = {0,1,0}; int ret = semop(semid,&sb,1); if(-1 == ret) { printf("sem v faild "); exit(1); } return ret; } int sem_d(int semid) { int ret = semctl(semid, 0, IPC_RMID, 0); return ret; } int sem_setval(int semid, int val) { union semun su; su.val = val; int ret = semctl(semid, 0, SETVAL,su); if (-1 == ret) { printf("sem setval faild "); exit(1); } return ret; } int sem_getval(int semid) { int ret = semctl(semid, 0, GETVAL,0); if (-1 == ret) { printf("sem getval faild "); exit(1); } return ret; } int sem_getmode(int semid) { union semun su; struct semid_ds sem; su.buf = &sem; int ret = semctl(semid , 0 , IPC_STAT, su); if (-1 == ret) { printf("sem getmode failed "); exit(1); } printf("current permissions is %o ",su.buf->sem_perm.mode); return ret; } int sem_setmode(int semid, char* mode) { union semun su; struct semid_ds sem; su.buf = &sem; int ret = semctl(semid , 0 , IPC_STAT, su); if (-1 == ret) { printf("sem getmode failed "); exit(1); } printf("current permissions is %o ",su.buf->sem_perm.mode); sscanf(mode ,"%o",(unsigned int*)&su.buf->sem_perm.mode); ret = semctl(semid , 0 , IPC_STAT, su); if (-1 == ret) { printf("sem getmode failed "); exit(1); } printf("permissios update... "); return ret; }
shmfifo.h
#include "ipc.h" #ifndef _SHM_FIFO_H_ #define _SHM_FIFO_H_ typedef struct shmfifo shmfifo_t; typedef struct shmhead shmhead_t; typedef struct stu { char name[32]; int age; }STU; struct shmhead { unsigned int blksize; // 块大小 unsigned int blocks; // 总块数 unsigned int rd_index; // 读索引 unsigned int wr_index; // 写索引 }; struct shmfifo { shmhead_t *p_shm; // 共享内存头部指针 char *p_payload; // 有效负载的起始地址 int shmid; // 共享内存ID int sem_mutex; // 用来互斥用的信号量 int sem_full; // 用来控制共享内存是否满的信号量 int sem_empty; // 用来控制共享内存是否空的信号量 }; shmfifo_t* shmfifo_init(int key, int blksize, int blocks);//初始化 void shmfifo_put(shmfifo_t *fifo, const void *buf);//添加数据到环形缓冲区 void shmfifo_get(shmfifo_t *fifo, void *buf);//从缓冲区中取数据 void shmfifo_destroy(shmfifo_t *fifo);//释放共享内存的环形缓冲区 #endif /* _SHM_FIFO_H_ */
shmfifo.c
#include "shmfifo.h" #include <assert.h> shmfifo_t* shmfifo_init(int key, int blksize, int blocks) { //分配内存空间 shmfifo_t *fifo = (shmfifo_t *)malloc(sizeof(shmfifo_t)); assert(fifo != NULL); memset(fifo, 0, sizeof(shmfifo_t)); int shmid; shmid = shmget(key, 0, 0); int size = sizeof(shmhead_t) + blksize*blocks; if (shmid == -1) {//创建共享内存 fifo->shmid = shmget(key, size, IPC_CREAT | 0666); if (fifo->shmid == -1) exit(1); fifo->p_shm = (shmhead_t*)shmat(fifo->shmid, NULL, 0); if (fifo->p_shm == (shmhead_t*)-1) exit(1); fifo->p_payload = (char*)(fifo->p_shm + 1); //进行字段初始化 fifo->p_shm->blksize = blksize; fifo->p_shm->blocks = blocks; fifo->p_shm->rd_index = 0; fifo->p_shm->wr_index = 0; fifo->sem_mutex = sem_create(key); fifo->sem_full = sem_create(key+1); fifo->sem_empty = sem_create(key+2); sem_setval(fifo->sem_mutex, 1); sem_setval(fifo->sem_full, blocks); sem_setval(fifo->sem_empty, 0); } else {//打开共享内存 fifo->shmid = shmid; fifo->p_shm = (shmhead_t*)shmat(fifo->shmid, NULL, 0); if (fifo->p_shm == (shmhead_t*)-1) exit(1); fifo->p_payload = (char*)(fifo->p_shm + 1); fifo->sem_mutex = sem_open(key); fifo->sem_full = sem_open(key+1); fifo->sem_empty = sem_open(key+2); } return fifo; } void shmfifo_put(shmfifo_t *fifo, const void *buf) { sem_p(fifo->sem_full); sem_p(fifo->sem_mutex); //生产产品 memcpy(fifo->p_payload+fifo->p_shm->blksize*fifo->p_shm->wr_index, buf, fifo->p_shm->blksize); fifo->p_shm->wr_index = (fifo->p_shm->wr_index + 1) % fifo->p_shm->blocks; sem_v(fifo->sem_mutex); sem_v(fifo->sem_empty); } void shmfifo_get(shmfifo_t *fifo, void *buf) { sem_p(fifo->sem_empty); sem_p(fifo->sem_mutex); memcpy(buf, fifo->p_payload+fifo->p_shm->blksize*fifo->p_shm->rd_index, fifo->p_shm->blksize); fifo->p_shm->rd_index = (fifo->p_shm->rd_index + 1) % fifo->p_shm->blocks; sem_v(fifo->sem_mutex); sem_v(fifo->sem_full); } void shmfifo_destroy(shmfifo_t *fifo) { //删除创建的信息量集 sem_d(fifo->sem_mutex); sem_d(fifo->sem_full); sem_d(fifo->sem_empty); //删除共享内存 shmdt(fifo->p_shm);//删除共享内存头部 shmctl(fifo->shmid, IPC_RMID, 0);//删除整个共享内存 //释放fifo的内存 free(fifo); }
shmfifo_send.c
#include "shmfifo.h" /* typedef struct stu { char name[32]; int age; }STU; */ int main(void) { shmfifo_t *fifo = shmfifo_init(1234,sizeof(STU),3); STU s; memset(&s, 0, sizeof(STU)); s.name[0] = 'A'; int i; for(i=0;i<10;i++) { s.age = 10 + i; shmfifo_put(fifo,&s); s.name[0] = s.name[0] + 1; printf("send ok "); } return 0; }
shmfifo_recv.c
#include "shmfifo.h" /* typedef struct stu { char name[32]; int age; }STU; */ int main(void) { shmfifo_t *fifo = shmfifo_init(1234,sizeof(STU),3); STU s; memset(&s, 0, sizeof(STU)); int i; for(i=0;i<10;i++) { shmfifo_get(fifo,&s); printf("name = %s, age = %d ",s.name,s.age); } return 0; }
shmfifo_free.c
#include "shmfifo.h" int main(void) { shmfifo_t *fifo = shmfifo_init(1234,sizeof(STU),3); shmfifo_destroy(fifo); return 0; }
Makefile
.PHONY:clean all CC=gcc CFLAGS=-Wall -g BIN= shmfifo_send shmfifo_recv shmfifo_free OBJS1=shmfifo_send.o shmfifo.o ipc.o OBJS2=shmfifo_recv.o shmfifo.o ipc.o OBJS3=shmfifo_free.o shmfifo.o ipc.o all:$(BIN) %.o:%.c $(CC) $(CFLAGS) -c $< -o $@ shmfifo_send:$(OBJS1) $(CC) $(CFLAGS) $^ -o $@ shmfifo_recv:$(OBJS2) $(CC) $(CFLAGS) $^ -o $@ shmfifo_free:$(OBJS3) $(CC) $(CFLAGS) $^ -o $@ clean: rm -f *.o $(BIN)