这里写目录标题
一 上一节的回顾
用 shmget 函数 创建了 共享内存
用 icps -m xxx 删除了指定的内存
二 上一节的补充
删除的是映射 为什么不是内核呢
映射的过程
相当于 内核的东西换了一个位置 输出 方便用户使用
节省了资源 删除也方便。
三 ftok shmget 函数配合生成的key值
name :文件名
int proj id :随机数字 (随意填1-65535)
key 为 ftok 的返回值
size :字节大小
shmflg:文件权限
#include<sys/shm.h>
#include<sys/types.h>
#include<stdio.h>
#include <sys/ipc.h>
#include<sys/msg.h>
int main()
{
int res;
int key;
key=ftok("key.c",1);
if(key<0)//出错
{
printf("error");
perror("why");
}
printf("ftok is sueecss ID is %d\n",key);
res=shmget(key,128,IPC_CREAT|0777);
if(res==-1)//出错
{
printf("error\n");
perror("***why:");
return -2;
}
printf("shmget is sueecss ID is %d\n",res);
return 0;
}
生成的id 都是固定的 方便血缘关系的通信 (固定概念)
四 shmat 函数
这个函数用下面的 关系图 就可以解释和证明他的用处了
1 以前 我们在用户态写缓存 满足 条件之后 是往 内核里面的 但是现在不用了
因为内核映射出了一个地址到了 用户态
2 用户态的进程组 直接调用系统函数 对映射操作
#include<sys/shm.h>
#include<sys/types.h>
#include<stdio.h>
#include <sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include <string.h>
int main()
{
int res;
int key;
char *p=(char*)malloc(1024);
key=ftok("key.c",1);
if(key<0)
{
printf("error");
perror("why");
}
printf("ftok is sueecss ID is %d\n",key);
res=shmget(key,128,IPC_CREAT|0777);
if(res==-1)
{
printf("error\n");
perror("***why:");
return -2;
}
printf("shmget is sueecss ID is %d\n",res);
p = (char *)shmat(res,(void *)NULL,0);
if(p==NULL)
{
printf("shamt is error\n");
perror("why");
return -5;
}
printf("sueecss\n");
fgets(p,128,stdin);//输入
printf("fgets is %s\n",p);//输出
return 0;
}
id :为shmget函数返回值
NULL:自动完成映射
0:可读写
如果是在读一次呢
#include<sys/shm.h>
#include<sys/types.h>
#include<stdio.h>
#include <sys/ipc.h>
#include<sys/msg.h>
int main()
{
int res;
int key;
char *p;
key=ftok("key.c",1);
if(key<0)
{
printf("error");
perror("why");
}
printf("ftok is sueecss ID is %d\n",key);
res=shmget(key,128,IPC_CREAT|0777);
if(res==-1)
{
printf("error\n");
perror("***why:");
return -2;
}
printf("shmget is sueecss ID is %d\n",res);
p = (char *)shmat(res,(void *)NULL,0);
if(p==NULL)
{
printf("shamt is error\n");
perror("why");
return -5;
}
printf("sueecss\n");
fgets(p,128,stdin);//输入
printf("one fgets is %s\n",p);//输出
printf("two fgets is %s\n",p);//输出
return 0;
}
能输出的原因
1 在创建的时候 会一直存在内核中 直到被删除或者系统关闭
2 共享内存和管道不一样 读取之后 内容不会消失
共享内存映射到用户态的根据
假设1
1 写一个printf("hello\n"); : 写满缓存它会进入内核态 然后输出
看看结束的形式
换行就结束了
共享内存的情况 (不进入内核态)
以空行结束
五 shmdt函数
函数指针可以存放指针
删除映射部分
实验证明
删除映射部分 之后 在读取 如果 出现段错误 证明删除成功
#include<sys/shm.h>
#include<sys/types.h>
#include<stdio.h>
#include <sys/ipc.h>
#include<sys/msg.h>
int main()
{
int res;
int key;
char *p;
key=ftok("key.c",1);
if(key<0)
{
printf("error");
perror("why");
}
printf("ftok is sueecss ID is %d\n",key);
res=shmget(key,128,IPC_CREAT|0777);
if(res==-1)
{
printf("error\n");
perror("***why:");
return -2;
}
printf("shmget is sueecss ID is %d\n",res);
p = (char *)shmat(res,(void *)NULL,0);
if(p==NULL)
{
printf("shamt is error\n");
perror("why");
return -5;
}
printf("sueecss\n");
fgets(p,128,stdin);//输入
printf("one fgets is %s\n",p);//输出
printf("two fgets is %s\n",p);//输出
shmdt((void*)p);//删除
printf("fgets is %s\n",p);//输出
return 0;
}
六 shmctl函数
主要看 第二个参数
删除指令 IPC_RMID 调用函数可以有两种方法实现删除命令 加上 icprm -m xxx (无需调用函数的 )一共三种
1 shmctl函数的使用第一种方法
参数配置
id:shmget返回值
command:IPC_RMID
buf :不指定 (NULL)
#include<sys/shm.h>
#include<sys/types.h>
#include<stdio.h>
#include <sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
int main()
{
int cv;
int res;
int key;
char *p;
key=ftok("key.c",1);
if(key<0)
{
printf("error");
perror("why");
}
printf("ftok is sueecss ID is %d\n",key);
res=shmget(key,128,IPC_CREAT|0777);
if(res==-1)
{
printf("error\n");
perror("***why:");
return -2;
}
printf("shmget is sueecss ID is %d\n",res);
p = (char *)shmat(res,(void *)NULL,0);
if(p==NULL)
{
printf("shamt is error\n");
perror("why");
return -5;
}
printf("sueecss\n");
fgets(p,128,stdin);//输入
printf("one fgets is %s\n",p);//输出
printf("two fgets is %s\n",p);//输出
shmdt(p);//删除
cv=shmctl(res,IPC_RMID,NULL);
if(cv==-1)
{
printf("error\n");
perror("!!why:");
return -2;
}
printf("shmctl is sueecss ID is %d\n");
return 0;
}
生成了它,查看不到 所以 删除成功
2 shmctl函数的使用第二种方法
使用main的形参实现
strmpy 字符串对比函数
参数 :一样的类型
0:就是相同
否则不同
#include<sys/shm.h>
#include<sys/types.h>
#include<stdio.h>
#include <sys/ipc.h>
#include<sys/msg.h>
#include <string.h>
int main(int argc,char *argv[])
{
int shmid;
int res;
char *p;
if(argc<2)
{
printf("argc is error");
return -2;
}
if(strcmp(argv[1],"-m")==0)
{
printf("two can is sueecss\n");
}
shmid=ator(argv[2]);
p= (char *)shmat(shmid,(void *)NULL,0);
fgets(p,128,stdin);
res=shmctl(shmid,IPC_RMID,NULL);
if(res==-1)
{
printf("shmctl is error\n");
perror("why");
retun -100;
}
printf("shmctl is sueecss\n");
return 0;
}
./a.out :argv[0]
-m : argv[1]
xxx:argv[2]
3 不使用shmctl函数第三种方法
方法 3 :ipcrm -m xxx
删除了 就不存在了