进程间通信之

时间:2021-08-04 08:43:24

众所周知,进程间通信有三种方式,信号量、消息队列和共享内存。不过信号量个人感觉不像通信,其实就是一个锁的东西。

共享内存,无非就是在内存段开辟一段小内存,返回地址,供以多个进程来使用,有的进程来这里存数据,有的进程来取数据。

要使用一块共享内存,进程必须首先分配它。随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中。当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块。所有共享内存块的大小都必须是系统页面大小的整数倍。(4K*n)

1.API:

共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。按步骤如下:

1shmget: int shmget(key_t key, size_t size, int shmflg)  得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符

key 0(IPC_PRIVATE):会建立新共享内存对象
大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值
size 大于0的整数:新建的共享内存大小,以字节为单位
0:只获取共享内存时指定为0
shmflg 0:取共享内存标识符,若不存在则函数会报错
IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符
IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的共享内存,则新建一个消息队列;如果存在这样的共享内存则报错

2shmat :把共享内存区对象映射到调用进程的地址空间

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

shmid 共享内存标识符
shmaddr 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflg SHM_RDONLY:为只读模式,其他为读写模式

3 管控共享内存  int shmctl(int shmid, int cmd, struct shmid_ds *buf)

shmid 共享内存标识符
cmd IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID:删除这片共享内存
buf 共享内存管理结构体。具体说明参见共享内存内核结构定义部分

断开共享内存连接 int shmdt(const void *shmaddr)  //shmaddr:连接的共享内存的起始地址

2.小例子和解释:

发送方.c进程申请一段共享内存,把一个结构体放入里面,接收方.c进程读取这段内存,读出内容。

SENDER.C

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>

struct personinfo{ //要存放的结构体
char name[10];
int number;
float scores;
};

typedef struct personinfo * player; //声明结构体指针

int main(void){
int shmid;
shmid=shmget(IPC_PRIVATE,4096,0666);//申请共享内存,大小4K,有rwxrwxrwx权限
if(shmid==-1) // shmid就是共享内存的标识
exit(1);
printf("shmid is %d\n",shmid);
player wade; //创建一个指针对象
wade=shmat(shmid,NULL,0);// shmat(shmid,NULL,0)就是把shmid标识的共享内存的地址连接到本进程,这里直接给到结构体指针,就是把结构体指针指向这段内存;
strcpy(wade->name,"dwyane_wade");
wade->number=3;
wade->scores=20.13;
if(shmdt(wade)<0)//解除链接
exit(1);
return 0;
}

RSVER.C

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
struct personinfo{
char name[10];
int number;
float scores;
};
typedef struct personinfo * player;

int main(int argc,char *argv[]){
int shmid;
shmid=atoi(argv[1]);// 从输入端把SENDER.C得到的shmid输入
player lee;

if((lee=shmat(shmid,NULL,0))==NULL) //把指针指向内存这里
exit(1);

printf("name %s\n",lee->name); //读取数据
printf("number %d\n",lee->number);
printf("scores %f\n",lee->scores);
}


运行结果应该是 dwyane_wade\n 3\n 20.129999\n