作业必备:操作系统实验五【管道通信】

您所在的位置:网站首页 进程的创建实验报告 作业必备:操作系统实验五【管道通信】

作业必备:操作系统实验五【管道通信】

2023-12-28 12:27| 来源: 网络整理| 查看: 265

🌸小白白系列第五弹~🌸

*写在前面🌟:Hi~everybody😄 本失踪人口回归,最近一直在忙各种考试👻,实在分身乏术😣,又不想水文章,想一直坚持写高质量好文💪,故而今日考试一结束,我就来更新了🙌!嘿嘿,希望大家喜欢哦😉 在这里插入图片描述

目录 🌸小白白系列第五弹~🌸🍀前言:🍀🍀【实验资料】:🌻一、小白发问:什么是管道呢🤓?🌻二、那么管道都有哪些类型呢🤔🌻三、实验涉及的系统调用👀 ☀正文:🌙🌝🍀【实验目的】:🍀【实验内容】:**🌹🌹🌹一、 编写一段程序,实现进程的管道通信:**🌹🌹🌹二、**编写一段程序,实现父子进程间的管道通信**。🌹🌹🌹三、**编写一段程序,实现:在父进程中用pipe()建立一条管道,往管道里写入两句话(字符串),两个子进程分别接收来自父进程写入的两句话并打印输出。** 🍀【实验感想】:**1、🌟⭐管道通信的特点:**⭐🌟**2、🌟⭐无名管道作用:**🌟⭐

🍀前言:🍀

**

🌻🌻🌻按照惯例,在实验前,我们需要先了解一些基本知识~

**

🍀【实验资料】: 🌻一、小白发问:什么是管道呢🤓?

🌷🌷🌷所谓管道,是指能够连接一个写进程和一个读进程的、并允许它们以生产者—消费者方式进行通信的一个共享文件,又称为pipe文件。由写进程从管道的写入端(句柄1)将数据写入管道,而读进程则从管道的读出端(句柄0)读出数据。

**不懂的,懒的读的,直接看下图🐷**~ 在这里插入图片描述

🌻二、那么管道都有哪些类型呢🤔

****🍁1.有名管道 ****

一个可以在文件系统中长期存在的、具有路径名的文件。用系统调用mknod( )建立。它克服无名管道使用上的局限性,可让更多的进程也能利用管道进行通信。因而其它进程可以知道它的存在,并能利用路径名来访问该文件。对有名管道的访问方式与访问其他文件一样,需先用open( )打开。

****🍁2.无名管道 ****

一个临时文件。利用pipe( )建立起来的无名文件(无路径名)。只用该系统调用所返回的文件描述符来标识该文件,故只有调用pipe( )的进程及其子孙进程才能识别此文件描述符,才能利用该文件(管道)进行通信。当这些进程不再使用此管道时,核心收回其索引结点。二种管道的读写方式是相同的,本次实验使用无名管道。

🌻三、实验涉及的系统调用👀

🍁1.pipe( )创建无名管道 ****

建立一无名管道。 系统调用格式 pipe(filedes) 参数定义 int pipe(filedes); int filedes[2]; 其中,filedes[1]是写入端,filedes[0]是读出端。 该函数使用头文件如下: #include #inlcude #include

🍁2.lockf 文件锁 ***

lockf()函数允许将文件区域用作信号量(监视锁),或用于控制对锁定进程的访问(强制模式记录锁定)。试图访问已锁定资源的其他进程将返回错误或进入休眠状态,直到资源解除锁定为止。当关闭文件时,将释放进程的所有锁定,即使进程仍然有打开的文件。当进程终止时,将释放进程保留的所有锁定。 头文件: #include

详见实验四的必读材料~

🍁3.read( ) ***

系统调用格式 read( fd ,buf ,nbyte ) 功能:从fd(一般是fd[0])所指示的文件中读出nbyte个字节的数据,并将它们送至由指针buf所指示的缓冲区中。如该文件被加锁,等待,直到锁打开为止。

