您的位置:首页 > 运维架构 > Linux

关于共享内存的一个题目(未完)

2013-12-02 21:02 369 查看
一万个计划,不如一个行动,从今天开始重新写博客,立志每周至少写一篇,并且要不断坚持下去。

今天比较闲,因为明天要负责别的项目,所以切换期整好可以偷下懒。同事下午给我了一个题目让我帮忙做下,后来才知道他在帮一个国外的妹纸,细节就不多讲了:-)……题目如下,我是用中文回答的:

Youare to develop and answer the following questions:

Aprogram which will create a shared memory region.

Ifthat region exists, remove the region and try again.

Thepointer type to the region is up to your discretion.

TheSHMID is based on a key from a local text file in your workingdirectory.

Choosethe size of the region to be more than 1 (one) memory page and nota page size multiple (ex size=125445).

Yourprogram will print out the key id from the SHM region in HEX format.

Yourprogram will also capture a signal SIGSEGV.

UponSIGSEGV, your program will print out the number of bytes written tothe region.

Yourprogram will write to the shared memory region until a SIGSEGVoccurs.

Writingany random number or a constant of your data type from offset 0until SIGSEGV

Thenreset the counter do 4.a a
4000
gain.

Yourprogram will loop 5 times (step 4 five times).

Questions:

Dida SIGSEGV signal occur and what was the number of bytes written tothe region before the signal was captured?

如果只写一次,且你的数据类型的大小不超过共享内存大小,不会发生sigsegv
如果连续写共享内存,假设你设置的共享内存有125445个字节,每页有4096个字节,则共享内存会有31页,即126976个字节,假设每次写4个字节,则会写入126976个字节,然后再继续写就有可能会产生sigsegv

Whydid the SIGSEGV occur or what analysis do you have on why it did notoccur.

内存越界

Isthere a difference between the number of bytes written than yourrequested size during creation of the SHM region.

                thenumber of bytes written:所写内存大小
                yourrequested size duringcreation:共享内存最大大小为页整数倍,即4096的整数倍,如果shmget的第二个参数不为4096的整数倍,操作系统会给该共享内存进行4096的对齐
                所写的内存大小需要在所创建内存大小范围之内,否则会出现内存越界,会抛出段错误

Couldyou complete item 5 of the program? Please explain why or why not.

                这个程序不能循环执行,因为程序产生了段错误之后,便会进入信号处理函数处理,处理完之后继续回到出错的地方,该错误会继续产生,即会不断抛出SIGSEGV信号,而无法完成剩下的4次循环
---------------------------------------------------------------------------------------
回过头来看这个题目,貌似这个题目考察以下几个内容
1.shmget函数中第二个参数不论你怎么设置,操作系统会帮你进行页对齐
2.内存越界会产生段错误(关于题干的第四点依然不是很懂,不明白是不断顺序写还是只写一个随机数或常量)
3.SIGSEGV信号的捕获之后,程序的行为如何

今天做这个题目花了不少时间,主要是对共享内存的使用不熟,做题的同时顺便也补补课。在解决第三个问题的时候,发现网上有人用siglongjmp的方式从信号处理函数跳回产生SIGSEGV的地方,然后通过之前保存的sigsetjmp恢复出错之前的环境,想用这样的方式循环五次,但最后还是失败告终,具体为什么会这样还没有弄清楚,代码先保存起来,在这里做个记录,以后有时间再找出具体的原因把。关于这道题的程序代码如下:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>

const char *path = "/tmp";
int memsize = 4097;
int count = 0;
unsigned int *tmpbuf = 0;
unsigned int *buf = 0;
sigjmp_buf env;

void recvSignal(int sig)
{
printf("received segment fault, count = %d !!!\n", count);
count = 0;
siglongjmp(env, 1);
}

int main()
{
//signal(SIGSEGV, recvSignal);

key_t key = ftok(path, 'a');
if (key < 0)
{
fprintf(stderr, "ftok err: %s\n", strerror(errno));
return -1;
}

int shmid = shmget(key, memsize, 0666 | IPC_CREAT | IPC_EXCL);
if (shmid < 0)
{
// delete the old
shmid = shmget(key, memsize, 0666 | IPC_CREAT);
shmctl(shmid, IPC_RMID, NULL);
}

// recreate
shmid = shmget(key, memsize, 0666 | IPC_CREAT | IPC_EXCL);
if (shmid < 0)
{
printf("shmget error: %s\n", strerror(errno));
return -1;
}

printf("SHMID=%d\n", shmid);
buf = (unsigned int*)shmat(shmid, NULL, 0);

int i = 0;
for (; i < 5; i++)
{
int r = sigsetjmp(env, 1);

if (r == 0)
{
signal(SIGSEGV, recvSignal);
tmpbuf = buf;
printf("tmpbuf=%x, count=%d\n", tmpbuf, count);
while (1)
{
*(tmpbuf++) = 1;
count += 4;
}
}
else
{
printf("jump back");
}
sleep(5);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  共享内存 Linux