Linux IPC——简单应用 共享内存(Share Memory)


目录

 

一:共享内存

1.1定义

1.2优缺点

1.2.1 优点

1.2.2缺点

1.3共享内存结构维护

1.4共享内存的通信原理

二:相关函数接口

2.1 Linux命令

2.1.1查看系统中的共享储存段

 2.1.2删除系统中的共享储存段  

2.2 函数

2.2.1shmget()创建共享内存函数

2.2.2shmctl()销毁等 函数

2.2.3shmat()脱接共享内存函数

2.2.4shmdt()去关联共享内存函数

三:代码测试

3.1shma.c文件

3.2shmb.c文件


一:共享内存

1.1定义

    内核管理一片物理内存,允许不同的进程同时映射(访问),多个进程可以映射同一块内存。被多个进程同时映射的物理内存:即共享内存。(允许多进       程同步访问给定的储存区域)。

    映射物理内存-》挂接 ; 用完之后解除映射-》脱接

1.2优缺点

1.2.1 优点

    因为数据不需要在客户进程和服务器进程之间复制,所以这是一种最快的IPC

1.2.2缺点

    内核没有提供对共享内存的互斥访问。(信号量,互斥量等)

1.3共享内存结构维护

    内核为每个共享内存都维护相关信息:

//共享内存的维护信息
struct shmid_ds{
    struct ipc_perm     shm_perm;    //权限控制
    size_t              shm_segsz;   //size of segement in bytes 字节数
    pid_t               shm_lpid;    //pid of last shomp() 最后执行shomp()的进程ID
    pid_t               shm_cpid;    //创建该共享内存的ID
    shmatt_t            shm_nattch;  //number of current attaches,现有连接数
    time_t              shm_time;    //最后被连接时间
    time_t              shm_dtime;   //最后删除连接的时间
    time_t              shm_ctime;   //最后修改时间
     .
     .
}   

1.4共享内存的通信原理

    Linux,中每个进程都有自己的PCB(进程控制块)和Addr Space(地址空间),该虚拟地址空间通过多级页表(这里以一级页表为例)和物理地址空间进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这个块区域即:共享内存。

     对于一个共享内存,实现采用的是引用计数的原理,当进程脱接共享储存区后,计数器减一;挂接则加一,直至计数器变为0,该共享内存才被删除。当进程终止的时间,它所附加的共享储存区都会自动脱离。

    这里还可以解决一个问题:为什么共享内存速度最快?

    上图中:Proc A进程在给共享区域写数据,Proc B 进程从其中读取数据,再次其中一共发生了两次数据的复制:

                      (1):Prco A 到共享内存             (2) : 共享内存到 Prec B

    因为直接在内存上操作,所以共享内存的速度也就提高了。

二:相关函数接口

2.1 Linux命令

2.1.1查看系统中的共享储存段

ipcs -m

 2.1.2删除系统中的共享储存段  

​ipcrm -m [shmid]​

2.2 函数

2.2.1shmget()创建共享内存函数

函数头文件

函数原型:

#include<sys/shm.h>

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

函数参数:

1. key:将key变换成一个标识符

2.size_t:创建:共享存储段的长度,字节为单位。引用:设置为0

3.flag : 控制位。

函数功能:

若key不存在,创建一个;否则获取。

成功返回 共享储存的ID,失败返回-1;

2.2.2shmctl()销毁等 函数

函数原型: int shmctl ( int shmid , int cmd , struct shmid_ds *buf);
函数参数:

1.shmid:指定共享内存

2.cmd :在shmid上执行某些命令:IPC_STAT IPC_SET IPC_RMID SHM_LOCK PID_UNLOCK

函数功能:

函数对共享存储段执行多种操作。

成功返回0,失败返回-1.

2.2.3shmat()脱接共享内存函数

函数原型: void* shmat ( int shmid , const void *addr , int flag );
函数参数:

addr:指定共享储存段连接到调用进程的哪个地址上。

addr为0 则此段连接到由内核选择的第一个可用地址上,推荐使用方式。
addr为非0

并且内有指定 SHM_RND(取整的意思),则此连接段到addr所指定的地址上。

addr为非0 指定了SHM_RND,连接到(addr-(addr mod SHMLBA))所表示的地址上。(SHMLBA低边界地址倍数)
函数功能: 一旦创建了一个共享储存段,进程就可以调用shmat将其连接到它的地址空间中

2.2.4shmdt()去关联共享内存函数

函数原型和返回值:

int shmdt ( const void *shmaddr );

成功返回0,并将shmid_ds结构体中的shm_nattch计数器减一;出错返回-1。

参数: 连接以后返回的地址
功能: 当一个进程不需要共享内存的时间,就需要 去关联。该函数并不删除所指定的共享存储区,而是将之前用shmat函数连接好的共享内存区 脱离目前进程。

三:代码测试

sem:链接https://blog.csdn.net/genzld/article/details/83095577

3.1shma.c文件

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>

#include <sys/shm.h>  // shm ==> shared  memory
#include "./sem.h"

int main()
{
	int shmid = shmget((key_t)1234, 512, 0666 | IPC_CREAT);//指定共享内存空间的大小
	assert(shmid != -1);

	char *ptra = (char *)shmat(shmid, NULL, 0);//推荐给NULL,使得系统自动选取虚拟地址
	//ptra指向的是内核对象的空间

	assert(ptra != (char*)-1);

	int semid = sem_init(123);//初始化一个信号量,



	while(1)
	{
		//sem_p(semid, 0);
		printf("please input: ");
		fflush(stdout);

		memset(ptra, 0, 512);//内核对象中的内容全部清空为0
		fgets(ptra, 128, stdin);//往共享内存中存取信息
		ptra[strlen(ptra) - 1] = 0;//回车替换

		if(strcmp(ptra, "end") == 0)
		{
			break;
		}

	//	sem_v(semid, 0);
	}

	shmdt(ptra);//shmdt(void* addr)//给shmat的返回值,将虚拟地址和内存空间断开
}

3.2shmb.c文件

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>

#include <sys/shm.h>  // shm ==> shared  memory
#include "./sem.h"

int main()
{
	int shmid = shmget((key_t)1234, 512, 0666 | IPC_CREAT);
	assert(shmid != -1);

	char *ptrb = (char *)shmat(shmid, NULL, 0);//自动查找

	assert(ptrb != (char*)-1);

	int semid = sem_init(123);

	while(1)
	{
		//sem_p(semid, 0);
		if(strcmp(ptrb, "end") == 0)
		{
			break;
		}

		int i = 0;
		for(; i < strlen(ptrb); ++i)//读取ptrb中的内容
		{
			printf("%c\n", ptrb[i]);
			sleep(1);
		}

		//sem_v(semid, 0);
	}

	shmdt(ptrb);
}

参考:https://www.cnblogs.com/xcywt/p/5128430.html

猜你喜欢

转载自blog.csdn.net/genzld/article/details/84699010