操作系统——实验贰——进程通信(一)管道及共享内存
一、 实验目的
- 熟悉并掌握管道机制,并实现进程间通信
- 熟悉并掌握共享内存机制,并实现进程间通信
二、 实验内容
任务一:
- (1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。
- (2)编写程序:父进程利用管道将一字符串交给子进程处理。子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。
任务二、
- (1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。 (有关ipcs和ipcrm介绍见后面一页)
- (2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。
- (3)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。
三、 代码及运行结果分析
任务一:
(1)#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <string.h>
int main()
{ int x,fd[2];char buf[30],s[30];pipe(fd);while ((x=fork())==-1);if (x==0){close(fd[0]);printf("Child Process!\n");strcpy(buf,"This is an example\n");write(fd[1],buf,30);exit(0);}else{close(fd[1]);printf("Parent Process!\n");read(fd[0],s,30);printf("%s\n",s);}
}
调用pipe创建一个管道,接着调用fork产生两个进程,首先执行子进程,关闭管道出口,通过管道入口向管道中写入内容。接着在父进程中关闭管道入口,通过管道出口从管道中读取写入内容,输出。
(2)#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(){int x,count,left,right,temp,fd[2],fe[2];char c,buf[30],s[30];pipe(fd);pipe(fe);printf("please input a line of char:\n");scanf("%s",buf);while((x=fork())==-1);if(x==0){close(fd[0]);close(fe[1]);printf("Child Process!\n");write(fd[1],buf,30);read(fe[0],buf,30);printf("%s\n",buf);exit(0);}else{close(fd[1]);close(fe[0]);count=0;do{read(fd[0],&c,1);s[count++]=c;}while(c!='\0');printf("Parent Process!\n");printf("%s\n",s);count-=2;for(left=0,right=count;left<=count/2;left++,right--){temp=s[left];s[left]=s[right];s[right]=temp;}write(fe[1],s,30);wait(0);}
}
任务二:
(1)#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main()
{
key_t key=231;
int shmid_1,shmid_2;
if ((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){perror("shmget shmid_1");exit(1);
}
printf("First shared memory identifier is %d\n",shmid_1);
if ((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){perror("shmget shmid_2");exit(2);
}
printf("Second shared memory identifier is %d\n",shmid_2);
exit(0);
return 0;
}
成功返回共享内存段标识符。对存在于内核存储空间中的每个共享内存段,内核均有shmid_ds。失败,返回-1。
参数key用来创建IPC标识符。参数size决定内存段的大小.参数shmflag,用于设置访问权限及标识创建条件。
对比:第二次的共享内存段中的关键字,共享内存标识符,访问权限,字节等都是不一样的。
(2)
程序一:#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 131 /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K 1024int shmid;
void cleanup()
{
shmctl(shmid,IPC_RMID,0);
exit(0);
}
int main (){
int i,*pint;
char *addr;
//extern int shmat();
// extern cleanup();
for(i=0;i<20;i++) signal(i,cleanup);
shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址 */
printf ("addr 0x%x\n",addr);
pint=(int *)addr;
for (i=0;i<256;i++) *pint++=i;
pause();/*等待接收进程读 */
}
程序二:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMKEY 131 /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K 1024
int shmid;
main (){
int i,*pint;
char *addr;
//extern char * shmat ();
shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */
addr=shmat(shmid,0,0);/*连接共享区*/
pint=(int *)addr;
for (i=0;i<256;i++)
printf("%d\n",*pint++);/*打印共享区中的内容*/
}
首先系统调用shmctl对shmid指向内存段进行删除,接着系统调用shmget创建共享内存段,返回标识符给shmid,系统再次调用shmat连接内存段,返回地址addr。程序1运行时,该程序开始执行,系统调用shmget创建共享内存段,再通过调用shmat挂接内存段,最终输出转换后的前255。
(3)#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 131
#define K 1024
int shmid_1,shmid_2;
int main ()
{int x,y,i,*pint;char *addr_1,*addr_2;char words[30]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D'};shmid_1=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */addr_1=shmat(shmid_1,0,0);/*挂接,并得到共享区首地址*/pint=(int *)addr_1;printf ("addr_1 0x%x\n",addr_1);for (i=0;i<26;i++) {*pint=words[i];pint++;}while((x=fork())==-1);if(x==0){shmid_2=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */addr_2=shmat(shmid_2,0,0);/*挂接,并得到共享区首地址*/pint=(int *)addr_2;for(i=0;i<26;i++){printf("%c ",*pint);*pint=*pint+32;pint++;if(i==25)printf("\n");}y=shmdt(addr_2);exit(0);}else{sleep(5);pint=(int *)addr_1;for(i=0;i<26;i++){printf("%c ",*pint);pint++;if(i==25)printf("\n");}}
}
四、 实验心得
通过本次实验简单了解了管道进程间通信形式,初步掌握利用管道进行进程通信的程序设计,基本完成了本次实验的要求。学会了shmget()、shmat()、shmdt()、shmctl()4个调用,ipcs、ipcrm命令使用:还加深了对操作系统中各进程之间的通信协同的了解。
操作系统——实验贰——进程通信(一)管道及共享内存相关推荐
- 2020 操作系统 实验二 进程通信
实验二.进程通信 一.实验名称 进程通信 二.实验目的 掌握用邮箱方式进行进程通信的方法,并通过设计实现简单邮箱理解进程通信中的同步问题以及解决该问题的方法. 三.实验原理 邮箱机制类似于日常使用的信 ...
- ZUCC_操作系统实验_Lab7进程通信---共享内存
lab7进程通信-共享内存 一.利用共享内存实现生产者/消费者问题的解决方案 1.代码 #include<stdio.h> #include<stdlib.h> #includ ...
- 操作系统实验·Linux进程通信与内存管理
预备知识 Linux进程的数据结构 在Linux中,进程用task_struct表示,所有进程被组织到以init_task为表头的双向链表中(见[include/linux/sched.h]SET_L ...
- GB28181系统设计(三)-进程通信让python获取共享内存数据
GB28181系统设计 一 事件设计 GB28181系统设计 二 kdtree 算法 这一节说到了GB28181 系统接收到RTP包后,解码后交付给python做图像识别 流媒体服务依然是c++主打, ...
- 计算机操作系统感悟随笔--进程通信
一.进程通信是指进程之间的信息交换 1.低级通信--进程之间的互斥和同步 信号量机制是有效的同步工具,但作为通信工具缺点如下: (1)效率低(通信量少) (2)通信对用户不透明(程序员实现,操作系统只 ...
- Linux进程通信——匿名管道、命名管道、管道的特性和共享内存
Linux进程通信--匿名管道.命名管道.管道的特性和共享内存 一.管道 1.1 什么是管道? 1.2 匿名管道 <1> 匿名管道参数说明 <2> fork共享管道原理 < ...
- linux共享存储通信实验,Linux进程通信——共享存储
共享内存是进程间通信最有用的方式,也是最快的IPC形式.共享内存是说:同一块内存被映射到多个进程的地址空间.但是共享内存并不提供同步机制,因此需要互斥锁或者信号量.使用共享内存唯一需要注意的是:当前如 ...
- java共享内存_Java进程通信之映像文件共享内存
Java进程通信之映像文件共享内存 1. 共享内存 vs 进程通信 对UNIX系统来说,共享内存分为一般共享内存和映像文件共享内存两种.但windows实际上只有影像文件共享内存一种. 而说到进程通信 ...
- 进程间通信(匿名管道、命名管道、共享内存)
进程间通信 进程间通信的作用 管道 匿名管道 命令感受匿名管道 从内核角度去解释匿名管道 代码创建匿名管道 从PCB角度去分析匿名管道 匿名管道的非阻塞读写特性 创建管道,获取管道读写两端文件描述符的 ...
最新文章
- 最近,又发现了 Pandas 中三个好用的函数
- nginx 认证多个客户端的问题
- Python 之glob模块
- code point,code unit
- 周五尾盘上涨,配合周末消息,周一套人的经典实例
- 8号团队-团队任务三:每日立会(2018-11-27)
- 操作系统 —— 内存管理
- 怎么删除mysql的压缩包_压缩包版mysql怎么卸载
- 能发出调子的c语言程序,求关于单片机的电子琴C程序
- mysql 可逆编码,简单明白彻底解决 MySQL 中文编码问题
- [VSCode] Ubuntu 16.04 安装/更新 vscode
- 【马哥教育视频】cacti入门及进阶[已更新至第四段]
- Matlab2018破解方法
- 北京理工珠海学院的计算机专业怎么样,北京理工大学珠海学院怎么样?北京理工大学珠海学院优势有哪些?...
- Linux下七种文件类型、文件属性及其查看方法
- mysql报表服务器配置_Power Bi报表服务器安装及数据库配置方法
- 带农历和法定节假日的 日历控件_带节日和农历的js日历
- 百度网盘加速无限试用_百度网盘临时加速正式上线,最低 2 元
- CSS3实现图片的3D旋转效果
- npmmirror 中国镜像站,npm设置最新淘宝镜像
热门文章
- 使用 js 设置组合快捷键,支持多个组合键定义,还支持 React
- Tomcat端口冲突
- 装饰器,迭代器,生成器
- grootjs 简明教程
- 服务器群集:Windows 2000 和 Windows Server 2003 网络配置的最佳做法(转自Technet)
- 蓝桥杯第六届国赛JAVA真题----切开字符串
- qt c++ 图片预览_Qt多语言国际化
- php里的stdclass,PHP中的stdClass是什么?
- java中抓阄_如何进行抓阄
- java redis 商品秒杀_使用redis秒杀出现产品超发现象求解?