进程的管道通信

记录于2022.7.7——南林操作系统课程设计心得

ps:这个实验也是让我写了很长时间


<任务>

     编写一段程序,实现进程的管道通信。使用系统调用pipe()建立一条管道线。两个子进程p1和p2分别向管道写信息,而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <iostream>int main() {// 用于存储文件描述符(相当于指针,记录的是下标)int fd[2];    // 定义两个进程变量pid_t pid1, pid2;// 写空间(用于暂存写入管道的数据)char buffer[128];       // 父进程调用pipe()函数创建管道,得到两个文件描述符fd[0]、fd[1]pipe(fd);// fd[0]指向管道的读端,fd[1]指向管道的写端// 父进程调用fork()函数创建子进程,那么子进程也有两个文件描述符指向同一管道// 父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出// 由于管道是利用环形队列实现的,数据从写端流入管道,从读端流出,这样就实现了进程间通信// 创建子进程1while ((pid1 = fork()) == -1);          // 如果此时是子进程1在运行if (pid1 == 0) {   std::cout << "Child process 1 is working!" << std::endl;/*int lockf(int files,int function,long size)files是文件描述符;function是锁定和 解锁;1 表示锁定,0 表示解锁;size是锁定和解锁的字节数,若用 0,表示从文件的当前 位置到文件尾LOCKF主要是给文件上锁。当p2进程想要访问文件是或者给文件上锁,那么就要等待p1释放锁,此时p2处于睡眠状态但当p1解开锁时,p2就可以向管道中写入数据。其目的在于控制p1、p2同时向管道中写入数据。*/// 进程1给管道的写端上锁lockf(fd[1], 1, 0);   /*写操作:write(fd[1],buf,size)    buf:写空间,size :要写入的字符长度会从buf所指的内存中读出size个字符放到fd所指的文件中读操作:read(fd[0],buf,size)     buf:读空间,size :要读出的字符长度会从fd所指的文件中读出size个字符放入buf指针所指的内存中*/// 进程1往写空间中写入字符串sprintf(buffer, "Child process 1 is sending a message!");       // 进程1从写空间中读出40个字符存入管道中write(fd[1], buffer, 40);      // 休眠1秒sleep(1);          // 进程1给管道的写端解锁lockf(fd[1], 0, 0);             exit(0);}else {// 创建进程2while ((pid2 = fork()) == -1);  // 如果是进程2在运行if (pid2 == 0) {     std::cout << "Child process 2 is working!" << std::endl;// 进程2给管道的写端上锁lockf(fd[1], 1, 0);             // 进程2往写空间中写入字符串sprintf(buffer, "Child process 2 is sending a message!");   // 进程2从写空间中读出40个字符放入管道中write(fd[1], buffer, 40);      // 休眠1秒sleep(1);        // 进程2给管道的写端解锁lockf(fd[1], 0, 0);            exit(0);}else {  // 如果是父进程执行std::cout << "Parent process is working!" << std::endl;// 读空间(存放从管道中读出的数据)char s[100];                    // 从管道中读出40个字符存入s中read(fd[0], s, 40);             std::cout << s << std::endl;// 从管道中读出40个字符存入s中read(fd[0], s, 40);             std::cout << s << std::endl;exit(0);}}return 0;
}

结果:

 

 分析:当父进程开始执行时,输出“Parent process is working!”,然后执行read(fd[0], s, 40)语句,由于此时fd中的字符数小于要求取出的字符数(40),会引起阻塞,此时操作系统进行进程调度,在该运行结果中,可以看到,操作系统为进程1分配处理机,进程1开始执行,输出“Child process 1 is working!”,当进程1执行完毕后,由于进程1已经向fd中写入了40个字符,此时父进程由阻塞变为就绪状态,操作系统进行进程调度,在本次运行结果中,可以看到,此时操作系统为父进程分配处理机,父进程开始执行,输出“Child process 1 is sending a message!”,然后再次执行read(fd[0], s, 40)语句,由于此时fd中的字符数仍小于要求取出的字符数(40),会引起阻塞,此时操作系统进行进程调度,为进程2分配处理机,进程2开始执行,输出“Child process 2 is working!”,待进程2执行完毕后,此时父进程由阻塞状态变为就绪状态,操作系统进行进程调度,将处理机分配给父进程,父进程开始执行,输出“Child process 2 is sending a message!”,执行完毕。


这一块其实需要查阅大量的资料才能理解,比如fd的作用,pipe()函数的作用、lockf()函数的作用等,我这里的注释简要写了下,如果不太能理解,可以查查具体函数的作用,来加以理解

本文链接:https://my.lmcjl.com/post/9956.html

展开阅读全文

4 评论

留下您的评论.