Linux共享内存(顺便求解惑)

        最近使用多进程共享内存来实现将图像处理算法进行模块化的功能,每个处理算法对应一个进程,他们之间的数据传输通过共享内存实现,比如简单的3个图像处理预处理算法:灰度化,滤波,二值化。我们就写3个CPP文件灰度化.cpp,滤波.cpp,二值化.cpp,然后编译成灰度化.exe,滤波.exe,二值化.exe3个图像处理模块。

        其运行过程大致解释为:

       1.灰度化.exe模块:读取原图像->进行灰度化处理->输出灰度图像->将输出图像写入共享内存a段->退出。

       2.滤波.exe模块:从共享内存a段读取灰度图像->进行滤波处理->输出滤波后的图像->将输出图像写入共享内存b段->退出

       3.二值化.exe模块:从共享内存b段读取滤波后图像->进行二值化处理->输出二值化后的图像->将输出图像写入共享内存c段待其他算法模块处理->退出

        Linux共享内存的几个API怎么用就不介绍了,这些文章已经很多了,直接上代码(注:这边的图像用文件名模拟实际的图像数据)->退出。

       1.灰度化.exe模块:<gray.cpp>

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>

#define IMAGE_BUFFER	1024 * 1024 * 3

int main(int argc, char **argv){
	
	printf("======Gray Process======\n");
	// 0.获取内存ID
	int read_mem_id = atoi(argv[1]);
	int write_mem_id = atoi(argv[2]);

	// 1.创建写共享内存
	char *myDataStruct;
	void *share_memory = (void *)0;	// 创建共享内存指针
	int shmid = shmget((key_t)write_mem_id, IMAGE_BUFFER, 0666 | IPC_CREAT);// 开辟内存
	if (shmid == -1) {
		
		fprintf(stderr, "shmget failed\n");
		exit(EXIT_FAILURE);
	}
	share_memory = (char *)shmat(shmid, (void *)0, 0);// 映射内存
	
	if (share_memory == (void *)-1) {
		
		fprintf(stderr, "shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("Memory attached at %p\n", (int *)(share_memory));
	
	myDataStruct = (char *)share_memory;
	
	// 2.图像处理
	char src_image_name[IMAGE_BUFFER];
	char gray_image_name[IMAGE_BUFFER];
	strncpy(src_image_name	, "src.jpg"	, strlen("src.jpg") + 1);
	strncpy(gray_image_name	, "gray.jpg", strlen("gray.jpg") + 1);
	printf("***Read image from <%s>\n"			, src_image_name);
	printf("***Gray image from <%s> to <%s>\n"	, src_image_name, gray_image_name);
	
	// 3.写入处理结果到共享内存
	strcpy(myDataStruct ,gray_image_name);
	
	return 0;
}

        2.滤波.exe模块:<blur.cpp>

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>

#define IMAGE_BUFFER	1024 * 1024 * 3

int main(int argc, char **argv){
	
	printf("======Blur Process======\n");
	// 0.获取内存ID
	int read_mem_id = atoi(argv[1]);
	int write_mem_id = atoi(argv[2]);
	
	// 1.创建读共享内存
	char *myDataStruct;
	void *share_memory = (void *)0;// 创建共享内存指针
	int shmid = shmget((key_t)read_mem_id, IMAGE_BUFFER, 0666 | IPC_CREAT);// 开辟内存
	if (shmid == -1) {
		
		fprintf(stderr, "shmget failed\n");
		exit(EXIT_FAILURE);
	}
	share_memory = (char *)shmat(shmid, (void *)0, 0);// 映射内存
	
	if (share_memory == (void *)-1) {
		
		fprintf(stderr, "shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("Memory attached at %p\n", (int *)(share_memory));
	
	myDataStruct = (char *)share_memory;
	
	// 2.图像处理
	char *gray_image_name = myDataStruct;
	char blur_image_name[IMAGE_BUFFER];
	strncpy(blur_image_name	, "blur.jpg", strlen("blur.jpg") + 1);
	printf("***Blur image from <%s> to <%s>\n"	, gray_image_name, blur_image_name);
	
	// 3.创建写共享内存
	share_memory = (void *)0;// 初始化共享内存指针
	shmid = shmget((key_t)write_mem_id, IMAGE_BUFFER, 0666 | IPC_CREAT);// 开辟内存
	if (shmid == -1) {
		
		fprintf(stderr, "shmget failed\n");
		exit(EXIT_FAILURE);
	}
	share_memory = (char *)shmat(shmid, (void *)0, 0);// 映射内存
	
	if (share_memory == (void *)-1) {
		
		fprintf(stderr, "shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("Memory attached at %p\n", (int *)(share_memory));
	
	myDataStruct = (char *)share_memory;
	
	// 4.写入处理结果到共享内存
	strcpy(myDataStruct ,blur_image_name);
	
	return 0;
}

        3.二值化.exe模块:<threshold.cpp>

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>

#define IMAGE_BUFFER	1024 * 1024 * 3

int main(int argc, char **argv){
	
	printf("======Threshold Process======\n");
	// 0.获取内存ID
	int read_mem_id = atoi(argv[1]);
	int write_mem_id = atoi(argv[2]);
	
	// 1.创建读共享内存
	char *myDataStruct;
	void *share_memory = (void *)0;// 创建共享内存指针
	int shmid = shmget((key_t)read_mem_id, IMAGE_BUFFER, 0666 | IPC_CREAT);// 开辟内存
	if (shmid == -1) {
		
		fprintf(stderr, "shmget failed\n");
		exit(EXIT_FAILURE);
	}
	share_memory = (char *)shmat(shmid, (void *)0, 0);// 映射内存
	
	if (share_memory == (void *)-1) {
		
		fprintf(stderr, "shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("Memory attached at %p\n", (int *)(share_memory));
	
	myDataStruct = (char *)share_memory;
	
	// 2.图像处理
	char *blur_image_name = myDataStruct;
	char thresh_image_name[IMAGE_BUFFER];
	strncpy(thresh_image_name	, "thresh.jpg", strlen("thresh.jpg") + 1);
	printf("***threshold image from <%s> to <%s>\n"	, blur_image_name, thresh_image_name);
	
	// 3.创建写共享内存
	share_memory = (void *)0;// 初始化共享内存指针
	shmid = shmget((key_t)write_mem_id, IMAGE_BUFFER, 0666 | IPC_CREAT);// 开辟内存
	if (shmid == -1) {
		
		fprintf(stderr, "shmget failed\n");
		exit(EXIT_FAILURE);
	}
	share_memory = (char *)shmat(shmid, (void *)0, 0);// 映射内存
	
	if (share_memory == (void *)-1) {
		
		fprintf(stderr, "shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("Memory attached at %p\n", (int *)(share_memory));
	
	myDataStruct = (char *)share_memory;
	
	// 4.写入处理结果到共享内存
	strcpy(myDataStruct ,thresh_image_name);
	
	return 0;
}

        以下是编译和运行的脚本run.sh:

#!/bin/bash

g++ gray.cpp -o gray
g++ blur.cpp -o blur
g++ threshold.cpp -o threshold

./gray 1 2
./blur 2 3
./threshold 3 4
        命令行下运行./run.sh,其输出结果如下:

        结果在意料之中。但是······

        但是我在将共享内存的大小变大时,却出错了,我将IMAGE_BUFFER改成1024 * 1024 * 4,程序就出现段错误了,连第一句的printf打印都没打印出来,实测IMAGE_BUFFER最大值为:1024 * 1024 * 3 + 1024 * 1018,再多一个字节就出现段错误···,于是我就想是不是这个最大值可以设置,百度了一下,这个值可以通过命令:cat /proc/sys/kernel/shmmax看到(单位是字节),运行结果如下:


        日了狗了,这个值这么大,为什么我将内存大小设置为1024 * 1024 * 4(4M)就报错?通过ipcs -s显示,是可以分配超过4M的,比如如下图,系统的一个共享内存就是16M的。


        但是为嘛我设置成4M以上就段错误了,而且连第一句的printf都没打印出来,效果如下,希望哪位大佬可以解惑解惑!


        如果哪位大佬有思路和想法,请高抬贵手为我解惑下,谢谢!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值