进程间通信方式之共享内存
1:什么事共享内存
共享内存共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。
在我们书写多个进程的时候,由于每个进程的资源都是不被共享的,所以为了多个进程间进行通信成为了一个很重要的问题。共享内存是进程间通信的一种比较简单的通信方式。
2:进程间共享内存通信
程序简述:
在线程一节的附加程序中我们建立了两个线程并且使用了一个变量来控制流水灯周期的速度。由于进程多个允许同时使用同一个线程中的数据并允许修改,所以程序中两个线程并没有太大的通信问题。但是由于线程的一些性质使得多线程并不能很好的去实现一整套的多任务程序(其实多线程编程要比多进程编程复杂,因为程序员要很好的考虑现成的运行时间等,不然会使电脑死机,而且线程对数据的使用并不是很安全。)。所以在大多较大的程序中使用的较多的依然是进程。由于进程间的数据是互相独立的,所以进程间的通信显得相当重要。
进程间的通信方式大致有:信号量,共享内存,管道等方式(各种书上介绍一大堆。)。由于信号量的列程开发板光盘中并没有(操作系统中的信号量类似于一个进程之间“标志位”,而且linux的信号量主要是针对互斥锁而设计的,经常一起使用。),而且对于初学者受51单片机编程的影响,需要进程间通信的时候更想得到一些自己设定好的数据。所以我们在进程间通信的第一个例子中使用的是共享内存。
共享内存可以使用一个指针指向一个设定成共享的变量,而且只要设置了共享内存且位置相同的两个任务(进程线程甚至于在终端中都能使用)。这样我们就可以向进程的列子一样传输数据了~。
重点掌握函数:
Ftok();
shmget();
shmget();
shmat();
memcpy();
shmdt();
注意:
1:共享内存法的通信可以再一个程序中建立多个程序使用,也可以建立多个程序使用。
2:再分配内存块大小时一定要保证内存块大小是2的整数幂如:1024、2048、4096等
//Testwrite.c文件内容:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct{ //定义了一个结构体people用来设置共享内存。
char name[4]; nt age;
} people;
main(int argc, char** argv)//main函数参数无用
{ int shm_id,i; //
key_t key; //共享内存的ID存放变量
char temp; //传输数据的暂存
people *p_map; //最终存放共享内存的指针,由fork(建立进程)分给两 //个进程
char* name = "/dev/shm/myshm2";//共享内存的名字
key = ftok(name,0);//系统建立IPC通讯时必须指定的ID值
if(key==-1)
perror("ftok error");
shm_id=shmget(key,4096,IPC_CREAT);// 创建共享内存快大小为4096(必 //须是1024的倍数)
//成功返回标识符。
if(shm_id==-1)
{
perror("shmget error");
return;
}
p_map=(people*)shmat(shm_id,NULL,0);//共享内存区对象映射到调用进 //程的地址空间,设置内存的指针类型,返回内存的首指真
temp='a'; //temp最初直
for(i = 0;i<10;i++)
{
temp+=1;
memcpy((*(p_map+i)).name,&temp,1);//将temp的值付给共享内存的name中
//*((*(p_map+i)).name)=temp;//若无法编译memcpy请删除上行使用这行。
(*(p_map+i)).age=20+i; //共享内存的age=20+1(就是个标志)
}
if(shmdt(p_map)==-1) //查询状态如果溢出则错误
perror(" detach error ");
}
//Testread.c的内容:(由于与Testwrite.c文件内容与上一个程序基本相同不多作解释)//
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct{
char name[4]; int age;
} people;
main(int argc, char** argv)
{ int shm_id,i;
key_t key;
people *p_map;
char* name = "/dev/shm/myshm2";
key = ftok(name,0);
if(key == -1)
perror("ftok error");
shm_id = shmget(key,4096,IPC_CREAT);
if(shm_id == -1)
{ perror("shmget error");
return;
}
p_map = (people*)shmat(shm_id,NULL,0);
for(i = 0;i<10;i++)
{printf( "name:%s/n",(*(p_map+i)).name );//输出后是一个数字后面跟 //着一个字母
printf( "age %d/n",(*(p_map+i)).age ); //测试程序 无意义
}
if(shmdt(p_map) == -1)
perror(" detach error ");
}