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

Linux通信之共享内存

2012-10-02 15:06 190 查看
共享内存有以下几个关键的函数,写在这里,记一下。

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。

可强制类型转换你想要的指针类型,如果shmaddr为0,内核会把共享内存映像到调用进程的地址空间中选定位置;如果shmaddr不为0,内核会把共享内存映像到shmaddr指定的位置。所以一般把shmaddr设为0。

int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式

成功时,这个函数返回共享内存的起始地址。失败时返回-1。

4) shmdt()函数删除本进程对这块内存的使用,shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。

函数原型:

int shmdt(
 void *addr );

参数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

示例程序:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define IPCKEY 0x521005
typedef struct
{
char name[10];
int number;
} stu_info;
int main(int argc, char** argv)
{
int shm_id;
key_t key;
stu_info *student;
//IPCKEY=ftok("/tmp", 65 );
shm_id=shmget(IPCKEY,1028,0640|IPC_CREAT|IPC_EXCL);
if(shm_id==(void *)-1)
{
printf("shmget error\n");
return -1;
}
//将这块共享内存区附加到自己的内存段,void*->stu_info *
student=(stu_info*)shmat(shm_id,NULL,0);
strncpy(student->name,"lurenx",10);
printf( "name:%s\n",student->name );
student->number = 97930971;
printf( "number:%d\n",student->number );
system("ipcs -m");//此时可看到有进程关联到共享内存的信息,nattch为1
//将这块共享内存区从自己的内存段删除出去
if(shmdt(student) == -1)
perror(" detach error ");
system("ipcs -m");//此时可看到有进程关联到共享内存的信息,nattch为0
//删除共享内存
if (shmctl( shm_id , IPC_RMID , NULL ) == -1)
perror(" delete error ");
//exit(0);

}




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