读写这两个进程需要共享的内存,在头文件中定义,
#define DZY_FRAME_SIZE 300000
#define DZY_FRAME_COUNT 10
typedef struct single_frame
{
int length;
char frame[DZY_FRAME_SIZE];
}single_frame;
typedef struct mul_frame
{
int count;
int readIdx;
int writeIdx;
single_frame frame[DZY_FRAME_COUNT];
}mul_frame;
其中single_frame,存放单个视频帧,mul_frame存放多帧的队列,其中count用来记录帧的数量,readIdx和writeIdx用来记录读帧和写帧的游标,通过结构体实现内存共享,便于操作。
写入进程的共享内存初始化代码
#include
#include
int shmid;
mul_frame *shared;//指向shm
sem_t* sem;
void *shm = NULL;//分配的共享内存的原始首地址
shmid = shmget((key_t)1234, sizeof(mul_frame), 0666|IPC_CREAT);
shm = shmat(shmid, 0, 0);
if(shm == (void*)-1)
{
fprintf(stderr, "shmat failed\n");
}
printf("\nMemory attached at %X\n", (int)shm);
shared = (mul_frame*)shm;
shared->readIdx = 0;
shared->writeIdx = 0;
shared->count = 0;
for(int i =0;iframe[i].length=0;
}
sem = sem_open("mysem", O_CREAT | O_RDWR , 0666, 1);
if (sem == SEM_FAILED)
{
printf("errno open sem\n");
}
其中共享内存的keyid为1234,用于不同进程间设置同一的keyid,共享内存的大小为sizeof(mul_frame),可以自定义,这在linux上优于命名管道(fifo),因为命名管道
只能缓冲65536bytes,但是命名管道自带同步机制,而共享内存没有,所以需要定义信
号量sem_t* sem,其中mysem为信号量的keyid,同样用于不同进程间共享。
下面是写入进程的共享内存析构代码
//把共享内存从当前进程中分离
if(shmdt((void*)shared) == -1)
{
fprintf(stderr, "shmdt failed\n");
}
//删除共享内存
if(shmctl(shmid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "shmctl(IPC_RMID) failed\n");
}
sem_destroy(sem);
读取共享内存的初始化的代码
int shmid;
mul_frame *shared;//指向shm
void *shm = NULL;//分配的共享内存的原始首地址
shmid = shmget((key_t)1234, sizeof(mul_frame), 0666|IPC_CREAT);
if(shmid == -1)
{
fprintf(stderr, "shmget failed\n");
}
//将共享内存连接到当前进程的地址空间
shm = shmat(shmid, 0, 0);
if(shm == (void*)-1)
{
fprintf(stderr, "shmat failed\n");
}
printf("\nMemory attached at %X\n", (int)shm);
shared = (mul_frame*)shm;
sem_t* sem;
sem = sem_open("mysem", O_CREAT | O_RDWR , 0666, 0);
if (sem == SEM_FAILED)
{
printf("errno open sem\n");
}
读取共享内存的代码与写共享内存的代码基本一致,其中sem_open不同,写入的代码中最后一个参数是1,而读取的代码中,最后一个参数是0。
读取共享内存的析构代码,暂略。
下面是写入共享内存的代码
//sem_wait(sem);
//printf("shared->count:%d\n",shared->count);
if(shared->count < DZY_FRAME_COUNT)
{
shared->frame[shared->readIdx].length = _rxH264Frame->GetFrameSize() - bytesUsed;
memcpy(shared->frame[shared->readIdx].frame,_rxH264Frame->GetFramePtr() + bytesUsed,shared->frame[shared->readIdx].length);
shared->readIdx = (shared->readIdx+1)%DZY_FRAME_COUNT;
shared->count++;
}else
{
printf("error, shared->count:%d\n",shared->count);
}
sem_post(sem);
下面是读取共享内存的代码
sem_wait(sem);
//printf("shared->count:%d\n",shared->count);
if(shared->count > 0)
{
*len = shared->frame[shared->writeIdx].length;
memcpy(buf,shared->frame[shared->writeIdx].frame,*len);
shared->writeIdx = (shared->writeIdx+1)%DZY_FRAME_COUNT;
shared->count--;
}else
{
printf("error, shared->count:%d\n",shared->count);
}
//sem_post(sem);
由于写入共享内存时,是通过网络接收,而读取共享内存是直接保存文件,网络接收的速度明显慢于保存文件,所以只需要在读取的时候加sem_wait,用来等待写入。
另外,通过%DZY_FRAME_COUNT,来实现环形缓冲区的效果。