【Linux下】进程间通信( 四 )


目前作用:像命令行的命令一样干掉共享内存
shmid: 前面所说用户级别的标识符(函数的返回值)
cmd: 选项
buf: 通过这个 我们可以获取共享内存的大概信息(输出型参数)
**法二:使用指令 ipcrm **
ipcrm
作用:释放共享内存
格式:
ipcrm -m shmid
注:只有在挂接共享空间的进程数为零时 才能ipcrm 将共享内存释放掉
挂接和去挂接共享内存
shmat
作用:将进程与共享内存空间挂起链接 本质是:在进程的页表建立起虚拟地址和共享内存的映射关系
shmid: 前面所说用户级别的标识符,(的返回值)
:设置参数,目前只要使用NULL即可
: 同之前一样 是个参数 此处我们只需要用0即可
返回值:
就像我们c语言一样 返回的是虚拟地址,而我们操作共享内存,就像操作字符指针(指向字符数组)一样
例:
char *mem =(char*)shmat(shmid,NULL,0);
shmdt
作用:解挂起 本质是:在进程的页表去除虚拟地址和共享内存的映射关系
参数:就是我们上面获取的mem地址
例:
int dt=shmdt(mem);
内存空间特点即对比管道
特点:
1.内存空间是没有协同机制的 例:读端并不会等待写端写入才进行操作
2.内存空间是双向的,并没有区分写端读端,俩边皆可操作
3.内存空间读写效率更高,因为是直接对内存进行操作 (减少了调用系统接口(read,write),即少了俩次拷贝–拷贝到文件缓冲区)
4.内存空间的生命周期是随os的,所以只能使用命令或者通过进行操作(也是调用系统命令),而管道的生命周期是随进程的
key vs shmid
不同之处:
相同之处:
头文件代码:
#pragma once #include #include #include #include #include #define PATH_NAME "./"#define SIZE 4097#define PROJ_ID 0x6666
.c代码:
#include "com.h"int main(){//不需要再打开命名空间 只需要获取共享内存的标识号shimd 即可//获取底层的标识符key_t key=ftok(PATH_NAME,PROJ_ID);if(key<0){perror("ftok");return 1;}//获取shimd 命名空间标识符int shmid = shmget(key,SIZE,IPC_CREAT);//单独使用的作用是 没有创建值 存在则获取之printf("shmid:%d\n",shmid);if(shmid<0){perror("shmget");return 2;}//挂接共享内存char *mem =(char*)shmat(shmid,NULL,0);printf("process attach sucess!\n");//if(mem<0)//{//perror("shmat");//return 3;//}//操作char c='A';while(c<'Z'){mem[c-'A']=c;++c;mem[c-'A']=0;sleep(1);}//去挂接int dt=shmdt(mem);if(dt<0){return 4;}return 0;}
注:最后一个参数选项,创建共享内存时,一定要把权限设置好,不然是进行不了读写操作的
.c代码:
#include "com.h"#include int main(){key_t key=ftok(PATH_NAME,PROJ_ID);printf("key:%p\n",key);if(key<0){perror("ftok");return 1;}//如果我们的共享内存已经开辟出来了 就会返回-1 int shmid=shmget(key,SIZE,IPC_CREAT|IPC_EXCL|0666);//俩个选线一起用代表 如果该内存空间已经被人开辟了 即返回错误 若是没有被创建 即创建之 printf("shmid:%d\n",shmid);//sleep(10);//将内存空间与该进程挂起联系 建立起映射char *mem=(char*)shmat(shmid,NULL,0);printf("mem attach !\n");//操作while(1){sleep(1);printf("%s\n",mem); //对进程来说里面的内容就是长字符串}//去挂起int dt=shmdt(mem);if(dt<0){perror("shmdt");return 3;}//关闭内存空间int id=shmctl(shmid, IPC_RMID, NULL );if(id