linux c 进程间通讯,shmat 共享内存之后,memset段错误,求教5555

zzzzluo 2011-08-23 11:13:14
linux c 进程间通讯,shmat 共享内存之后,memset段错误,求教5555
shmat 返回的地址ok的
使用gdb调试,在memset的时候Program received signal SIGSEGV, Segmentation fault
如果去掉memset ,到了读写内存的时候也同样是段错误,求教。。谢谢
typedef struct
{
char a[16];
char b[16];
}Strutest;
typedef struct
{
int indx;
Strutest S8testData[1024];
}StruAlltest;

StruAlltest *gMemtest;
int s32Index,s32ID;
unsigned int u32Addr;

s32ID = shmget(s32Index,u32Size,IPC_CREAT|0777);
if(s32ID == -1)
{
perror("shmget error");
//printf("shmget error.\n");
return(NULL);
}

u32Addr = (unsigned int)shmat(s32ID,NULL,0);
gMemtest= (StruAlltest*)u32Addr;
memset(gMemtest,0,u32Size);

...全文
624 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
不辣 2011-08-23
  • 打赏
  • 举报
回复
试试把
memset(gMemtest,0,u32Size);

改为:memset((char*)gMemtest,0,u32Size);
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
u32Addr都从没等于-1过~
hacqing 2011-08-23
  • 打赏
  • 举报
回复
u32Addr = (unsigned int)shmat(s32ID,NULL,0);

判断u32Addr是否为-1
Upon successful completion, shmat() shall increment the value of shm_nattch in the data structure associated with the shared memory ID of the attached shared memory segment and return the segment's start address.

Otherwise, the shared memory segment shall not be attached, shmat() shall return -1, and errno shall be set to indicate the error.

zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
看了很多书本范例,都没有关于初始化的。。。创建共享内存 ,总要有个进程最先初始化吧。。
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
为了简洁,大家好看,代码贴了一部分而已。。我补充下


不好意思啊。。呵呵
s32Index = ftok("test",0);
if(s32Index == -1)
{ printf("ftok error.\n");
return(NULL);
}
jackyjkchen 2011-08-23
  • 打赏
  • 举报
回复
我觉得你把未初始化的s32Index传进去是有问题的
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
if(gMemtest== NULL) return(-1);
printf("%x\n",gMemtest);//699ce000 有打印出地址
jackyjkchen 2011-08-23
  • 打赏
  • 举报
回复
shmat是有可能失败的
qq120848369 2011-08-23
  • 打赏
  • 举报
回复
你没有检查过u32Addr是否为空就memset,于是一切皆有可能。
不辣 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 zzzzluo 的回复:]
s32ID = shmget(s32Index,u32Size * 2,IPC_CREAT|0777);//
*2 要去掉

我原来的程序

后面补上*2 能运行。。读写都ok
后面换上你最后给我的代码。。好像不用*2也OK,。。。奇怪
[/Quote]

shmget()的第一个参数就是要申请内存的大小,跟malloc类似,不必过于纠结,管理好内存就行
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
s32ID = shmget(s32Index,u32Size * 2,IPC_CREAT|0777);//
*2 要去掉

我原来的程序

后面补上*2 能运行。。读写都ok
后面换上你最后给我的代码。。好像不用*2也OK,。。。奇怪
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
谢谢了。。让我的理解更进一步。。呵呵
看来我的程序哪里有问题。。指针没转换好

sprintf(c8Buf,"%sSMemGprs",SHARTMEM_PATH); //gprs
s32size = sizeof(*gMemGprsData);
printf("size %d\n",s32size);
gMemGprsData = (StruAllGprsData *)CreatShareMem(c8Buf,sizeof(StruAllGprsData));
if(gMemGprsData == NULL) return(-1);
printf("%x\n",gMemGprsData);
memset(gMemGprsData,0,s32size);
//创建共享内存
void *CreatShareMem(char *c8PName,unsigned int u32Size)
{
int s32Index,s32ID;
char *u32Addr;
//unsigned int u32Addr;
FILE *fp;

fp = fopen(c8PName,"rb"); //创建文件
if(fp == NULL)
{ fp = fopen(c8PName,"wb");
if(fp == NULL)
{ printf("Creat file %s error.\n",c8PName);
return(NULL);
}
}
fclose(fp);

s32Index = ftok(c8PName,0);
if(s32Index == -1)
{ printf("ftok error.\n");
return(NULL);
}

s32ID = shmget(s32Index,u32Size * 2,IPC_CREAT|0777);//IPC_CREAT|IPC_EXCL|0600
if(s32ID == -1)
{
perror("shmget error");
//printf("shmget error.\n");
return(NULL);
}

u32Addr = (char*)shmat(s32ID,NULL,0);

//u32Addr += 3;
//u32Addr &= 0xFFFFFFFC;

printf("Share mem %s addr=0x%X,size=%d\r\n",c8PName,u32Addr,u32Size);

return((void *)u32Addr);
}
不辣 2011-08-23
  • 打赏
  • 举报
