创建一个共享内存的步骤主要有两个:
1、创建共享内存段(shmget());
2、映射共享内存到进程中(shmat());
1、创建共享内存段:#include 、#include
int shmget(key_t key, sizi_t size, int flage);
成功返回共享内存ID,若出错返回-1;
key_t:是键的数据类型是定义在之中的长整形,键由内核变换成标识符。
unix之中有三种方式让不同的进程获取到一个共享内存的键值:
1、服务器通过制定的键IPC_PRIVATE创建一个新的IPC结构,将返回的标识符放在一个已存在的文件或者管道中以便客户进程取用。
缺点:服务进程要将整形标识符写到文件中,客户进程需要读取文件获取键值。
2、在一个公用头文件中定义一个客户进程和服务进程都认可的键。由服务进程指定此键创建一个新的IPC结构。
缺点:指定的键值可能已与一个IPC结构相结合,这种情况下,get函数(msgget、semget、shmget)出错返回。
3、客户进程和服务进程通过ftok函数创建键值。ftok将客户进程和服务进程都认同的路径名和项目ID(ID:1~255)两个值变换成一个键。
ftok函数:#include
key_t ftok(const char *path,int id);
ls -i 可以查看文件节点。
path必须为一个已经存在的现存文件。产生键时,只是用id参数的低8位。
如果两个路径名引用不同的文件,那么两个路径名调用ftok通常返回不同的键,但是如果使用同一个项目ID,那么对于不同文件的两个路径名可能产生相同的键值。
三种XSI IPC拥有两个类似的参数:一个key和一个整形的flag,满足下列两个条件之一,则创建一个新的IPC结构(通常由服务器进程创建):
1、key是IPC_PRIVATE;
2、key是当前未与特定类型的IPC结构相结合,并且flag中指定了IPC_CREAT位;
为了访问现存的队列(客户程序进行),key必须等于创建该队列时所指定的键,并且不应指定IPC_CREAT。IPC_PRIVATE作为一个特殊的键值,总是用于创建一个新的队列。
对于任何一个XSI IPC的IPC结构都有一个ipc_perm结构,该结构规定了权限和所有者。包含在#include之中,和文件调用中的chmod差不多,比如0666表示:用户可读可写,用户组用户可读可写,其他用户可读可写。可以通过(msgctl、semctl、shmctl)修改这些值。
size:为要创建共享内存的长度。通常为向上取系统页长的整数倍。如果size的值并非系统页长的整数倍,系统会为内存分配size最小整数倍,但是最后一页的余下部分是不可用的。如果正在引用一个现存的段,则将size指定为0。创建一个新段时,段内的内容初始化为0.
int flag:包括两个有效值:IPC_CREAT和IPC_EXCL:IPC_CREAT 如果共享内存不存在,则创建一个共享内存,否则打开操作。 IPC_EXCL 只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。 如果单独使用IPC_CREAT,shmget()函数要么返回一个已经存在的共享内存的操作符,要么返回一个新建的共享内存的标识符。如果将IPC_CREAT和IPC_EXCL标志一起使用,shmget()将返回一个新建的共享内存的标识符;如果该共享内存已存在,或者返回-1。IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证所得的对象是新建的,而不是打开已有的对象。
#define PERM S_IRUSR | S_IWUSR | IPC_CREAT
S_IRUSR:Permits the file's owner to read it.
S_IWUSR:Permits the file's owner to write to it.
S_IRGRP:Permits the file's group to read it.
S_IWGRP:Permits the file's group to write to it.
提供两个参考程序:在RHE5.5上调试通过,server程序创立共享内存,并写入hello world;client程序读取。
server程序:
#include
#include
#include
#include
#include
#include
#include
#include
#define PERM 0666 | IPC_CREAT //用户可读可写 创建共享内存段
int main(void)
{
long shmid=0;
char *s_addr;
char buf[1024];
key_t llv_key;
llv_key = ftok(".",1);
if(llv_key == -1)
{
perror("ftok");
exit(1);
}
printf("%x\n", llv_key);
if( (shmid=shmget( llv_key, 1024, PERM )) == -1)
{
printf("GET ID ERROR!\n");
exit(1);
}
printf("%ld\n",shmid);
s_addr = shmat(shmid,0,0);
memset(s_addr,'\0',1024);
strncpy(s_addr,"helloworld!",1024);
return 0;
}
client程序:
#include
#include
#include
#include
#include
#include
#include
#include
#define PERM S_IRUSR | S_IWUSR | IPC_CREAT //用户可读可写 创建共享内存段
int main(void)
{
int shmid;
char *c_addr;
key_t llv_key;
llv_key = ftok(".", 1);
if(llv_key == -1)
{
printf("can't creat the key!\n");
exit(1);
}
printf("%x\n", llv_key);
if( (shmid=shmget( llv_key, 1024, PERM )) == -1)
{
printf("GET ID ERROR!\n");
exit(1);
}
printf("%d\n",shmid);
c_addr = shmat(shmid,0,0);
printf("%s\n",c_addr);
return 0;
}
参考书:《UNIX 环境高级编程》