条件变量放在共享内存中可以进程间同步吗

条件变量放在共享内存中可以进程间同步吗,第1张

一、简介

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

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

在实际编程中,可以使用

信号量

传递消息(使用管道或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)

}

信号量在进程是以有名信号量进行通信的,在线程是以无名信号进行通信的,因为线程linux还没有实现进程间的通信,所以在sem_init的第二个参数要为0,而且在多线程间的同步是可以通过有名信号量也可通过无名信号,但是一般情况线程的同步是无名信号量,无名信号量使用简单,而且sem_t存储在进程空间中,有名信号量必须LINUX内核管理,由内核结构struct ipc_ids 存储,是随内核持续的,系统关闭,信号量则删除,当然也可以显示删除,通过系统调用删除,

消息队列,信号量,内存共享,这几个都是一样的原理。,只不过信号量分为有名与无名

无名使用 <semaphore.h>,

有名信号量<sys/sem.h>

无名信号量不能用进程间通信,

//无名与有名的区别,有名需要KEY值与IPC标识

所以sem_init的第二个参数必须为0,,,,

seo:seo优化就是搜索引擎优化的简称就是让你的网站排名更加的靠前和为你的网站提供更多的流量与转化SEO ,用专业的回答来说就是做搜索引擎排名。

sem:英文Search Engine Marketing的手写字母简称,翻译中文就是搜索引擎营销,就是根据用户使用搜索引擎的方式利用用户检索信息的机会尽可能将营销信息传递给目标用户。简单来说,搜索引擎营销就是基于搜索引擎平台的网络营销,利用人们对搜索引擎的依赖和使用习惯,在人们检索信息的时候将信息传递给目标用户。它是一种新的网络营销形式。

你还不知道该如何分配你进行搜索引擎营销的预算,或者是你不知道怎样更好地向顾客解释SEO和SEM的区别,不懂得如何根据企业现有的特点来进行对应的优化战略,那你就更需要阅读本文了,能有效助你更好了解两者的区别

1、跨搜索引擎平台效果:

SEO优化是针对所有的搜索引擎来做的,只要SEO的方法是白帽的、专业的、面向用户体验的,那么你不仅仅能收获百度来的流量,谷歌,搜狗,360,雅虎都会不同程度的认可你的网站,从而给你网站良好的展示位置。而SEM,不同的搜索引擎有不同的服务机制。

2、提升流量无须增加预算:

要提升PPC的流量,你必须提升预算。但SEO不一样,SEO优化有点像滚雪球,一开始虽然不起眼,但雪球一旦滚起来,机制一旦建立,那么势必后劲十足,效果越到后面越显著,而无需你投入更多。

3、停止花费,流量余存:

一个经过专业SEO优化后的网站自然流量不会因为你停止了SEO服务而立即消失,相反这段流量会持续相当长的一段时间,理论上来说如果没有过大的外部竞争以及搜索算法没有大变化的话,流量基本上是稳定的。所以,如果真要算的话,至少应该拿2年的SEO流量去和一年的SEM流量去做比较。

4、更高的信任度:

比起SEM,SEO有更高的用户信任度。毕竟SEM也是一种商业广告,用户点击本身就是抱着一种看广告的心态,如果不满意就跳出看下一条。而自然排名则不同,用户会认为靠自然排名排上去的网站更专业、更可信,同时用户参与度和转化率也更高。

5、排除负面消息:

试想如果在你的SEM广告下面有一条SEO的负面消息,是不是很糟糕?通常负面消息的影响力要比正面消息大3-5倍,所以平时就要重视SEO,通过SEO,可以更好地巩固第一页的搜索结果的权重,设立好这样的保护屏障,可以有效防止负面入侵。只是很多公司都是等事情发生了再去做挽回。

6、更容易吸引点击:

自然结果毕竟处在SERP的用户视觉重心处,相比SEM可以获得更多的关注和点击。按以往的经验来看,自然结果第一名的SEO流量通常要高于排在PPC第一名的广告。

所以根据企业的现有条件和企业的特点来选取相对应的方式来进行优化,不仅能降低优化时需要的成本更重要的是能有效提高优化的效率。达到预期想要的结果。

优先内容是每一个搜索引擎优化活动带动增量流量和收入必须的。以SEO人员来说,我们必须继续专注于根据用户的意图,帮助我们的客户实现他们的目标,构建出高品质的内容。


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

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

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

发表评论

登录后才能评论

评论列表(0条)

    保存