回复

#include <sys/shm.h>
#include <string.h>

typedef struct
{
char a[16];
char b[16];
}Strutest;

typedef struct
{
int indx;
Strutest S8testData[1024];
}StruAlltest;

int main(int argc, char **argv)
{
StruAlltest *gMemtest;
int s32Index = 0x000010221, s32ID;
// unsigned int u32Addr;
char *u32Addr;

// s32ID = shmget(s32Index,u32Size,IPC_CREAT|0777);
s32ID = shmget(s32Index, sizeof(StruAlltest) , IPC_CREAT|0777);
if(s32ID == -1)
{
perror("shmget error");
return -1;
}

u32Addr = (char*)shmat(s32ID,NULL,0);
gMemtest= (StruAlltest*)u32Addr;
memset(gMemtest,0,sizeof(StruAlltest) );
return 0;
}
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
为什么sizeof(StruAlltest)这样的大小去 ,memset有段错误。。我还是很郁闷。。
因为我在arm7 和arm9上面memset是ok的。。
不辣 2011-08-23
  • 打赏
  • 举报
回复
s32ID = shmget(s32Index, sizeof(StruAlltest) * 2, IPC_CREAT|0777);
memset(gMemtest,0,sizeof(StruAlltest) * 2);


要一致!
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
但是为什么我只要申请我定义的结构那么大的内存就不行了呢?我之前以为内存溢出,有尝试size+ 1 之类的。。好像也不行
size不能刚刚好吗?
不辣 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zzzzluo 的回复:]
楼上的,你好。。测试了你的代码。。ok的
请教下int s32Index = 0x000010221,这个值的定义有什么特殊的吗?
sizeof为什么*2?
[/Quote]

int s32Index = 0x000010221 是共享内存的KEY,用16进制,是为了方便用命令 ipcs 查到自己创建的共享内存,因为ipcs下显示的是16进制

size*2 只是随便举得例子,填自己想要申请的共享内存的大小

zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
测试了下。。只要size*2 就可以了。。难道因为是机器的问题,32位?64位?
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
如果定义的结构不一样,key就要不一样吗?size为什么放大一倍呢?
zzzzluo 2011-08-23
  • 打赏
  • 举报
