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)

}

#include

#include

#include

#include types.h>

#include msg.h>

#include

#include ipc.h>

void msg_show_attr(int msg_id, struct msqid_ds msg_info)

{

int ret = -1

sleep(1)

ret = msgctl(msg_id, IPC_STAT, &msg_info)

if( -1 == ret)

{

printf(获消息信息失败\n)

return

}

printf(\n)

printf(现队列字节数:%d\n,msg_info.msg_cbytes)

printf(队列消息数:%d\n,msg_info.msg_qnum)

printf(队列字节数:%d\n,msg_info.msg_qbytes)

printf(发送消息进程pid:%d\n,msg_info.msg_lspid)

printf(接收消息进程pid:%d\n,msg_info.msg_lrpid)

printf(发送消息间:%s,ctime(&(msg_info.msg_stime)))

printf(接收消息间:%s,ctime(&(msg_info.msg_rtime)))

printf(变化间:%s,ctime(&(msg_info.msg_ctime)))

printf(消息UID:%d\n,msg_info.msg_perm.uid)

printf(消息GID:%d\n,msg_info.msg_perm.gid)

}

int main(void)

{

int ret = -1

int msg_flags, msg_id

key_t key

struct msgmbuf{

int mtype

char mtext[10]

}

struct msqid_ds msg_info

struct msgmbuf msg_mbuf

int msg_sflags,msg_rflags

char *msgpath = /ipc/msg/

key = ftok(msgpath,’a')

if(key != -1)

{

printf(功建立KEY\n)

}

else

{

printf(建立KEY失败\n)

}

msg_flags = IPC_CREAT

msg_id = msgget(key, msg_flags|0666)

if( -1 == msg_id)

{

printf(消息建立失败\n)

return 0

}

msg_show_attr(msg_id, msg_info)

msg_sflags = IPC_NOWAIT

msg_mbuf.mtype = 10

memcpy(msg_mbuf.mtext,测试消息,sizeof(测试消息))

ret = msgsnd(msg_id, &msg_mbuf, sizeof(测试消息), msg_sflags)

if( -1 == ret)

{

printf(发送消息失败\n)

}

msg_show_attr(msg_id, msg_info)

msg_rflags = IPC_NOWAIT|MSG_NOERROR

ret = msgrcv(msg_id, &msg_mbuf, 10,10,msg_rfla

共享内存示例代码:

#include

#include sem.h>

#include ipc.h>

#include

typedef int sem_t

union semun {

int val

struct semid_ds *buf

unsigned short *array

} arg

sem_t CreateSem(key_t key, int value)

{

union semun sem

sem_t semid

sem.val = value

semid = semget(key,value,IPC_CREAT|0666)

if (-1 == semid)

{

printf(create semaphore error\n)

return -1

}

semctl(semid,0,SETVAL,sem)

return semid

}

/*

struct sembuf{

ushort sem_num

short sem_op

short sem_flg

}

*/

void SetvalueSem(sem_t semid, int value)

{

union semun sem

sem.val = value

semctl(semid,0,SETVAL,sem)

return

}

int GetvalueSem(sem_t semid)

{

union semun sem

return semctl(semid,0,GETVAL,sem)

return sem.val

}

void DestroySem(sem_t semid)

{

union semun sem

sem.val = 0

semctl(semid,0,IPC_RMID,sem)

}

int Sem_P(sem_t semid)

{

struct sembuf sops={0,+1,IPC_NOWAIT}

return (semop(semid,&sops,1))

}

int Sem_V(sem_t semid)

{

struct sembuf sops={0,-1,IPC_NOWAIT}

return (semop(semid,&sops,1))

}

static char msg[]=共享内存\n

int main(void)

{

key_t key

int semid,shmid

char i,*shms,*shmc

struct semid_ds buf

int value = 0

char buffer[80]

pid_t p

key = ftok(/ipc/sem/,’a')

shmid = shmget(key,1024,IPC_CREAT|0604)

semid = CreateSem(key,1)

p = fork()

if(p >0)

{

/* 父进程 */

/* 建立共享内存 */

shms = (char *)shmat(shmid,0,0)

memcpy(shms, msg, strlen(msg)+1)

sleep(10)

Sem_P(semid)

shmdt(shms)

DestroySem(semid)

}

else if(p == 0)

{

shmc = (char *)shmat(shmid,0,0)

Sem_V(semid)

printf(共享内存值:%s\n,shmc)

shmdt(sg_


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

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

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

发表评论

登录后才能评论

评论列表(0条)

    保存