• linux共享内存的使用


    linux共享内存和windows的共享内存逻辑上有很大区别,要注意一下几点

    1. shmget的第三个参数标识

    标识 描述
    IPC_EXCL 这个加入后,如果已经存在标识为key的共享内存则报错返回-1
    0 如果是0 的话,就可以实现,如果共享内存不存在则返回失败-1,否则直接创建返回成功
    0666 这个标识符很多人不知道啥意思,其实试试就知道了,它可以让你在普通用户下创建访问共享内存,如果没有这个标识,共享内存的创建和访问都必须在root用户下进行,参考《unix环境高级编程第二版》,里面有 #define SHM_MODE 0600 /* user read/write */

    2. 共享内存的回收

    共享内存想完全销毁,需要满足两个条件

    1. 应用计数为0,shmat/shmdt
    2. 标记为删除, shmctl
      如果引用计数不为0,你删除了,那么这个共享内存还在,还可以读取里面的值,但是共享内存的标记已经删除,所以后续程序无法打开,找不到共享内存
      如果引用计数为0,但是你没标记删除,那么共享内存标记和空间都还在,可以访问并读取内存,造成内存泄露,注意了

    3. 例子

    首先是创建共享内存

    /*
     File: sharemem.c
     Author: magicdmer
    */
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    int main()
    {
    	void *shm_addr = NULL;
    	int shmid;	
    	key_t key;
    
        key=ftok("/usr/local/ve-viewer",10);  
    	if(key==-1)  
    	{  
        	perror("ftok error
    ");  
        	return 0;  
    	} 
    
    	perror("shmid:%u
    ",key);  
        
        /*
          这里要注意了,IPC_EXCL这个的作用是:如果存在这个共享内存了就返回失败
          如果不加这个,会一直成功,会直接打开已有的
        */
    	shmid = shmget(key,1,IPC_CREAT|IPC_EXCL);
    	if (shmid == -1)
    	{
    		perror("shmget error
    ");
    		return 0;
    	}
    	
    	shm_addr = shmat(shmid, NULL, 0);
    	if (shm_addr == -1)
    	{
    		perror("shmat error
    ");
    		return 0;
    	}
    
    	memcpy(shm_addr,"Y",1);
    
    	getchar();
    
    	if (shmdt(shm_addr) == -1)
    	{
    		perror("shmdt error
    ");
    		return 0;
    	}
    
    	if (shmctl(shmid, IPC_RMID, 0) == -1)
        {
            perror("shmctl error!
    ");
    		return 0;
        }
    
    	return 0;
    }
    

    然后是读写共享内存

    /*
     File: sharemem.c
     Author: magicdmer
    */
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    int main()
    {
    	void *shm_addr = NULL;
    	int shmid;	
    	key_t key;
    
        key=ftok("/usr/local/ve-viewer",10);  
    	if(key==-1)  
    	{  
        	perror("ftok error
    ");  
        	return 0;  
    	} 
    
        
        //这里要注意了,最后一个flag设置成0,这样,如果共享内存不存在就会报错,不然即使没有也直接创建了
    	shmid = shmget(key,1,0);
    	if (shmid == -1)
    	{
    		perror("shmget error
    ");
    		return 0;
    	}
    
    	shm_addr = shmat(shmid, NULL, 0);
    	if (shm_addr == (void *)-1)
    	{
    		perror("shmat error!");
    		return 0;
    	}
    
    	char tmp[10];
    	bzero(tmp, 10);
    	memcpy(tmp,shm_addr,1);
    	printf("read from shared memory:%s
    ",tmp);
    	
    	getchar();
    	
    	bzero(tmp, 10);
    	memcpy(tmp,shm_addr,1);
    	printf("read from shared memory:%s
    ",tmp);
    
    	if (shmdt(shm_addr) == -1)
    	{
    		perror("shmdt error
    ");
    		return 0;
    	}
    
    }
    
  • 相关阅读:
    Python命名规范 Test
    MySQL学习总结之路(第七章:选择合适的数据类型)
    MySQL 遇到错误以及解决
    MySQL学习 配置执行日志记录
    SpringCloud Alibaba整合Sentinel
    Java对姓名, 手机号, 身份证号, 地址进行脱敏
    JSP页面button标签的id与onclick函数名字相同导致函数失效的问题
    mysql游标的使用:对查询的结果进行遍历
    基于SpringBoot+redis如何实现一个点赞功能?
    byte与str的相互转换
  • 原文地址:https://www.cnblogs.com/magicdmer/p/12792685.html
Copyright © 2020-2023  润新知