【基础知识】进程通信之共享内存+信号量

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
上一篇:Hi3559AV100平台PCIE硬盘STAT驱动调试


下一篇:PYTHON2.day07