2. 示例代码
新建semaphore.h文件
#ifndef __SEM_H__
#define __SEM_H__
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/types.h>
#define PATHNAME "./"
#define PROJ_ID 0x666
union semun
{
int val; //单个信号的值
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int create_sem_set(int nsem);
int get_sem_set(int nsem);
int init_sem_set(int sem_set_id, int which_sem);
int sem_p(int sem_set_id, int which_sem);
int sem_v(int sem_set_id, int which_sem);
int destroy_sem_set(int sem_set_id);
#endif
新建semaphore.c文件
#include "semaphore.h"
static int sem_set(int nsem, int semflag)
{
key_t key = ftok(PATHNAME, PROJ_ID);
if (key < 0)
{
perror("ftok failure");
exit(-1);
}
int sem_set_id = semget(key, nsem, semflag);
if (sem_set_id < 0)
{
perror("semget failure");
exit(-1);
}
return sem_set_id;
}
int create_sem_set(int nsem)
{
if (nsem <= 0)
{
perror("nsem <= 0");
exit(-1);
}
return sem_set(nsem, IPC_CREAT | IPC_EXCL | 0666);
}
int get_sem_set(int nsem)
{
if (nsem <= 0)
{
perror("nsem <= 0");
exit(-1);
}
return sem_set(nsem, IPC_CREAT);
}
int init_sem_set(int sem_set_id, int which_sem)
{
union semun my_semun;
my_semun.val = 1;//semun中val的值去设置信号集(sem_set)中单个sem的值
int ret = semctl(sem_set_id, which_sem, SETVAL, my_semun);
if (ret == -1)
{
perror("semctl error");
exit(-1);
}
return 0;
}
static int sem_operatons(int sem_set_id, int which_sem, int op)
{
struct sembuf sb;
//sembuf is as follows:
//unsigned short sem_num
//short sem_op
//short sem_flg
sb.sem_num = which_sem;
sb.sem_op = op;
sb.sem_flg = SEM_UNDO;
return semop(sem_set_id, &sb, 1);
}
int sem_p(int sem_set_id, int which_sem)
{
return sem_operatons(sem_set_id, which_sem, -1);
}
int sem_v(int sem_set_id, int which_sem)
{
return sem_operatons(sem_set_id, which_sem, +1);
}
int destroy_sem_set(int sem_set_id)
{
int ret = semctl(sem_set_id, 0, IPC_RMID, NULL);
if (ret == -1)
{
perror("semctl failure");
exit(-1);
}
return ret;
}
新建shm.h文件
#ifndef __SHM__
#define __SHM__
#include<stdlib.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#define PATHNAME "./"
#define PROJ_ID 0x666
int create_shm(int sz);
int get_shm(int sz);
void* malloc_addr(int shm_id);
int free_addr(const void* addr);
int destroy_shm(int shm_id);
#endif
新建shm.c文件
#include"shm.h"
static int shm(int sz, int flag)
{
key_t key = ftok(PATHNAME, PROJ_ID);
if (key == -1)
{
perror("ftok failure");
exit(-1);
}
int shm_id = shmget(key, sz, flag);
if (shm_id < 0)
{
perror("shmget failure");
exit(-1);
}
return shm_id;
}
int create_shm(int sz)
{
return shm(sz, IPC_CREAT | IPC_EXCL | 0666);
}
int get_shm(int sz)
{
return shm(sz, IPC_CREAT);
}
void* malloc_addr(int shm_id)
{
return shmat(shm_id, NULL, 0);
}
int free_addr(const void* addr)
{
return shmdt(addr);
}
int destroy_shm(int shm_id)
{
return shmctl(shm_id, IPC_RMID, NULL);
}
新建test.c文件
#include"shm.h"
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>
#include"semaphore.h"
typedef struct cPicInfo{
int size;
char state;
}cPicInfo;
typedef struct cPicBuf{
char *picbuf;
int *picbuf_size;
char *picbuf_state; //0 :not use 1: will using 2: is using
}cPicBuf;
#define SHM_SIZE (4096 + sizeof(cPicInfo))
#define PICBUF_NUM (10)
cPicBuf* getfreebuf_frome_mem(char *sharebuf, int perpic_size)
{
int i;
cPicBuf picbuf[PICBUF_NUM];
char *psharebuf = sharebuf + 1;
for( i = 0; i <PICBUF_NUM; i++){
picbuf[i].picbuf = psharebuf + i * SHM_SIZE;
picbuf[i].picbuf_size = (int *)(picbuf[i].picbuf + ( SHM_SIZE - sizeof(cPicInfo)));
picbuf[i].picbuf_state = (char *)(picbuf[i].picbuf_size) + sizeof(int);
if(*picbuf[i].picbuf_state == 0){
*picbuf[i].picbuf_state = 2;
break;
}
}
printf("get free i:%d\n",i);
return i < PICBUF_NUM ? &picbuf[i] : NULL;
}
cPicBuf* getcolbuf_frome_mem(char *sharebuf, int perpic_size)
{
int i;
cPicBuf picbuf[PICBUF_NUM];
char *psharebuf = sharebuf + 1;
for( i = 0; i <PICBUF_NUM; i++){
picbuf[i].picbuf = psharebuf + i * SHM_SIZE;
picbuf[i].picbuf_size = (int *)(picbuf[i].picbuf + ( SHM_SIZE - sizeof(cPicInfo)));
picbuf[i].picbuf_state = (char *)(picbuf[i].picbuf_size) + sizeof(int);
if(*picbuf[i].picbuf_state == 2){
*picbuf[i].picbuf_state = 3;
break;
}
}
printf("get col i:%d\n",i);
return i < PICBUF_NUM ? &picbuf[i] : NULL;
}
int main()
{
int ret;
//创建信号量并初始化
int sem_set_id = create_sem_set(2);
init_sem_set(sem_set_id, 0);
init_sem_set(sem_set_id, 1);
//创建共享内存
int shm_id = create_shm(SHM_SIZE * PICBUF_NUM + 1);
//创建子进程
pid_t pid = fork();
if (pid < 0)
{
perror("fork failure");
exit(-1);
}
else if (pid == 0) //子进程
{
char* buf = (char*)malloc_addr(shm_id);
int count = 0;
cPicBuf* freebuf;
buf[0] = 1;
while(1)
{
//if(buf[0] == 1){ int ret = semctl(sem_set_id, which_sem, SETVAL, my_semun);
if( 1 == (ret =semctl(sem_set_id, 1, GETVAL, NULL))){
printf("zi ret: %d\n", ret);
; count++;
sem_p(sem_set_id, 0);
freebuf = getfreebuf_frome_mem(buf, SHM_SIZE);
if(freebuf != NULL)
*freebuf->picbuf_size = count;
buf[0] = 2;
sem_v(sem_set_id, 0);
sem_p(sem_set_id, 1);
}
if(count == 10)
break;
}
free_addr(buf);
}
else //父进程
{
char* buf = (char*)malloc_addr(shm_id);
//usleep(500000);//让子进程先P操作
cPicBuf* colbuf;
int count1 = 0;
while(1)
{
//if(buf[0] == 2){
if( 0 == (ret = semctl(sem_set_id, 1, GETVAL, NULL))){
printf("fu ret: %d\n", ret);
count1++;
sem_p(sem_set_id, 0);
colbuf = getcolbuf_frome_mem(buf, SHM_SIZE);
if(colbuf != NULL)
{
printf("picbuf_size :%d \n",*colbuf->picbuf_size);
}
buf[0] = 1;
sem_v(sem_set_id, 0);
sem_v(sem_set_id, 1);
}
if(count1 == 10)
break;
}
free_addr(buf);
destroy_shm(shm_id);
destroy_sem_set(sem_set_id);
}
return 0;
}
新建Makefile文件
test:test.c semaphore.c shm.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f test