system v linux,Linux IPC实践(9) --System V共享内存

共享内存API

#include

#include

int shmget(key_t key, size_t size, int shmflg);

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

//System V 共享内存基本数据结构

struct shmid_ds

{

struct ipc_perm shm_perm; /* Ownership and permissions: System V IPC所共有的数据结构 */

size_t shm_segsz; /* Size of segment (bytes): 共享内存段的大小 */

time_t shm_atime; /* Last attach time */

time_t shm_dtime; /* Last detach time */

time_t shm_ctime; /* Last change time */

pid_t shm_cpid; /* PID of creator */

pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */

shmatt_t shm_nattch; /* No. of current attaches */

...

};

shmget

int shmget(key_t key, size_t size, int shmflg);

创建共享内存,并将该内存的内容初始化为0;

打开一个已经存在共享内存, 如果打开时不知道共享内存的大小, 可以将size指定为0, shmflg可以指定为0(按照默认的权限打开);

参数:

key:这个共享内存段名字;

size:共享内存大小(bytes);

shmflg:用法类似msgget中的msgflg参数;

返回值:

成功返回一个非负整数,即该共享内存段的标识码;失败返回-1

/**示例: 创建并打开一个共享内存 **/

int main(int argc,char **argv)

{

const int SHM_SIZE = 1024;

int shmid = shmget(0x1234, SHM_SIZE, 0666|IPC_CREAT);

if (shmid == -1)

err_exit("shmget error");

cout << "share memory get success" << endl;

}

shmat

void *shmat(int shmid, const void *shmaddr, int shmflg);

连接到本进程地址空间,成功连接之后, 对该内存的操作就与malloc来的一块内存非常类似了, 而且如果这块内存中有数据, 则就可以直接将其中的数据取出来!!

参数:

shmaddr:指定连接的地址(推荐使用NULL)

shmflg:一般指定为0, 表示可读,可写; 而它的另外两个可能取值是SHM_RND和SHM_RDONLY(见下)

返回值:

成功返回一个指针,指向共享内存起始地址;失败返回(void *) -1

shmaddr与shmflg组合说明

shmaddr为NULL

Linux内核自动为进程连接到进程的内存(推荐使用)

shmaddr不为NULL且shmflg无SHM_RND标记

以shmaddr为连接地址

shmaddr不为NULL且shmflg设置了SHM_RND标记

连接的地址会自动向下调整为SHMLBA的整数倍;

公式:shmaddr - (shmaddr % SHMLBA)

SHMLBA为内存页面的大小(4K)

shmflg=SHM_RDONLY

只读共享内存, 不然的话就是可读,可写的, 注意: 此处没有可读,可写这个概念

shmdt

int shmdt(const void *shmaddr);

参数:

shmaddr: 由shmat所返回的指针

注意:将共享内存段与当前进程脱离不等于删除共享内存段

/** 示例: 将数据写入/读出共享内存

程序write: 将数据写入共享内存

程序read: 将数据读出共享内存(当然, 可以读取N多次)

**/

//write程序

struct Student

{

char name[26];

int age;

};

int main(int argc,char **argv)

{

int shmid = shmget(0x1234, sizeof(Student), 0666|IPC_CREAT);

if (shmid == -1)

err_exit("shmget error");

// 以可读, 可写的方式连接该共享内存

Student *p = (Student *)shmat(shmid, NULL, 0);

if (p == (void *)-1)

err_exit("shmat error");

strcpy(p->name, "xiaofang");

p->age = 22;

shmdt(p);

}

//read程序

int main(int argc,char **argv)

{

int shmid = shmget(0x1234, 0, 0);

if (shmid == -1)

err_exit("shmget error");

// 以只读方式连接该共享内存

Student *p = (Student *)shmat(shmid, NULL, 0);

if (p == (void *)-1)

err_exit("shmat error");

// 直接将其中的内容打印输出

cout << "name: " << p->name << ", age: " << p->age << endl;

shmdt(p);

}

shmctl

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

设置/获取共享内存属性

参数:

cmd:将要采取的动作(三个取值见下)

buf:指向一个保存着共享内存的模式状态和访问权限的数据结构

VQYEjSlXNliiMJVm.png

System V共享内存小结:

1.共享内存被别的程序占用,则删除该共享内存时,不会马上删除(引用计数计数);

2.此时会出现一个现象:该共享内存的key变为0x00000000,变为私有;

3.此时还可以读,但必须还有办法获取该共享内存的ID(shmid),因为此时试图通过该共享内存的key获取该共享内存,是白费的!

/** 示例: 删除共享内存 **/

int main(int argc,char *argv[])

{

int shmid = shmget(0x1234, 0, 0);

if (shmid == -1)

err_exit("shmget error");

if (shmctl(shmid, IPC_RMID, NULL) == -1)

err_exit("shmctl IPC_RMID error");

cout << "share memory remove success" << endl;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值