21、Posix共享内存
1、posix共享内存区涉及两个步骤:
1)指定一个名字参数调用shm_open,以创建一个新的共享内存区对象或打开一个以存在的共享内存区对象。
2)调用mmap把这个共享内存区映射到调用进程的地址空间。传递给shm_open的名字参数随后由希望共享该内存区的任何其他进程使用。
2、函数
(1)创建
#include <sys/mman.h>
int shm_open(const char *name,int oflag,mode_t mode);
1)name 共享内存区的名字
2)oflag 标志位
3)mode 权限位,它指定O_CREAT标志的前提下使用。
(2)删除
int shm_unlink(const char *name);
(3)调整大小
普通文件或共享内存区对象的大小都可以通过调用ftruncate修改。
int ftruncate(int fd,off_t length);
(4)查看状态
当打开一个已存在的共享内存区对象时,我们可调用fstat来获取有关该对象的信息。
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *file_name,struct stat *buf);
对于普通文件stat结构可以获得12个以上的成员信息,然而当fd指代一个共享内存区对象时,只有四个成员含有信息。
struct stat
{
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
off_t st_size;
};
g++ -g -o statt fstatt.cpp -lrt
3、示例
示例1
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
int main(int argc,char **argv)
{
int shm_id;
struct stat buf;
char *ptr;
if(argc!=2)
{
printf("usage:shm_open <pathname>\n");
exit(1);
}
shm_id=shm_open(argv[1],O_RDWR|O_CREAT,0644);/*创建共享内存区*/
ftruncate(shm_id,100);/*修改共享区大小*/
fstat(shm_id,&buf);
ptr=mmap(NULL,buf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,shm_id,0);/*连接共享内存区*/
strcpy(ptr,"hello linux");/*写入共享内存区*/
printf("%s\n",ptr);/*读出共享内存区*/
shm_unlink(argv[1]);/*删除共享内存区*/
}
示例2
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv)
{
int shm_id;
char *ptr;
sem_t *sem;
if(argc != 2)
{
printf("usage:shm_open <pathname>\n");
exit(1);
}
shm_id = shm_open(argv[1], O_RDWR, 0644);
sem = sem_open(argv[1], O_RDWR);
ptr = (char*)mmap(NULL,100,PROT_READ | PROT_WRITE, MAP_SHARED, shm_id, 0);
while(1)
{
sem_wait(sem);
fgets(ptr, 15, stdin);
printf("user:%s", ptr);
if((strcmp(ptr, "q\n")) == 0)
exit(0);
sem_post(sem);
sleep(1);
}
return (0);
}
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv)
{
int shm_id;
char *ptr;
sem_t *sem;
if(argc != 2)
{
printf("usage:shm_open <pathname>\n");
exit(1);
}
shm_id = shm_open(argv[1], O_RDWR | O_CREAT, 0644);
ftruncate(shm_id, 100);
sem = sem_open(argv[1], O_CREAT, 0644, 1);
ptr = (char*)mmap(NULL, 100, PROT_READ | PROT_WRITE, MAP_SHARED, shm_id, 0);
strcpy(ptr, "\0"); //清空共享内存区
while(1)
{
if((strcmp(ptr, "\0")) ==0)
{
continue;
}
else
{
if((strcmp(ptr, "q\n"))==0)
break;
sem_wait(sem);
printf("server:%s", ptr);
strcpy(ptr, "\0");
sem_post(sem);
}
sem_unlink(argv[1]);
shm_unlink(argv[1]);
}
}
g++ -o pw pshm_w.cpp -lrt
参考
【1】 http://linux.die.net/man/3/shm_open
【2】 非常不错的中文man
http://cpp.ezbty.org/import_doc/linux_manpage/shm_unlink.3.html