🍁4.write( ) ***

系统调用格式 write(fd,buf,nbyte) 功能:把nbyte 个字节的数据,从buf所指向的缓冲区写到由fd(一般是fd[1])所指向的文件中。如文件加锁,暂停写入,直至开锁。

—————————————————————————

***提示***:以下是本篇文章正文内容,下面我们将会通过三个例子学习管道通信,本文案例可供参考(直接ctrl+C/V到作业嘿嘿~🌝🌝)***

☀正文:🌙🌝 🍀【实验目的】:

🍂1.了解管道的概念。 🍂2.掌握Linux支持的管道通信方式。

🍀【实验内容】: 🌹🌹🌹一、 编写一段程序,实现进程的管道通信:

使用pipe()建立一个管道。子进程p1向管道写一句话: Child process is sending message! 而父进程则从管道中读取来自于子进程的信息,显示在屏幕上。

1、参考代码:🌛

#include #include # include # include # include #include #include int pid1; //存储子进程的PID号; int main() { int fd[2]; //打开文件的文件描述符 char OutPipe[100],InPipe[100];//存储要写入管道的字符串 pipe(fd); //创建无名管道 while((pid1 = fork()) == -1);//先pipe再fork,创建了2个管道 if(pid1 == 0) { sprintf(OutPipe,"Child process is sending message!");//将字符串存储outpipe里 write(fd[1],OutPipe,50);//将50个字节的数据从outpipe写入到fd[1]端 sleep(1); //休眠1秒,防止读写冲突 exit(0);//安全及时的退出 } else //父进程 { wait(0); //等待子进程 read(fd[0],InPipe,50);//将50个字节的数据从fd[0]中读出到inpipe里 printf("%s\n",InPipe); //打印inpipe内字符串 } return 0; }

2、运行结果:🌜

yzy@yzy-virtual-machine:~/new$ ./aa.out Child process is sending message!

**3、分析结果:**⭐⭐⭐

(1)过程:使用pipe函数创建一个管道,让子进程向管道中写入一句话:Child process is sending message!”而父进程从管道中读出这句话,并显示在屏幕上。

(2)解释sprintf函数作用: 打印到字符串中(要注意字符串的长度要足够容纳打印的内容,否则会出现内存溢出),而printf函数打印输出到屏幕上。sprintf函数在我们完成其他数据类型转换成字符串类型的操作中应用广泛。**

🌹🌹🌹二、编写一段程序,实现父子进程间的管道通信。

使用pipe()建立一条管道线。两个子进程p1和p2分别向管道各写一句话: Child 1 is sending message! Child 2 is sending message! 而父进程则从管道中分别读出来自于两个子进程的信息,显示在屏幕上。

1、参考代码:🌛🐟🐟🌜🌛🌝

# include # include # include # include #include #include int pid1,pid2; //存储两个子进程的PID号; int main() { int fd[2]; //打开文件的文件描述符 char OutPipe[100],InPipe[100]; //存储要写入管道的字符串 pipe(fd);//创建无名管道 while((pid1=fork())==-1); //用fork函数创建子进程 if(pid1==0){ //子进程1号 lockf(fd[1],1,0); //上锁,为了两个子进程之间的互斥 sprintf(OutPipe,"Child process 2 is sending a message!"); //存储字符串 write(fd[1],OutPipe,50);//将字符串写入管道 sleep(1); //休眠1秒,防止写冲突 lockf(fd[1],0,0); //解锁,与上锁成对使用 exit(0);//安全退出 } else{ while((pid2=fork())==-1); //子进程2号,同上 if(pid2==0){ lockf(fd[1],1,0); sprintf(OutPipe,"Child process 1 is sending a message!"); write(fd[1],OutPipe,50); sleep(1); lockf(fd[1],0,0); exit(0);} else{ //父进程 read(fd[0],InPipe,50); //将字符串1从管道中读出到inpipe printf("%s\n",InPipe); //打印inpipe内数据 wait(0); //等待子进程 read(fd[0],InPipe,50); //将字符串2从管道中读出到inpipe printf("%s\n",InPipe); exit(0); } } return 0; }