回复
楼上的,你好。。测试了你的代码。。ok的
请教下int s32Index = 0x000010221,这个值的定义有什么特殊的吗?
sizeof为什么*2?
加载更多回复(3)
要使用共享内存,应该有如下步骤: 1.开辟一块共享内存 shmget() 2.允许本进程使用共某块共享内存 shmat() 3.写入/读出 4.禁止本进程使用这块共享内存 shmdt() 5.删除这块共享内存 shmctl()或者命令行下ipcrm ftok()。它有两个参数,一个是字符串,一个是字符。字符串一般用当前进程的程序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内存。ftok()会返回一个key_t型的值,也就是计算出来的标识符的值。 shmkey = ftok( "mcut" , 'a' ); // 计算标识符 操作共享内存,我们用到了下面的函数 #include #include #include int shmget( key_t shmkey , int shmsiz , int flag ); void *shmat( int shmid , char *shmaddr , int shmflag ); int shmdt( char *shmaddr ); shmget()是用来开辟/指向一块共享内存的函数。参数定义如下: key_t shmkey 是这块共享内存的标识符。如果是父子关系的进程通信的话,这个标识符用IPC_PRIVATE来代替。但是刚才我们的两个进程没有任何关系,所以就用ftok()算出来一个标识符使用了。 int shmsiz 是这块内存的大小. int flag 是这块内存的模式(mode)以及权限标识。 模式可取如下值: 新建:IPC_CREAT 使用已开辟的内存:IPC_ALLOC 如果标识符以存在,则返回错误值:IPC_EXCL 然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。 如: IPC_CREAT | IPC_EXCL | 0666 这个函数成功时返回共享内存的ID,失败时返回-1。 // shmid开辟共享内存 shmid = shmget( shmkey , sizeof(in_data) , IPC_CREAT | 0666 ) ; shmat()是用来允许本进程访问一块共享内存的函数。 int shmid是那块共享内存的ID。 char *shmaddr是共享内存的起始地址 int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式 成功时,这个函数返回共享内存的起始地址。失败时返回-1。 char *head , *pos , head = pos = shmat( shmid , 0 , 0 ); // 允许本进程使用这块共享内存 shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。 参数char *shmaddr是那块共享内存的起始地址。 成功时返回0。失败时返回-1。 shmdt( head ); // 禁止本进程使用这块内存 此外,还有一个用来控制共享内存shmctl()函数如下: #include #include #include int shmctl( int shmid , int cmd , struct shmid_ds *buf ); int shmid是共享内存的ID。 int cmd是控制命令,可取值如下: IPC_STAT 得到共享内存的状态 IPC_SET 改变共享内存的状态 IPC_RMID 删除共享内存 struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。 返回值: 成功:0 失败:-1 shmctl(shmid,IPC_RMID,NULL); 刚才我们的mpaste.c程序中还可以加入这样几句。 struct shmid_ds buf; ... ... shmctl( shmid , IPC_STAT , &buf ); // 取得共享内存的状态 ... ... shmctl( shmid , IPC_RMID , &buf ); // 删除共享内存 注意:在使用共享内存,结束程序退出后。如果你没在程序中用shmctl()删除共享内存的话,一定要在命令行下用ipcrm命令删除这块共享内存。你要是不管的话,它就一直在那儿放着了。 简单解释一下ipcs命令和ipcrm命令。 取得ipc信息: ipcs [-m|-q|-s] -m 输出有关共享内存(shared memory)的信息 -q 输出有关信息队列(me
共享内存是系统出于多个进程通讯的考虑,而预留的的一块内存区。在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区标识符数shmmni等,可以手工对其调整,但不推荐这样做。 一、应用 共享内存的使用,主要有以下几个API:ftok()、shmget()、shmat()、shmdt()及shmctl()。 1)用ftok()函数获得一个ID号. 应用说明: 在IPC中,我们经常用用key_t的值来创建或者打开信号量,共享内存和消息队列。 函数原型: key_t ftok(const char *pathname, int proj_id); Keys: 1)pathname一定要在系统中存在并且进程能够访问的 3)proj_id是一个1-255之的一个整数值,典型的值是一个ASCII值。 当成功执行的时候,一个key_t值将会被返回,否则-1被返回。我们可以使用strerror(errno)来确定具体的错误信息。 考虑到应用系统可能在不同的主机上应用,可以直接定义一个key,而不用ftok获得: #define IPCKEY 0x344378 2)shmget()用来开辟/指向一块共享内存的函数 应用说明: shmget()用来获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域。 函数原型: int shmget(key_t key, size_t size, int shmflg); key_t key 是这块共享内存的标识符。如果是父子关系的进程通信的话,这个标识符用IPC_PRIVATE来代替。如果两个进程没有任何关系,所以就用ftok()算出来一个标识符(或者自己定义一个)使用了。 int size 是这块内存的大小. int flag 是这块内存的模式(mode)以及权限标识。 模式可取如下值: IPC_CREAT 新建(如果已创建则返回目前共享内存的id) IPC_EXCL 与IPC_CREAT结合使用,如果已创建则则返回错误 然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。 如: IPC_CREAT | IPC_EXCL | 0640 例子中的0666为权限标识,4/2/1 分别表示读/写/执行3种权限,第一个0是UID,第一个6(4+2)表示拥有者的权限,第二个4表示同组权限,第3个0表示他人的权限。 这个函数成功时返回共享内存的ID,失败时返回-1。 关于这个函数,要多说两句。 创建共享内存时,shmflg参数至少需要 IPC_CREAT | 权限标识,如果只有IPC_CREAT 则申请的地址都是k=0xffffffff,不能使用; 获取已创建的共享内存时,shmflg不要用IPC_CREAT(只能用创建共享内存时的权限标识,如0640),否则在某些情况下,比如用ipcrm删除共享内存后,用该函数并用IPC_CREAT参数获取一次共享内存(当然,获取失败),则即使再次创建共享内存也不能成功,此时必须更改key来重建共享内存。 3) shmat()将这个内存区映射到本进程的虚拟地址空。 函数原型: void *shmat( int shmid , char *shmaddr , int shmflag ); shmat()是用来允许本进程访问一块共享内存的函数。 int shmid是那块共享内存的ID。 char *shmaddr是共享内存的起始地址,如果shmaddr为0,内核会把共享内存映像到调用进程的地址空中选定位置;如果shmaddr不为0,内核会把共享内存映像到shmaddr指定的位置。所以一般把shmaddr设为0。 int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式 成功时,这个函数返回共享内存的起始地址。失败时返回-1。 4) shmdt()函数删除本进程对这块内存的使用,shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。 函数原型: int shmdt( char *shmaddr ); 参数char *shmaddr是那块共享内存的起始地址。 成功时返回0。失败时返回-1。 5) shmctl() 控制对这块共享内存的使用 函数原型: int shmctl( int shmid , int cmd , struct shmid_ds *buf ); int shmid是共享内存的ID。 int cmd是控制命令,可取值如下: IPC_STAT 得到共享内存的状态 IPC_SET 改变共享内存的状态 IPC_RMID 删除共享内存 struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。 返回值: 成功:0 失败:-1

69,379

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