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

Linux IPC实践(10) --Posix共享内存

2016-01-03 10:21 232 查看
1. 创建/获取一个共享内存

[cpp] view
plaincopy





#include <sys/mman.h>

#include <sys/stat.h> /* For mode constants */

#include <fcntl.h> /* For O_* constants */

int shm_open(const char *name, int oflag, mode_t mode);

参数:

name: 共享内存名字;

oflag: 与open函数类型, 可以是O_RDONLY, O_WRONLY, O_RDWR, 还可以按位或上O_CREAT, O_EXCL, O_TRUNC.

mode: 此参数总是需要设置, 如果oflag没有指定O_CREAT, 则mode可以设置为0;

返回值:

成功: 返回一个文件描述符;

失败: 返回-1;

注意-Posix IPC名字限制:

1. 必须以”/”开头, 并且后面不能还有”/”, 形如:/file-name;

2. 名字长度不能超过NAME_MAX

3. 链接时:Link with -lrt.

[cpp] view
plaincopy





/** 示例: 共享内存的打开与关闭 **/

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

{

int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);

if (shmid == -1)

err_exit("shmget error");

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

close(shmid);

}

2. 修改共享内存大小

[cpp] view
plaincopy





int ftruncate(int fd, off_t length);

该函数不仅可用于修改共享内存大小, 而且可以用于修改文件大小

[cpp] view
plaincopy





/** 示例: 修改共享内存大小

将其修改为一个Student结构体的大小

**/

struct Student

{

char name[32];

int age;

};

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

{

int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);

if (shmid == -1)

err_exit("shmget error");

if (ftruncate(shmid, sizeof(Student)) == -1)

err_exit("ftruncate error");

cout << "share memory change size success" << endl;

close(shmid);

}

3. 获取共享内存状态

[cpp] view
plaincopy





int fstat(int fd, struct stat *buf);

该函数不仅可用于获取共享内存状态, 而且可以用于获取文件状态, 与前面曾经讲述过的stat, lstat类型;

[cpp] view
plaincopy





//stat结构体

struct stat

{

dev_t st_dev; /* ID of device containing file */

ino_t st_ino; /* inode number */

mode_t st_mode; /* protection */

nlink_t st_nlink; /* number of hard links */

uid_t st_uid; /* user ID of owner */

gid_t st_gid; /* group ID of owner */

dev_t st_rdev; /* device ID (if special file) */

off_t st_size; /* total size, in bytes */

blksize_t st_blksize; /* blocksize for filesystem I/O */

blkcnt_t st_blocks; /* number of 512B blocks allocated */

time_t st_atime; /* time of last access */

time_t st_mtime; /* time of last modification */

time_t st_ctime; /* time of last status change */

};

[cpp] view
plaincopy





/** 示例: 获取共享内存的mode和size **/

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

{

int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);

if (shmid == -1)

err_exit("shmget error");

if (ftruncate(shmid, sizeof(Student)) == -1)

err_exit("ftruncate error");

struct stat buf;

if (fstat(shmid, &buf) == -1)

err_exit("lstat error");

// 注意: 获取权限时, 需要&上0777, 而且要以%o, 八进制方式打印

printf("mode: %o\n", buf.st_mode&0777);

printf("size: %ld\n", buf.st_size);

close(shmid);

}

4. 删除一个共享内存对象

[cpp] view
plaincopy





int shm_unlink(const char *name);

[cpp] view
plaincopy





//示例:

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

{

shm_unlink("/xyz");

}

5. 共享内存的映射/卸载

[cpp] view
plaincopy





#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

int munmap(void *addr, size_t length);

参数:

addr: 要映射的起始地址, 通常指定为NULL, 让内核自动选择;

length: 映射到进程地址空间的字节数, 通常是先前已经创建的共享内存的大小;

prot: 映射区保护方式(见下);

flags: 标志(通常指定为MAP_SHARED, 用于进程间通信);

fd: 文件描述符(填为shm_open返回的共享内存ID);

offset: 从文件头开始的偏移量(一般填为0);

prot
说明
PROT_READ
页面可读
PROT_WRITE
页面可写
PROC_EXEC
页面可执行
PROC_NONE
页面不可访问
flags
说明
MAP_SHARED
变动是共享的
MAP_PRIVATE
变动是私有的
MAP_FIXED
准确解释addr参数, 如果不指定该参数, 则会以4K大小的内存进行对齐
MAP_ANONYMOUS
建立匿名映射区, 不涉及文件
mmap返回值:

成功: 返回映射到的内存区的起始地址;

失败: 返回MAP_FAILED;

注意:mmap失败返回EACCES错误的原因:

EACCES A file descriptor refers to a non-regular file.

Or MAP_PRIVATE was requested, but fd is not open for reading.

Or MAP_SHARED was requested and PROT_WRITE is set, but fd is not open

in read/write (O_RDWR) mode. Or PROT_WRITE is set, but the file is append-only.

[cpp] view
plaincopy





/** 示例: 向共享内存写入数据 **/

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

{

int shmid = shm_open("/xyz", O_RDWR, 0);

if (shmid == -1)

err_exit("shm_open error");

struct stat buf;

if (fstat(shmid, &buf) == -1)

err_exit("fstat error");

Student *p = (Student *)mmap(NULL, buf.st_size,

PROT_WRITE, MAP_SHARED, shmid, 0);

if (p == MAP_FAILED)

err_exit("mmap error");

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

p->age = 5;

munmap(p, buf.st_size);

close(shmid);

}

[cpp] view
plaincopy





/** 从共享内存读出数据 **/

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

{

int shmid = shm_open("/xyz", O_RDONLY, 0);

if (shmid == -1)

err_exit("shm_open error");

struct stat buf;

if (fstat(shmid, &buf) == -1)

err_exit("fstat error");

Student *p = (Student *)mmap(NULL, buf.st_size,

PROT_READ, MAP_SHARED, shmid, 0);

if (p == MAP_FAILED)

err_exit("mmap error");

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

munmap(p, buf.st_size);

close(shmid);

}

[附]

-Posix共享内存默认创建在/dev/shm目录下

-可以使用od命令查看共享内存的内容

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