精华内容
下载资源
问答
  • 易语言读写共享内存例程源码,读写共享内存例程,CreateFileMappingA,MapViewOfFile,UnmapViewOfFile,CloseHandle,OpenFileMappingA
  • 此包含了共享内存读源代码和写源代码的两个程序,可以方便您用此两个程序进行两个进程的通信
  • 共享内存

    千次阅读 2018-09-19 15:38:10
     共享内存是在两个正在运行的进程之间传递数据的一种非常有效的方式。共享内存的具体实现是不同进程共享的内存安排为同一段物理地址。  如上图所示,进程A和进程B共享同一块物理内存,共享内存中的数据进程A和...

    一、定义

      共享内存是在两个正在运行的进程之间传递数据的一种非常有效的方式。共享内存的具体实现是不同进程共享的内存安排为同一段物理地址。

        如上图所示,进程A和进程B共享同一块物理内存,共享内存中的数据进程A和进程B均可进行相关操作,这样便可达到两个进程之间数据传递的目的。

    二、相关函数

    1、shm函数(创建共享内存)

    函数声明:

    int shmget(key_t ey,size_t size, int shmflg);
    第一个参数key:为共享内存段命名,有一个特殊的键值IPC_PRIVATE,用于创建一个只属于创建进程的共享内存
    第二个参数size:是共享内存的大小(字节数)
    第三个参数shmflg:包含9个比特的权限标志,作用同文件操作是的mode标志位相同
    返回值:函数执行成功返回一个非负整数,即内存标识符,失败时返回-1.
    

    2、shmat函数(将共享内存连接到进程)

       第一次创建共享内存段,该共享内存段并不能被任何进程所使用,只有当共享内存被连接到一个进程,才可以访问共享内存,这个功能由shmat函数实现。

    函数声明:

    void *shmat(int shm_id, const oid *shm_addr, int shmflg);
    第一个参数:所要连接的共享内存标识符。
    第二个参数:指定共享内存连接到当前进程的地址位置,一般传NULL,表示由系统选择共享内存连接的位置。
    第三个参数:可取SHM_RND和SHM_RDONLY(使得连接的内存地址只读)
    返回值:函数执行成功返回共享内存的首地址,失败返回-1

    3、shmdt函数(分离共享内存)

    该函数的参数是shmat函数返回的共享内存地址指针,成功返回0,失败返回-1.

    4、shmctl(控制函数)

    函数声明:

    int shmctl(int shm_id, int command, struct shmid_ds *buf);
    第一个参数:共享内存标识符
    第二个参数://要采取的动作,有如下取值:
                 IPC_STAT:把shm_ds结构中的数据设置为共享内存的当前关联值
                 IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构体中的值
                 IPC_RMID:删除共享内存。
    第三个参数:buf是一个指针,指向包含共享内存模式和访问权限的结构
    返回值:成功返回0失败返回-1.
    struct shmid_ds
    {
        uid_t shm_perm.uid;   
        uid_t shm_perm.gid;    
        mode_t shm_perm.mode;    
    }
    

    三、实例

       共享内存和信号量同时使用会使得程序效率更加显著,以下代码实现了一个进程往共享内存里输入数据,并一个进程从共享内存里读取数据,并且只有当写进程写入之后读进程才可读取,不可重复读取相同的数据。

    sem.h

    # include<unistd.h>
    # include<sys/sem.h>
    
    union semun
    {
    	int val;
    };
    
    void sem_init();
    void sem_p();
    void sem_v();
    void sem_destory();

    sem.c

    # include<stdio.h>
    # include<error.h>
    # include"sem.h"
    
    static int semid = -1;
    
    void sem_init()
    {
    	semid = semget((key_t)1234,1,IPC_CREAT | IPC_EXCL | 0600);
    	if(semid == -1)
    	{
    		semid = semget((key_t)1234, 1, 0600);
    		if(semid == -1)
    		{
    			perror("semget error\n");
    		}
    	}
    	else
    	{
    		union semun a;
    		a.val = 0;
    
    		if(semctl(semid,0,SETVAL,a) == -1)
    		{
    			perror("semctl setval error\n");
    		}
    	}
    }
    void sem_p()
    {
    	struct sembuf buf;
    	buf.sem_num = 0;
    	buf.sem_op = -1;
    	buf.sem_flg = SEM_UNDO;
    
    	if(semop(semid, &buf, 1) == -1)
    	{
    		perror("semop seeoe\n");
    	}
    }
    void sem_v()	
    {
    	struct sembuf buf;
    	buf.sem_num = 0;
    	buf.sem_op = 1;
    	buf.sem_flg = SEM_UNDO;
    
    	if(semop(semid, &buf, 1) == -1)
    	{
    		perror("semop seeoe\n");
    	}
    }
    void sem_destory()
    {
    	if(semctl(semid,0,IPC_RMID) == -1)
    	{
    		perror("semctl error\n");
    	}
    }

    shmwrite.c

    # include<stdio.h>
    # include<stdlib.h>
    # include<assert.h>
    # include<sys/shm.h>
    # include<string.h>
    # include"sem.h"
    
    int main()
    {
    	sem_init();
    	int shmid = shmget((key_t)1234, 256,IPC_CREAT|0600);
    	assert(shmid != -1);
    
    	char *s = (char *)shmat(shmid, NULL, 0);
    
    	while(1)
    	{
    		char buf[128] = {0};
    		printf("input:\n");
    		fgets(buf, 128, stdin);
    		strcpy(s,buf);
            sem_v();
    		if(strncmp(buf, "end", 3) == 0)
    		{
    			break;
    		}
    	}
    	shmdt(s);
    	exit(0);
    }

    shmread.c

    # include<stdio.h>
    # include<stdlib.h>
    # include<string.h>
    # include<sys/shm.h>
    # include<assert.h>
    # include"sem.h"
    
    int main()
    {
    	sem_init();
    	int shmid = shmget((key_t)1234, 256, IPC_CREAT | 0600);
    	assert(shmid != -1);
    	char *p = (char *)shmat(shmid,NULL,0);
    
    	while(1)
    	{
            sem_p();
    		if(strncmp(p,"end",3) == 0)
    		{
    			break;
    		}
    		printf("%s\n",p);
    		sleep(1);
    	}
    	shmdt(p);
    	sem_destory();
    	shmctl(shmid, IPC_RMID, NULL);
    	exit(0);
    }

     

    展开全文
  • 创建一个共享内存 #include #include #include #include #include #include #include #include #include #include #include int main(int arg, char *args[]) { int shmid = shmget(IPC_PRIVATE, 1024,...

    创建一个共享内存

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    int main(int arg, char *args[])
    {
    	int shmid = shmget(IPC_PRIVATE, 1024, 0666);
    	if (shmid < 0)
    	{
    		printf("error\n");
    	} else
    	{
    		printf("succes\n");
    	}
    
    	shmat(shmid, NULL, )
    
    	return EXIT_SUCCESS;
    }
    然后使用这个共享内存

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/shm.h>
    int main(int arg, char *args[])
    {
    	char *shmbuf;
    	int shmid = 0;
    	if (arg > 2)
    	{
    		shmid = atoi(args[1]);
    		shmbuf = shmat(shmid, 0, 0);
    		if (atoi(args[2]) == 1)
    		{
    			scanf("%s", shmbuf);
    		}
    		if (atoi(args[2]) == 2)
    		{
    			printf("%s\n", shmbuf);
    		}
    		shmdt(shmbuf);
    	}
    	return 0;
    }
    



    展开全文
  • L_重复运行,L_写共享内存,L_读共享内存,检测内存,Z_共享内存_CreateFileMappingA,Z_共享内存_OpenFileMappingA,Z_共享内存_MapViewOfFile,Z_共享内存_CloseHandle,Z_共享内存_UnmapViewOfFile,Z_共享内存_拷贝内存_...
  • 易语言重复运行检测共享内存方式源码,L_重复运行,L_写共享内存,L_读共享内存,检测内存,Z_共享内存_CreateFileMappingA,Z_共享内存_OpenFileMappingA,Z_共享内存_MapViewOfFile,Z_共享内存_CloseHandle,Z_共享内存_...
  • linux 共享内存与nginx共享内存

    千次阅读 2014-03-12 13:37:04
    共享内存的实现分为两个步骤: 一、 创建共享内存,使用shmget函数。 二、 映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数。 创建共享内存 int shmget(key_t key ,int size,int ...

    共享内存的实现分为两个步骤:

    一、 创建共享内存,使用shmget函数。

    二、 映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数。

    创建共享内存

    int shmget(key_t key ,int size,int shmflg)

    key标识共享内存的键值:0/IPC_PRIVATE。当key的取值为IPC_PRIVATE,则函数shmget将创建一块新的共享内存;如果key的取值为0,而参数中又设置了IPC_PRIVATE这个标志,则同样会创建一块新的共享内存。

    返回值:如果成功,返回共享内存表示符,如果失败,返回-1。

    映射共享内存

    int shmat(int shmid,char *shmaddr,int flag)

    参数:

    shmid:shmget函数返回的共享存储标识符

    flag:决定以什么样的方式来确定映射的地址(通常为0)

    返回值:

    如果成功,则返回共享内存映射到进程中的地址;如果失败,则返回-1。

    共享内存解除映射

    当一个进程不再需要共享内存时,需要把它从进程地址空间中多里。

    int shmdt(char *shmaddr)

    贡献内存实例如下:

    实验要求:创建两个进程,在A进程中创建一个共享内存,并向其写入数据,通过B进程从共享内存中读取数据。

    chm_com.h函数

    1. #define TEXT_SZ 2048   
    2.   
    3. struct shared_use_st  
    4. {  
    5.     int written_by_you;  
    6.     char some_text[TEXT_SZ];  
    7. };  
    #define TEXT_SZ 2048
    
    struct shared_use_st
    {
        int written_by_you;
    	char some_text[TEXT_SZ];
    };
    
    


    读取进程:

    1. /********************************************************** 
    2. *实验要求:   创建两个进程,通过共享内存进行通讯。 
    3. *功能描述:   本程序申请和分配共享内存,然后轮训并读取共享中的数据,直至 
    4. *           读到“end”。 
    5. *日    期:   2010-9-17 
    6. *作    者:   国嵌 
    7. **********************************************************/  
    8. #include <unistd.h>   
    9. #include <stdlib.h>   
    10. #include <stdio.h>   
    11. #include <string.h>   
    12. #include <sys/types.h>   
    13. #include <sys/ipc.h>   
    14. #include <sys/shm.h>   
    15. #include "shm_com.h"   
    16.   
    17. /* 
    18.  * 程序入口 
    19.  * */  
    20. int main(void)  
    21. {  
    22.     int running=1;  
    23.     void *shared_memory=(void *)0;  
    24.     struct shared_use_st *shared_stuff;  
    25.     int shmid;  
    26.     /*创建共享内存*/  
    27.     shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);  
    28.     if(shmid==-1)  
    29.     {  
    30.         fprintf(stderr,"shmget failed\n");  
    31.         exit(EXIT_FAILURE);  
    32.     }  
    33.   
    34.     /*映射共享内存*/  
    35.     shared_memory=shmat(shmid,(void *)0,0);  
    36.     if(shared_memory==(void *)-1)  
    37.     {  
    38.         fprintf(stderr,"shmat failed\n");  
    39.         exit(EXIT_FAILURE);  
    40.     }  
    41.     printf("Memory attached at %X\n",(int)shared_memory);  
    42.   
    43.     /*让结构体指针指向这块共享内存*/  
    44.     shared_stuff=(struct shared_use_st *)shared_memory;  
    45.   
    46.     /*控制读写顺序*/  
    47.     shared_stuff->written_by_you=0;  
    48.     /*循环的从共享内存中读数据,直到读到“end”为止*/  
    49.     while(running)  
    50.     {  
    51.        if(shared_stuff->written_by_you)  
    52.        {  
    53.            printf("You wrote:%s",shared_stuff->some_text);  
    54.            sleep(1);  //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写   
    55.            shared_stuff->written_by_you=0;  
    56.            if(strncmp(shared_stuff->some_text,"end",3)==0)  
    57.            {  
    58.                running=0; //结束循环   
    59.            }  
    60.        }  
    61.     }  
    62.     /*删除共享内存*/  
    63.     if(shmdt(shared_memory)==-1)  
    64.     {  
    65.         fprintf(stderr,"shmdt failed\n");  
    66.         exit(EXIT_FAILURE);  
    67.     }  
    68.        exit(EXIT_SUCCESS);  
    69. }  
    /**********************************************************
    *实验要求:   创建两个进程,通过共享内存进行通讯。
    *功能描述:   本程序申请和分配共享内存,然后轮训并读取共享中的数据,直至
    *           读到“end”。
    *日    期:   2010-9-17
    *作    者:   国嵌
    **********************************************************/
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include "shm_com.h"
    
    /*
     * 程序入口
     * */
    int main(void)
    {
        int running=1;
    	void *shared_memory=(void *)0;
    	struct shared_use_st *shared_stuff;
    	int shmid;
    	/*创建共享内存*/
    	shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
    	if(shmid==-1)
    	{
    	    fprintf(stderr,"shmget failed\n");
    		exit(EXIT_FAILURE);
    	}
    
    	/*映射共享内存*/
    	shared_memory=shmat(shmid,(void *)0,0);
    	if(shared_memory==(void *)-1)
    	{
    	    fprintf(stderr,"shmat failed\n");
    		exit(EXIT_FAILURE);
    	}
    	printf("Memory attached at %X\n",(int)shared_memory);
    
    	/*让结构体指针指向这块共享内存*/
    	shared_stuff=(struct shared_use_st *)shared_memory;
    
    	/*控制读写顺序*/
    	shared_stuff->written_by_you=0;
    	/*循环的从共享内存中读数据,直到读到“end”为止*/
    	while(running)
    	{
    	   if(shared_stuff->written_by_you)
    	   {
    	       printf("You wrote:%s",shared_stuff->some_text);
    		   sleep(1);  //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写
    		   shared_stuff->written_by_you=0;
    		   if(strncmp(shared_stuff->some_text,"end",3)==0)
    		   {
    		       running=0; //结束循环
    		   }
    	   }
    	}
    	/*删除共享内存*/
    	if(shmdt(shared_memory)==-1)
    	{
    	    fprintf(stderr,"shmdt failed\n");
    	    exit(EXIT_FAILURE);
    	}
           exit(EXIT_SUCCESS);
    }
    
    


    写入进程:

    1. /********************************************************** 
    2. *实验要求:   创建两个进程,通过共享内存进行通讯。 
    3. *功能描述:   本程序申请了上一段程序相同的共享内存块,然后循环向共享中 
    4. *           写数据,直至写入“end”。 
    5. *日    期:   2010-9-17 
    6. *作    者:   国嵌 
    7. **********************************************************/  
    8. #include <unistd.h>   
    9. #include <stdlib.h>   
    10. #include <stdio.h>   
    11. #include <string.h>   
    12. #include <sys/types.h>   
    13. #include <sys/ipc.h>   
    14. #include <sys/shm.h>   
    15. #include "shm_com.h"   
    16.   
    17. /* 
    18.  * 程序入口 
    19.  * */  
    20. int main(void)  
    21. {  
    22.     int running=1;  
    23.     void *shared_memory=(void *)0;  
    24.     struct shared_use_st *shared_stuff;  
    25.     char buffer[BUFSIZ];  
    26.     int shmid;  
    27.     /*创建共享内存*/  
    28.     shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);  
    29.     if(shmid==-1)  
    30.     {  
    31.         fprintf(stderr,"shmget failed\n");  
    32.         exit(EXIT_FAILURE);  
    33.     }  
    34.   
    35.     /*映射共享内存*/  
    36.     shared_memory=shmat(shmid,(void *)0,0);  
    37.     if(shared_memory==(void *)-1)  
    38.     {  
    39.         fprintf(stderr,"shmat failed\n");  
    40.         exit(EXIT_FAILURE);  
    41.     }  
    42.     printf("Memory attached at %X\n",(int)shared_memory);  
    43.   
    44.     /*让结构体指针指向这块共享内存*/  
    45.     shared_stuff=(struct shared_use_st *)shared_memory;  
    46.     /*循环的向共享内存中写数据,直到写入的为“end”为止*/  
    47.     while(running)  
    48.     {  
    49.         while(shared_stuff->written_by_you==1)  
    50.         {  
    51.             sleep(1);//等到读进程读完之后再写   
    52.             printf("waiting for client...\n");  
    53.         }  
    54.         printf("Ener some text:");  
    55.         fgets(buffer,BUFSIZ,stdin);  
    56.         strncpy(shared_stuff->some_text,buffer,TEXT_SZ);  
    57.         shared_stuff->written_by_you=1;  
    58.         if(strncmp(buffer,"end",3)==0)  
    59.         {  
    60.             running=0;  //结束循环   
    61.         }  
    62.     }  
    63.     /*删除共享内存*/  
    64.     if(shmdt(shared_memory)==-1)  
    65.     {  
    66.         fprintf(stderr,"shmdt failed\n");  
    67.         exit(EXIT_FAILURE);  
    68.     }  
    69.     exit(EXIT_SUCCESS);  
    70. }  
    /**********************************************************
    *实验要求:   创建两个进程,通过共享内存进行通讯。
    *功能描述:   本程序申请了上一段程序相同的共享内存块,然后循环向共享中
    *           写数据,直至写入“end”。
    *日    期:   2010-9-17
    *作    者:   国嵌
    **********************************************************/
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include "shm_com.h"
    
    /*
     * 程序入口
     * */
    int main(void)
    {
        int running=1;
    	void *shared_memory=(void *)0;
    	struct shared_use_st *shared_stuff;
    	char buffer[BUFSIZ];
    	int shmid;
    	/*创建共享内存*/
    	shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
    	if(shmid==-1)
    	{
    	    fprintf(stderr,"shmget failed\n");
    		exit(EXIT_FAILURE);
    	}
    
    	/*映射共享内存*/
    	shared_memory=shmat(shmid,(void *)0,0);
    	if(shared_memory==(void *)-1)
    	{
    	    fprintf(stderr,"shmat failed\n");
    		exit(EXIT_FAILURE);
    	}
    	printf("Memory attached at %X\n",(int)shared_memory);
    
    	/*让结构体指针指向这块共享内存*/
    	shared_stuff=(struct shared_use_st *)shared_memory;
    	/*循环的向共享内存中写数据,直到写入的为“end”为止*/
    	while(running)
    	{
    	    while(shared_stuff->written_by_you==1)
    		{
    		    sleep(1);//等到读进程读完之后再写
    			printf("waiting for client...\n");
    		}
    		printf("Ener some text:");
    		fgets(buffer,BUFSIZ,stdin);
    		strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
    		shared_stuff->written_by_you=1;
    		if(strncmp(buffer,"end",3)==0)
    		{
    		    running=0;  //结束循环
    		}
    	}
    	/*删除共享内存*/
    	if(shmdt(shared_memory)==-1)
    	{
    	    fprintf(stderr,"shmdt failed\n");
    		exit(EXIT_FAILURE);
    	}
    	exit(EXIT_SUCCESS);
    }
    
    

    3 . 在一个终端中运行shm1,在另一个终端中运行shm2.当shm1运行起来之后,由于共享内存中没有数据可读,会处于等待状态

    [root@localhost 2-4-4]# ./shm1

    Memory attached at B7F9A000

    /***阻塞***/

    再向shm2运行的终端输入字符串

    [root@localhost 2-4-4]# ./shm2

    Memory attached at B7FD8000

    Enter some text:Impossible is nothing

    waiting for client。。。

    waiting for client。。。

    Enter some text:Anything is possible

    waiting for client。。。

    Ener some text:end

    [root@localhost 2-4-4]#

    shm1能够逐个从共享内存中巴他们读出来,知道双方晕倒字符串"end"后,两个程序都退出。

    [root@localhost 2-4-4]# ./shm1

    Memory attached at B7F9A000

    You write:Impossible is nothing

    You write:Anything is possible

    You write:end

    [root@localhost 2-4-4]#

    以上运行过程中,红色表示在终端1中运行的结果,蓝色表示在终端2里面运行的结果。



    展开全文
  • linux内核支持多种共享内存方式,如mmap内存映射,Posix共享内存,以system V共享内存。当内核空间和用户空间存在大量数据交互时,共享内存映射就成了这种情况下的不二选择。它能够最大限度的降低内核空间和用户空间...

    linux内核支持多种共享内存方式,如mmap内存映射,Posix共享内存,以system V共享内存。当内核空间和用户空间存在大量数据交互时,共享内存映射就成了这种情况下的不二选择。它能够最大限度的降低内核空间和用户空间之间的数据拷贝,从而大大提高系统的性能。

    共享内存是最有用,也是最快的IPC方式。两个不同进程A、B共享内存时,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。

    内存映射,简而言之就是将用户空间的一段内存区域(即进程地址空间的内存映射段,其位于堆空间和栈空间之间)映射到内核空间,映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,同样,内核空间对这段区域的修改也直接反映用户空间,那么对于内核空间和用户空间两者之间需要大量数据传输等操作的话效率是非常高的。对于Posix共享内存和system V共享内存一样,在地址空间处于内存映射段,物理内存处于内核区。因此,这三种方式都不需要内核区与用户区进行数据的交换,效率更高,通过指针的方式可以直接对内存进行访问。对于大数据的内存访问,一般来说在Linux系统中采用内存映射和共享内存是最好的方式,这样对于应用层来说,可以很方便的访问到内核的空间。

    mmap内存映射

    mmap内存映射的方式分为两种:文件映射(一般文件或者/dev/zero文件)和匿名映射。文件映射,是指该地址空间(内存映射段)的内容来自于一个文件;而匿名映射地址空间背后什么靠山都没有。进程的代码段来自于镜像,采用文件映射方式;而栈,堆,.bss段,数据段均是匿名映射。

    下图是文件映射的示意图(映射文件的一部分):

    off为偏移大小,len为映射区的大小。

    mmap函数是unix和类unix下的系统调用,其系统调用接口为:void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);   mmap内存映射的作用有二:1.用于共享内存,完成IPC;2.提供了不同于一般访问文件的方式,如系统函数(read和write等)、C库函数(printf、scanf等),由于其不需要内核空间与用户空间的数据拷贝,因此效率会更高。使得访问文件类似于直接访问内存一样,直接用指针就可以操作文件。Posixsystem V的共享内存IPC则纯粹用于共享目的,当然mmap实现共享内存也是其主要应用之一。

    mmap内存映射并不分配空间,只是将文件映射到调用进程的地址空间里(但是会占掉你的 virutal memory),然后你就可以用memcpy等操作写文件,而不用write了。写完后,内存中的内容并不会立即更新到文件中,而是有一段时间的延迟,你可以调用msync来显式同步一下, 这样你所写的内容就能立即保存到文件里了。不过通过mmap来写文件这种方式没办法增加文件的长度,因为要映射的长度在调用mmap的时候就决定了。

    在内存映射的过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上被放入了地址空间的内存映射段。在用指针实际访问的时候,逻辑地址加上基地址形成的线性地址经过MMU映射成为物理地址,此时会检测到访问的文件不在内存,从而通过缺页中断请求的方式,才将其调入内存,并同时修改页表和快表,此时才真正调入到内存。即MMU完成了地址的变换(变换后的信息存储在PCB中)、缺页中断、调页请求等。缺页中断的中断响应函数会在swap中寻找相对应的页面,如果找不到(也就是该文件从来没有被读入内存的情况),则会通过mmap建立的映射关系,从硬盘上将文件读取到物理内存中。如果在拷贝数据时,发现物理内存不够用,则会通过虚拟内存机制(swap)将暂时不用的物理页面交换到硬盘上。

    比较:mmapC库函数、系统函数、管道和消息队列

    用户进程通过系统调用访问系统资源(如访问文件)时需要切换到内核态,而这对应一些特殊的堆栈和内存环境,必须在系统调用前建立好。在系统调用后,CPU会从内核态转换到用户态,而堆栈又必须恢复成用户进程的上下文,这种切换会消耗大量的系统时间。在用户态,不仅仅是系统资源,位于其它进程空间的资源都是看不到的(透明的),因此在切换到用户态时,需要将系统调用访问的资源拷贝到用户空间,才能被用户空间进行操作,用户态是没有权限对内核进行操作的。

    read、write等系统函数访问文件时,都是先将外部设备上的数据读到内核缓冲区,然后将内核的数据交到用户缓冲区,然后用户进程就可以通过用户缓冲区来使用这些数据了。printf等C库函数一样,它们的唯一区别就是,C库函数有自己维护的I/O缓冲区(8KB),而系统函数需要自己指定缓冲区buff。C库函数对文件的访问,最终也是通过read和write等系统函数来完成的。但由于其I/O缓冲区(无缓冲、行缓冲和全缓冲)比较大,因此较少了内核与用户的交互次数,从而一般比系统函数访问速度会更快,但是系统函数可以通过指定buff的大小大于I/O缓冲区的大小,使其效率比C库函数更高,它们的原理一样的。 综上,内核缓冲区是为了减少操作磁盘等外部设备的次数,缓解CPU的速度与外部设备速度之间的不匹配;而I/O缓冲区是为了减少系统调用的次数。

    采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝(读文件read、再write到管道一端、再从管道另一端read、最后再write到外部文件),而共享内存则只拷贝两次数据。一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。

    内核将硬盘文件的内容直接映射到内存, 任何应用程序都可通过Linux的mmap()系统调用请求这种映射。内存映射是一种方便高效的文件I/O方式, 因而被用于装载动态共享库。如C标准库函数(fread、fwrite、fopen等)和Linux系统I/O函数,它们都是动态库函数,其中C标准库函数都被封装在了/lib/libc.so库文件中,都是二进制文件。这些动态库函数都是与位置无关的代码,即每次被加载进入内存映射区时的位置都是不一样的,因此使用的是其本身的逻辑地址,经过变换成线性地址(虚拟地址),然后再映射到内存。而静态库不一样,由于静态库被链接到可执行文件中,因此其位于代码段,每次在地址空间中的位置都是固定的。

    system V共享内存

    共享内存就是多个进程的地址空间映射到同一个物理内存,多个进程都能看到这块物理内存,共享内存可以提供给服务器进程和客户进程之间进行通信,不需要进行数据的复制,所以速度最快。

    共享内存操作需要的函数:

    1.我们需要利用ftok函数生成key标识符。

    key_t ftok(const char *pathname,int proj_id);

    2.使用shmgt函数,创建一个共享内存块,返回这个共享内存块的标识符shmid。

    int shmget(key_t key,size_t size,int shmflg);

    size是需要申请的共享内存的大小,需要注意的是,操作系统为你提供的大小的时候是按页来提供,所以size为4k的整数倍;shmflg:如果要创建新的共享内存,那么就使用IPC_CREAT,IPC_EXCL,如果是已经存在的,那么只需要使用IPC_CREAT。

    3.用shmat挂接共享内存(将进程地址空间挂接到共享内存,共享内存是物理空间,可以有多个挂接)

    void *shmat(int shmid,const void *shmaddr, int shmflg);

    shmid是挂接的进程号;shmaddr置为NULL,让系统选择一个合适的地址空间进行挂接;shmflg表示什么方式进行挂接,一般都是取0;函数返回各个进程挂接的虚拟的地址空间。

    4.用shmdt去挂接。

    int shmdt(const void *shmaddr);

    5.用shmctl销毁共享内存

    int shmctl(int shmid,int cmd,struct shmid_ds *buf);

    cmd取IPC_RMID表示删除这块共享内存;buf一般设置为NULL,不关心这个东西,消息队列中也有这么一个类似的结构体也是设置为NULL。

    共享内存与mmap内存映射的区别

    首先说明相同点:都可以进行进程之间的通信。

    mmap还可以提供非文件进行访问的操作,访问文件就像访问内存一样,可以用指针直接对文件进行操作,但是速度还是不一样,毕竟mmap最终还是访问的是磁盘文件。

    mmapshm

    1.mmap是在磁盘上建立一个文件,每个进程地址空间中开辟出一块空间进行映射。而对于shm而言,shm每个进程最终会映射到同一块物理内存。shm保存在物理内存,这样读写的速度要比磁盘要快,但是存储量不是特别大。

    2.相对于shm来说,mmap更加简单,调用更加方便,所以这也是大家都喜欢用的原因。

    3.另外mmap有一个好处是当机器重启,因为mmap把文件保存在磁盘上,这个文件还保存了操作系统同步的映像,所以mmap不会丢失,但是shmget就会丢失。

    展开全文
  • 共享内存及其用mmap实现共享内存

    千次阅读 2016-08-01 00:32:49
    一、什么是共享内存顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。...
  • 共享单车、共享充电宝、共享雨伞,世间的共享有千万种,而我独爱共享内存。早期的共享内存,着重于强调把同一片内存,map到多个进程的虚拟地址空间(在相应进程找到一个VMA区域),以便于CPU可以在各个进程访问到这...
  • ),执行后两个或多个进程可同时读取该文件并在终端打印。 要实现该功能,首先你得了解共享内存的搭建,有四个函数,分别为shmget,shmat,shmdt,shmctl,他们的作用如下: 1、shmget函数 该函数用来创建共享...
  • Linux下共享内存编程(共享存储空间)

    万次阅读 多人点赞 2018-07-29 23:44:08
    最简单的共享内存的使用流程 ①ftok函数生成键值 ②shmget函数创建共享内存空间 ③shmat函数获取第一个可用共享内存空间的地址 ④shmdt函数进行分离(对共享存储段操作结束时的步骤,并不是从系统中删除共享内存...
  • 共享内存实现原理

    万次阅读 2018-09-28 18:02:39
    共享内存的使用实现原理(必考必问,然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?) nmap函数要求内核创建一个新额虚拟存储器区域,最好是从地质start开始的一个...
  • 共享单车、共享充电宝、共享雨伞,世间的共享有千万种,而我独爱共享内存。早期的共享内存,着重于强调把同一片内存,map到多个进程的虚拟地址空间(在相应进程找到一个VMA区域),以便于CPU...
  • 消费者进程从共享内存中读取并输出序列。生产者进程要在命令行指定生成Catalan数的数目。例如,命令行指定5,说明生产者进程会生成5个Catalan数:1 2 5 14 42 这里的实现没有显式创建进程,因为打开不同的命令行...
  • Java 共享内存

    千次阅读 2019-06-11 20:00:08
    对UNIX系统来说,共享内存分为一般共享内存和映像文件共享内存两种,对windows实际上只有映像文件共享内存一种。所以java应用中也是只能创建映像文件共享内存。使用共享内存,有如下几个特点: 1、可以被多个进程...
  • VC++ 共享内存读写操作

    热门讨论 2014-01-02 13:58:34
    此解决方案含两个工程文件,一个是写操作工程文件,即把任意字符串写入创建的共享内存里,另外一个操作工程文件,则是读取共享内存里的数据,从而实现了进程之间的共享内存读写操作。
  • 【Linux】Linux的共享内存

    万次阅读 多人点赞 2018-08-10 19:17:45
    实现进程间通信最简单也是最直接的方法就是共享内存——为参与通信的多个进程在内存中开辟一个共享区。由于进程可以直接对共享内存进行读写操作,因此这种通信方式效率特别高,但其弱点是,它没有互斥机制,需要信号...
  • Qt 读写共享内存

    千次阅读 2020-10-01 14:05:43
    Qt 读写共享内存 一、简述 记--使用Qt进行简单的读写共享内存。 二、工程结构 三、测试代码 #include <QDebug> #include <QSharedMemory> //测试使用的数据结构 typedef struct{ int age; ...
  • 【需求描述】 1、共享内存保存信息 2、提供接口写入共享内存 3、提供接口获取共享内存 【编写语言:C】 【环境:linux】 1、写入内存一千万条数据 耗时:5.356秒 2、读取内存一千万条数据 耗时:1.449秒
  • C语言编写程序,用信号量和共享内存实现读写同步,程序中父进程为进程,子进程为写进程。开启共享内存空间和二值信号量,子进程占用信号量,父进程无法执行,等待子进程写完释放信号量后父进程进行操作。依次...
  • Windows共享内存解析

    千次阅读 2017-07-29 23:47:42
    在Windows程序开发过程中,当多个进程之间需要使用同样的数据的时候我们最好的方式就是通过共享内存进行处理(比如:当A进程运行时,进行数据处理,那么此时我想知道数据是不是正确,用B监控,那么A与B之间就可以...
  • 上一篇博文提到的系统调用mmap通过映射一个普通文件实现共享内存。那么本文中介绍的System V 共享内存则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信。也就是说,每个共享内存区域对应特殊文件系统...
  • 使用另一个程序通过上一程序返回的shmid共享内存内的数据 建立共享内存并写入数据的程序 #include #include #include #include #include #include void get_buf(char *buf) {  int i=0

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 299,613
精华内容 119,845
关键字:

共享内存同时读