weiqi7777

进击吧,linux(十七) 共享内存通讯

0
阅读(2353)

Linux进程和进程之间有多种通讯方式。Linux进程间通讯的主要方式有:

1、无名管道

2、有名管道

3、信号

4、消息队列

5、共享内存

6、信号量

7、套接字

共享内存通讯,从这名字一听就知道这个通讯的方式了。就是利用内存进行通信。两个进程对内存的同一个区域进行数据操作,不就能进行通信了。

通过下面一个图就能清楚的知道共享内存通信。

clip_image002

同样,对共享内存学习也是学习几个函数。

10.1创建打开共享内存

10.1.1函数名

shmget

10.1.2函数原型

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

10.1.3函数功能

创建或者获取共享内存,并返回其描述符id

10.1.4所属头文件

10.1.5函数返回值

成功:共享内存的描述符

失败:-1

10.1.6参数说明

key共享内存的键值

size创建的共享内存的大小

shmflg:打开标志

-IPC_CREAT:key所关联的共享内存不存在,就创建共享内存

10.2映射共享内存

10.2.1函数名

shmat

10.2.2函数原型

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

10.2.3函数功能

把指定的shmid共享内存映射到进程的地址空间去

10.2.4所属头文件

10.2.5函数返回值

成功:返回映射到进程空间之后的内存地址

失败:-1

10.2.6参数说明

shmid共享内存的描述符

shmaddr:指定映射后的内存地址,一般设置为空,即NULL,让系统自动选择映射地址

shmflg:标志,一般设置为0

10.3分离共享内存

10.3.1函数名

shmdt

10.3.2函数原型

int shmdt(const void *shmaddr)

10.3.3函数功能

从进程地址空间中,断掉与共享内存的联系

10.3.4所属头文件

10.3.5函数返回值

成功:0

失败:-1

10.3.6参数说明

shmaddr要断开的共享内存的映射地址

10.4控制共享内存

10.4.1函数名

shmctl

10.4.2函数原型

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

10.4.3函数功能

控制共享内存

10.4.4所属头文件

10.4.5函数返回值

成功:根据不同的操作返回不同的值

失败:-1

10.4.6参数说明

shmid:共享内存的描述符

cmd:对共享内存的操作命令

-IPC_STAT:从指定的共享内存的内核数据中读取数据到buf结构体中

-IPC_SET:buf结构体中数据写入到指定的共享内存的内核数据中

-IPC_RMID:删除共享内存

buf:一个结构体,指向shmid_ds结构体,获取linux中描述共享内存的结构。基本不使用。

clip_image004

其中的struct ipc_perm也是一个结构体

clip_image005

下面就是写代码来学习以上的函数。

有两个进程AB,进程A创建一个共享内存,然后往这个共享内存中写入数据,进程B获取A创建的共享内存,然后从这共享内存中读取数据。当A进程写入weiqi7777,通信结束,两个进程分离共享内存,最后B进程删除共享内存。

A进程:

#include #include #include #include #include #include #define TEXT_SZ 2048 struct memory_share { int flag; char text[TEXT_SZ]; }; void main() { key_t key; int shmid; struct memory_share *p; char data[TEXT_SZ]; /*创建键值*/ key = ftok("/home",6); /*创建共享内存*/ shmid = shmget(key,sizeof(struct memory_share),IPC_CREAT); if(shmid == -1) { printf("create shm failed\n"); exit(EXIT_FAILURE); } /*映射共享内存*/ p = (struct memory_share *)shmat(shmid,NULL,0); /*往共享内存放入数据*/ while(1) { while(p->flag == 1); fgets(data,TEXT_SZ,stdin); strncpy(p->text,data,TEXT_SZ); p->flag = 1; if(strncmp(data,"weiqi7777",9) == 0 ) break; } /*分离共享内存*/ shmdt((const void *)p); }

A进程首先创建键值,因为共享内存是和键值关联的,然后再通过这个键值创建一个共享共存,并将struct memory_share p结构体与共享内存关联。然后就往结构体p中写入数据,不就相当于往共享内存中写入数据了。

最后判断写入的数据是不是weiqi7777,是的话就退出循环,通信结束,然后分离共享内存。

B进程:

#include #include #include #include #include #include #define TEXT_SZ 2048 struct memory_share { int flag; char text[TEXT_SZ]; }; void main() { key_t key; int shmid; struct memory_share *p; char data[TEXT_SZ]; /*创建键值*/ key = ftok("/home",6); /*获取共享内存*/ shmid = shmget(key,sizeof(struct memory_share),IPC_CREAT); if(shmid == -1) { printf("create shm failed\n"); exit(EXIT_FAILURE); } /*映射共享内存*/ p = (struct memory_share *)shmat(shmid,NULL,0); /*从共享内存里面读取数据,并打印*/ while(1) { while(p->flag != 1); strncpy(data,p->text,TEXT_SZ); p->flag = 0; printf("read data: %s",data); if(strncmp(data,"weiqi7777",9) == 0 ) break; } /*分离共享内存*/ shmdt((const void *)p); /*删除共享内存*/ shmctl(shmid,IPC_RMID,NULL); }

B进程首先也是创建键值,创建的键值和A进程创建的进程要是一样的,然后再通过这个键值获取与A进程创建的共享共存,并将struct memory_share p结构体与共享内存关联。然后就从结构体p中读取数据,不就相当于从共享内存中读取数据了。

最后判断读取的数据是不是weiqi7777,是的话就退出循环,通信结束,然后分离共享内存,最后删除共享内存。

运行程序:

两个进程运行,A进程在等待输入输入,B进程在等待A进程往共享内存中写入数据。

clip_image007

A进程接收键盘输入数据,写入到共享内存中,B进程从共享内存中读取数据,并显示。

clip_image009

当输入的数据是weiqi7777时,两个进程结束,分离共享内存,B进程删除共享内存。

clip_image011

以上就实现了进程间共享内存通信,其实也是比较简单的。

Baidu
map