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

1. 创建/获取一个共享内存

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <sys/mman.h>  
  2. #include <sys/stat.h>        /* For mode constants */  
  3. #include <fcntl.h>           /* For O_* constants */  
  4. 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 plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 示例: 共享内存的打开与关闭 **/  
  2. int main(int argc,char *argv[])  
  3. {  
  4.     int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);  
  5.     if (shmid == -1)  
  6.         err_exit("shmget error");  
  7.   
  8.     cout << "share memory open success" << endl;  
  9.     close(shmid);  
  10. }  

2. 修改共享内存大小

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int ftruncate(int fd, off_t length);  

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 示例: 修改共享内存大小 
  2. 将其修改为一个Student结构体的大小 
  3. **/  
  4. struct Student  
  5. {  
  6.     char name[32];  
  7.     int age;  
  8. };  
  9. int main(int argc,char *argv[])  
  10. {  
  11.     int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);  
  12.     if (shmid == -1)  
  13.         err_exit("shmget error");  
  14.     if (ftruncate(shmid, sizeof(Student)) == -1)  
  15.         err_exit("ftruncate error");  
  16.   
  17.     cout << "share memory change size success" << endl;  
  18.     close(shmid);  
  19. }  

3. 获取共享内存状态

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int fstat(int fd, struct stat *buf);  

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //stat结构体  
  2. struct stat  
  3. {  
  4.     dev_t     st_dev;     /* ID of device containing file */  
  5.     ino_t     st_ino;     /* inode number */  
  6.     mode_t    st_mode;    /* protection */  
  7.     nlink_t   st_nlink;   /* number of hard links */  
  8.     uid_t     st_uid;     /* user ID of owner */  
  9.     gid_t     st_gid;     /* group ID of owner */  
  10.     dev_t     st_rdev;    /* device ID (if special file) */  
  11.     off_t     st_size;    /* total size, in bytes */  
  12.     blksize_t st_blksize; /* blocksize for filesystem I/O */  
  13.     blkcnt_t  st_blocks;  /* number of 512B blocks allocated */  
  14.     time_t    st_atime;   /* time of last access */  
  15.     time_t    st_mtime;   /* time of last modification */  
  16.     time_t    st_ctime;   /* time of last status change */  
  17. };  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 示例: 获取共享内存的mode和size **/  
  2. int main(int argc,char *argv[])  
  3. {  
  4.     int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);  
  5.     if (shmid == -1)  
  6.         err_exit("shmget error");  
  7.     if (ftruncate(shmid, sizeof(Student)) == -1)  
  8.         err_exit("ftruncate error");  
  9.   
  10.     struct stat buf;  
  11.     if (fstat(shmid, &buf) == -1)  
  12.         err_exit("lstat error");  
  13.     // 注意: 获取权限时, 需要&上0777, 而且要以%o, 八进制方式打印  
  14.     printf("mode: %o\n", buf.st_mode&0777);  
  15.     printf("size: %ld\n", buf.st_size);  
  16.   
  17.     close(shmid);  
  18. }  

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int shm_unlink(const char *name);  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //示例:   
  2. int main(int argc,char *argv[])  
  3. {  
  4.     shm_unlink("/xyz");  
  5. }  

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <sys/mman.h>  
  2. void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);  
  3. 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 plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 示例: 向共享内存写入数据 **/  
  2. int main(int argc,char *argv[])  
  3. {  
  4.     int shmid = shm_open("/xyz", O_RDWR, 0);  
  5.     if (shmid == -1)  
  6.         err_exit("shm_open error");  
  7.   
  8.     struct stat buf;  
  9.     if (fstat(shmid, &buf) == -1)  
  10.         err_exit("fstat error");  
  11.     Student *p = (Student *)mmap(NULL, buf.st_size,  
  12.                                  PROT_WRITE, MAP_SHARED, shmid, 0);  
  13.     if (p == MAP_FAILED)  
  14.         err_exit("mmap error");  
  15.     strcpy(p->name, "Hadoop");  
  16.     p->age = 5;  
  17.   
  18.     munmap(p, buf.st_size);  
  19.     close(shmid);  
  20. }  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 从共享内存读出数据 **/  
  2. int main(int argc,char *argv[])  
  3. {  
  4.     int shmid = shm_open("/xyz", O_RDONLY, 0);  
  5.     if (shmid == -1)  
  6.         err_exit("shm_open error");  
  7.   
  8.     struct stat buf;  
  9.     if (fstat(shmid, &buf) == -1)  
  10.         err_exit("fstat error");  
  11.     Student *p = (Student *)mmap(NULL, buf.st_size,  
  12.                                  PROT_READ, MAP_SHARED, shmid, 0);  
  13.     if (p == MAP_FAILED)  
  14.         err_exit("mmap error");  
  15.   
  16.     cout << "name: " << p->name << ", age: " << p->age << endl;  
  17.   
  18.     munmap(p, buf.st_size);  
  19.     close(shmid);  
  20. }  

[附]

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

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

od -c /dev/shm/xyz

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值