c++ semaphore信号量的使用

c++ semaphore信号量的使用,第1张

目前网上可以查找到很多关于信号量的实现文章,但是讲解在linux下使用semaphore的文章比较少;

c++ linux semaphore信号量的使用

sem_init函数是Posix信号量操作中的函数。sem_init() 初始化一个定位在 sem 的匿名信号量。value 参数指定信号量的初始值。 pshared 参数指明信号量是由进程内线程共享,还是由进程之间共享。如果 pshared 的值为 0,那么信号量将被进程内的线程共享,并且应该放置在这个进程的所有线程都可见的地址上(如全局变量,或者堆上动态分配的变量)。

如果 pshared 是非零值,那么信号量将在进程之间共享,并且应该定位共享内存区域(见 shm_open(3)、mmap(2) 和 shmget(2))。因为通过 fork(2) 创建的孩子继承其父亲的内存映射,因此它也可以见到这个信号量。所有可以访问共享内存区域的进程都可以用 sem_post(3)、sem_wait(3) 等等操作信号量。初始化一个已经初始的信号量其结果未定义。

返回值 :

sem_init() 成功时返回 0;错误时,返回 -1,并把 errno 设置为合适的值。

例子:

一、简介

共享内存为在多个进程之间共享和传递数据提供了一种有效的方式。

但它本身并未提供同步机制。

在实际编程中,可以使用

信号量,

传递消息(使用管道或IPC消息),

生成信号,

条件变量,

等方法来提供读写之间的有效的同步机制。

本例程序使用信号量进行同步,

主要是因为它方便,使用广泛,且独立于进程。

本例程序实现了,

生产者进程:

每次读取YUV输入文件的一帧,

然后将其写到共享内存中。

消费者进程:

每次从共享内存中读到一帧,

处理后,

将其写到输出文件。

两个进程间使用信号量来保证同步处理每一帧。

本例程序很好地示范了共享内存和信号量的机制,

对于实际程序的开发很有意义。

二、生产者进程

common.h

用来设置一些测试用的基本参数。

/*

* \File

* common.h

*/

#ifndef __COMMON_H__

#define __COMMON_H__

#define TEST_FILE "coastguard_cif.yuv"

#define OUTPUT_FILE "coastguard_cif_trsd.yuv"

#define FYUV_WIDTH 352

#define FYUV_HEIGHT 288

#endif

共享内存相关的头文件。

shm_com.h

/*

* \File

* shm_com.h

* \Brief

*/

#ifndef __SHM_COM_H__

#define __SHM_COM_H__

#define SHM_SEED 1001

#define MAX_SHM_SIZE 2048*2048*3

typedef struct shared_use_st

{

int end_flag //用来标记进程间的内存共享是否结束: 0, 未结束; 1, 结束

char shm_sp[MAX_SHM_SIZE]//共享内存的空间

}shared_use_st

#endif

信号量的头文件

semaphore.h

/*

* \File

* semaphore.h

* \Brief

* semaphore operation

*/

#ifndef __SEMAPHORE_H__

#define __SEMAPHORE_H__

#define SEM_SEED 1000

union semun

{

int val

struct semid_ds *buf

unsigned short *array

}

int set_semvalue(int sem_id, int value)

void del_semvalue(int sem_id)

int semaphore_p(int sem_id)

int semaphore_v(int sem_id)

#endif

帧处理的头文件

frame.h

/*

* \File

* frame.h

* \Brief

*

*/

#ifndef __FRAME_H__

#define __FRAME_H__

#include "shm_com.h"

#define PIX_VALUE 1

typedef enum

{

YUV420,

YUV422,

YUV444,

RGB

}frame_type_e

typedef struct

{

int frm_w// width

int frm_h// height

frame_type_e frm_type

int frm_size

char *frm_comps

}frame_t, *frame_p

int init_frame(frame_p frame, int width, int height, frame_type_e type)

int free_frame(frame_p frame)

int read_frame_from_file(frame_p frame, FILE* fp)

int write_frame_into_file(FILE* fp, frame_p frame)

int read_frame_from_shm(frame_p frame, shared_use_st* shm)

int write_frame_into_shm(shared_use_st* shm, frame_p frame)

int crop_frame(frame_p frame, int l_offset, int t_offset, int c_w, int c_h)

#endif

生产者进程的基本流程:

打开输入文件并初始化帧

创建并初始化共享内存和信号量

然后每次读取一帧,

用信号量获取共享内存的权限后,

将读取的帧写入共享内存,

再释放共享内存的权限。

当处理完所有的帧后,

设置结束标志,

并释放相关的资源。

producer.c

/*

* \File

* producer.c

* \Brief

* Test shared-memory and message-queue

*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <unistd.h>

#include <sys/shm.h>

#include <sys/sem.h>

#include "common.h"

#include "semaphore.h"

#include "shm_com.h"

#include "frame.h"

int main(char argc, char* argv[])

{

FILE* fp_in = NULL

frame_t frame

int frame_cnt = 0

int sem_id// semaphore id

int shm_id// shared-memory id

void* shared_memory = (void*)0

shared_use_st* shared_stuff

/* Open input file */

if ((fp_in = fopen(TEST_FILE, "rb")) <0 )

{

printf("Open input file failed: %s\n", TEST_FILE)

exit(EXIT_FAILURE)

}

/* Init frame */

init_frame(&frame, FYUV_WIDTH, FYUV_HEIGHT, YUV420)

printf("FRAME: w = %d, h = %d\n", frame.frm_w, frame.frm_h)

/* Create and init semaphore */

sem_id = semget((key_t)SEM_SEED, 1, 0666 | IPC_CREAT)

if (sem_id == -1)

{

fprintf(stderr, "semget failed.\n")

exit(EXIT_FAILURE)

}

/* Init shared-memory */

shm_id = shmget((key_t)SHM_SEED, sizeof(struct shared_use_st), 0666 | IPC_CREAT)

if (shm_id == -1)

{

fprintf(stderr, "shmget failed.\n")

exit(EXIT_FAILURE)

}

shared_memory = shmat(shm_id, (void*)0, 0)

if (shared_memory == (void*)-1)

{

fprintf(stderr, "shmat failed.\n")

exit(EXIT_FAILURE)

}

shared_stuff = (struct shared_use_st*)shared_memory

shared_stuff->end_flag = 0

printf("FRAME_CNT: %d\n", frame_cnt)

set_semvalue(sem_id, 1)

while (read_frame_from_file(&frame, fp_in) == 0)

{

semaphore_p(sem_id)

/* Write it into shared memory */

write_frame_into_shm(shared_stuff, &frame)

shared_stuff->end_flag = 0

semaphore_v(sem_id)

frame_cnt++

printf("FRAME_CNT: %d\n", frame_cnt)

}

semaphore_p(sem_id)

shared_stuff->end_flag = 1

semaphore_v(sem_id)

/* over */

printf("\nProducer over!\n")

fclose(fp_in)

free_frame(&frame)

del_semvalue(sem_id)

if (shmdt(shared_memory) == -1)

{

fprintf(stderr, "shmdt failed.\n")

exit(EXIT_FAILURE)

}

exit(EXIT_SUCCESS)

}


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/131002.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-16
下一篇2023-03-16

发表评论

登录后才能评论

评论列表(0条)

    保存