linux课程设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux课程设计报告
专业班级:
学号:
姓名:
使用共享内存来完成进程间通信
一、相关原理介绍分析
1,共享内存的三种实现方式
(1)POSIX共享内存对象:shm_open创建一个名称为tmp的共享内存区对象后,在/dev/shm/下可以看到对应的文件(tmpfs的文件系统可以看成是直接对内存操作,速度非常快)。cat可以看到映射的内容。进程重启共享内存中数据不会丢失,内核自举或显示调用
shm_unlink或rm掉文件删除后丢失
(2)POSIX文件映射:通过映射一个普通文件(匿名文件或一个打开的命名文件)实现共享内存——mmap()。该方式的特点接口简单,较通用。可利用cat查看映射的文件,要注意考虑进程终止对通信的影响。该方式也是本实验使用的方式,下面将做具体表述。
(3)systemV共享内存:通过映射特殊存储块shm中的文件实现进程间的共享内存通信——主要有以下几个API:shmget()、shmat()、shmdt()及shmctl()。本方式无法看到文件实体。
进程重启共享内存中数据不会丢失,内核自举或显示调用shmdt或使用ipcrm删除后丢失。
2,POSIX文件映射共享内存简介
POSIX文件映射指mmap mmap()系统调用使得进程之间通过映射同一个普通文件实
现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一
样对文件进行访问,不必再调用read(),write()等操作。
3,POSIX文件映射共享内存实现方法
(1)文件与address_space结构的对应:一个具体的文件在打开后,内核会在内存中为之建立
一个struct inode结构,其中的i_mapping域指向一个address_space结构。这样,一个文件就对应一个address_space结构,一个address_space与一个偏移量能够确定一个page cache 或swap cache中的一个页面。因此,当要寻址某个数据时,很容易根据给定的文件及数据在文件内的偏移量而找到相应的页面。
(2)进程调用mmap()时,只是在进程空间内新增了一块相应大小的缓冲区,并设置了相应的
访问标识,但并没有建立进程空间到物理页面的映射。
4,主要函数介绍:
(1)void* mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset )
①返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址
②addr指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选
择起始地址的任务留给内核来完成。
③len是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。
④prot 参数指定共享内存的访问权限。
PROT_READ(可读),
PROT_WRITE (可写),
PROT_EXEC (可执行),
PROT_NONE(不可访问)。
⑤flags由以下几个常值指定:
MAP_SHARED , (与private选择其一)
MAP_PRIV ATE ,
MAP_FIXED,(不推荐使用)
⑥fd为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,
此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射
⑦offset参数一般设为0,表示从文件头开始映射。
(2) int open( const char * pathname,int flags, mode_t mode);
①p athname 指向欲打开的文件路径字符串。
②f lags 所能使用的旗标:
O_RDWR 以可读写方式打开文件。
O_CREAT 若欲打开的文件不存在则自动建立该文件。
O_TRUNC 若文件存在并且以可写的方式打开时,此旗标会令文件长度清为0,而原来
存于该文件的资料也会消失。
③Mode有多种组合,只有在建立新文件时才会生效,此外真正建文件时的权限会受到
umask值所影响,因此该文件权限应该为(mode-umaks)。S_IRWXG 00777,代表具有可读可写可操作
二,设计实现
1,功能介绍
实现了共享内存机制。在一个终端上运行writer端,由于writer端得程序设置了八个缓冲区,因此可以依次输入,在另一个终端上运行reader端,在reader端可以读到数据并且屏幕输出。
实现了信号量同步机制。程序中应用了信号量,reader端和writer端不能同时对同一缓冲区进行操作。
2,程序结构框图
3,程序代码
(1)写者程序:w.c
#define NRBUF 8 //设置常数缓冲区的个数int empty[NRBUF];
int main()
{
/*数据结构的声明*/
int i=0,fd;
struct buffer_head *buf;
struct buffer_head bu[NRBUF];
char temp[20];
fd=open("arg",O_CREAT|O_RDWR|O_TRUNC,00777);//打开文件
truncate("arg",sizeof(bu)); //实际分配内存空间
buf=(struct
buffer_hea*)mmap(NULL,sizeof(bu),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//非配缓冲区
close(fd);//关闭文件
/* 初始化信号量*/
for(i=0;i { empty[i] = CreateSem(1);//产生信号量 } /* 初始化缓冲区*/ int k=0; for(k=0;k { //(bu)->data =NULL; (buf+k)->b_next=buf+k+1; (buf+k)->sem = empty[k]; (buf+k)->lo = k+1; } (buf+NRBUF-1)->b_next = buf; (buf+NRBUF-1)->sem = empty[NRBUF-1]; (buf+NRBUF-1)->lo = NRBUF; i=0; while(1) { /*进行PV操作 */ Psem(buf->sem); printf(" writer 缓冲区%d :",buf->lo); printf("请输入一个字符串"); gets(temp); memcpy(buf->data,temp,20); //内存拷贝 buf=buf->b_next; } } (2)读者程序:r.c