2、运行结果:🌜🌜🌛🐠🐠

yzy@yzy-virtual-machine:~/new$ ./2a.out Child process 2 is sending a message! Child process 1 is sending a message!

**3、分析结果:**⭐⭐⭐⭐

根据阅读材料: 读/写进程互斥,为使读、写进程互斥地访问pipe文件,需使各进程互斥地访问pipe文件索引结点中的直接地址项。因此,每次进程在访问pipe文件前,都需检查该索引文件是否已被上锁。若是,进程便睡眠等待,否则,将其上锁,进行读/写。操作结束后解锁,并唤醒因该索引结点上锁而睡眠的进程。根据上述材料,编写代码,先打出一个父进程,两个子进程,一条管道线的框架。再加上互斥锁,sleep函数,wait函数等,防止两个子进程互斥。

🌹🌹🌹三、编写一段程序,实现:在父进程中用pipe()建立一条管道,往管道里写入两句话(字符串),两个子进程分别接收来自父进程写入的两句话并打印输出。

****1、参考代码:**🌛🌛🌛🌛🌛

# include # include # include # include #include #include int pid1,pid2; //存储两个子进程的PID号; int main() { int fd[2]; //打开文件的文件描述符 char OutPipe[100],InPipe[100]; //存储要写入管道的字符串 pipe(fd); //创建无名管道 while((pid1=fork())==-1); //用fork函数创建子进程 if(pid1==0){ //子进程1号 read(fd[0],InPipe,50); //将字符串1从管道中读出到inpipe printf("%s\n",InPipe); //打印inpipe内数据 } else{ while((pid2=fork())==-1); //子进程2号,同上 if(pid2==0){ read(fd[0],InPipe,50); //将字符串2从管道中读出到inpipe printf("%s\n",InPipe); exit(0);} else{ //父进程 lockf(fd[1],1,0); //上锁,为了两个子进程之间的互斥 sprintf(OutPipe,"Child process 2 is reading a message from pipe!"); //存储字符串 write(fd[1],OutPipe,50);//将字符串2写入管道 sleep(1); //休眠1秒,防止写冲突 lockf(fd[1],0,0); //解锁,与上锁成对使用 wait(0); lockf(fd[1],1,0); //同上 sprintf(OutPipe,"Child process 1 is reading a message from pipe!"); write(fd[1],OutPipe,50); //将字符串1写入管道 sleep(1); lockf(fd[1],0,0); exit(0); } } return 0;}

2、运行结果: **🌜🌛🌜🌜🌜

y@yzy-virtual-machine:~/new$ ./3a.out Child process 2 is reading a message from pipe! Child process 1 is reading a message from pipe!

**3、分析结果:****⭐⭐⭐⭐⭐

本题与上题不同,是由父进程写入管道,子进程读出内容,这是一种单向通信。 代码编写思路: 第一步-创建管道。 第二步-创建子进程。 第三步-父进程写入管道。 第四步-子进程从管道中读取信息并写入标准输出。 第五步-再一次重复第三步和第四步。

🍀【实验感想】: **1、🌟⭐管道通信的特点:**⭐🌟

(1)管道是半双工的,先进先出的,它把一个进程的输出和另一个进程的输入连接在一起 (2)一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据

**2、🌟⭐无名管道作用:**🌟⭐

用于父子进程之间的通信。创建管道——读管道——写管道——关闭管道。管道用于不同进程间的通信,通常先创建一个管道,在通过fork函数创建一个子进程,该子进程会继承父进程所创建的管道。

***喜欢的朋友可以留下你的赞哦~*** 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3