-
共享内存
共享内存是System V版本的一个进程间通信方式。
优点:共享内存是进程间通信最快的,因为它能减少进程间数据拷贝的次数。
缺点:共享内存不提供任何互斥或同步机制,这个过程由用户自己提供。
和共享内存相关函数的头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
-
共享内存函数
- 创建共享内存函数 shmget
int shmget(key_t key, size_t size, int shmflg);
作用:用来创建共享内存
key:共享内存名字,确保不同进程看到同一份IPC资源;其中key值的又由ftok函数创建:
key_t ftok(const char *pathname, int proj_id);
//pathname是key的路径名;id就是key值
size:共享内存的大小,共享内存的创建是以页为单位的,页的大小是4096k(4kb);
shmflag:有两个选项,分别是:IPC_CREAT和IPC_EXCL,这两个选项同时使用,会创建一个全新的共享内存,如果单独使用IPC_CREAT,创建成功,但是单独使用IPC_EXCL没有意义。
返回值:成功返回的是shmid,即共性内存的标识码,失败返回-1
- 建立映射函数 shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
作用:将共享内存连接到进程地址空间
shmid:标识共性内存的id
sdmaddr:指定链接的地址,一般默认为NULL
shmflag:它的两个可能取值是SHM_RND和SHM_RDONLY,但是这个参数,我们一般默认设置为0
返回值:成功返回一个指针,这个指针指向共享内存的第一个字节;失败返回-1
- 去链接函数 shmdt
int shmdt(const void *shmaddr);
作用:将共享内存与当前进程脱离
shmaddr:由shmat返回的指针
返回值:成功返回0;失败返回-1
需要注意的是:将共性内存与当前进程脱离不等于删除共享内存函数,它只是一个去链接的过程。
- 删除共性内存函数 shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
作用:用于控制(删除)共享内存
shmid:是shmget返回的共享内存标识码
cmd:将要采取的动作,有三个选项:IPC_STAT(把shnid_ds数据结构中的数据设置为共性内存的当前关联值);IPC_SET(在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值);IPC_PRID(删除共享内存)
buf:指向一个保存着共享内存的模式和访问权限的数据结构,通常设置为NULL
返回值:成功返回0,失败返回-1
-
使用共享内存进行进程间通信
server.c:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PN "."
#define PJ 0x4545
int main()
{
//使用ftok函数创建k值
key_t k = ftok(PN, PJ);
if (k<0)
{
printf("ftok error!\n");
return 1;
}
//创建共享内存
int shmid = shmget(k, 4098, IPC_CREAT | IPC_EXCL | 0666);
if (shmid<0)
{
perror("shmget");
return 2;
}
printf("%d\n", shmid);
sleep(5);
//建立挂接(映射)
char *str = (char*)shmat(shmid, NULL, 0);
//打印客户端发送过来的数据
int i = 0;
while (i++<26)
{
printf("client# %s\n", str);
sleep(1);
}
//去关联即将共享内存与当前进程脱离
shmdt(str);
sleep(5);
//删除共享内存
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
clientIpc.c:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PN "."
#define PJ 0x4545
int main()
{
//使用ftok函数创建k值
key_t k = ftok(PN, PJ);
if (k<0)
{
printf("ftok error!\n");
return 1;
}
//创建共享内存
int shmid = shmget(k, 4098, IPC_CREAT);
if (shmid<0)
{
perror("shmget");
return 2;
}
printf("%d\n", shmid);
//建立挂接(映射)
char *str = (char*)shmat(shmid, NULL, 0);
sleep(1);
//写入数据
int i = 0;
while (i<26)
{
str[i] = 'A' + i;
i++;
str[i] = 0;
sleep(1);
}
//去关联
shmdt(str);
sleep(5);
//删除共享内存
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
makefile:
.PHONY:all
all : server clientIpc
server : server.c
gcc - o $@ $^
clientIpc:clientIpc.c
gcc - o $@ $^
.PHONY:clean
clean :
rm - f server clientIpc
程序执行结果: