当前位置: 首页 > news >正文

1元做网站方案各种软件开发定制

1元做网站方案,各种软件开发定制,spark 网站开发,北京建设信息咨询中心网站文章目录 📕 进程间通信介绍📕 匿名管道原理使用读写规则特点 📕 命名管道原理使用匿名管道和命名管道的区别 📕 进程间通信介绍 进程间通信,顾名思义,就是两个进程之间的 “交流” ,我们知道&…

文章目录

  • 📕 进程间通信介绍
  • 📕 匿名管道
    • 原理
    • 使用
    • 读写规则
    • 特点
  • 📕 命名管道
    • 原理
    • 使用
    • 匿名管道和命名管道的区别

📕 进程间通信介绍

进程间通信,顾名思义,就是两个进程之间的 “交流” ,我们知道,进程是相互独立的,也就是说,正常情况下,两个进程之间无法传递消息,但是有时候又需要 进程间通信,如下,这是进程间通信的目的。

  • 数据传输:一个进程需要将它的数据发送给另一个进程
  • 资源共享:多个进程之间共享同样的资源。
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

要达到这些目的,就需要使用一些技术来完成进程间通信。以下是三类技术,管道 、System V、POSIX 。本篇文章主要讲解管道的方法。

  • 管道
    • 匿名管道pipe
    • 命名管道
  • System V IPC
    • System V 消息队列
    • System V 共享内存
    • System V 信号量
  • POSIX IPC
    • 消息队列
    • 共享内存
    • 信号量
    • 互斥量
    • 条件变量
    • 读写锁

那么什么是管道呢?
管道是Unix中最古老的进程间通信的形式。我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。

听起来很抽象,可以了解一下管道的原理,就明白了!

📕 匿名管道

原理

如下图,一个进程可以打开多个文件,其 file_struct 里面的文件描述符 0、1、2 分别指向了内存里的 三个 struct file,在文件描述符那篇文章有提到,每一个 struct file 都有对应的缓冲区,是内存级别的。(要理解这里的内容,首先要了解文件描述符哦,可以看一下这篇文章:【Linux】文件描述符)

所以,我们可以用操作系统创建管道的系统调用,打开一个文件(下图中绿色部分),分别以 读、写 方式打开(具体原因下文会讲),然后这个打开的文件会对应有 struct file 和 缓冲区。这些都是操作系统的行为,所以即使磁盘上没有对应的文件,也可以这样打开。当不需要使用管道的时候,直接将内存里的对应 struct file 和缓冲区释放即可。

所以,管道就是一个妥妥的内存级的文件!!

请添加图片描述

此时,我们再 fork() ,产生一个子进程,子进程会继承父进程的绝大多数内容,包括 file_struct ,但是子进程并不会创建新的文件,因为这是属于文件系统范畴了, fork() 只是创建子进程。此时,子进程同样地也以读写的方式打开了父进程创建的管道文件
请添加图片描述

然后,由于管道是半双工的,所以要在父子进程里面,一个关闭读端,一个关闭写端,就可以完成进程间通信的基本条件。
比如这里,我需要父进程写入信息,子进程读取父进程的信息,那么就把父进程的读端关闭,子进程的写端关闭,这样子就是父进程写、子进程读!

请添加图片描述

使用

创建匿名管道需要用到 pipe() 系统调用。

头文件:#include <unistd.h>
功能:创建一个匿名管道
原型
int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码

使用匿名管道需要注意几点,首先是要在创建子进程之前,创建管道。否则子进程无法继承父进程的文件描述符。
其次,不要忘记关闭读端或者写端。

#include <iostream>
#include <unistd.h>
#include <cerrno>
#include <string.h>
#include <stdio.h>using std::cout;
using std::endl;int main()
{int pipefd[2] = {0};// 1.创建管道int n = pipe(pipefd); // pipefd[0] 写端   pipefd[1] 读端if (n == -1){cout << "create pipe error," << errno << strerror(errno) << endl;exit(1);}// cout<<pipefd[0]<<endl<<pipefd[1];// 2.创建子进程pid_t pid = fork();// 子进程if (pid == 0){// 3.子进程写,那么关闭读端close(pipefd[0]);// 4.通信char buf[128];int cnt = 1;while (true){snprintf(buf, sizeof buf, "我是子进程,cnt:%d ,pid: %d\n", cnt++, getpid());write(pipefd[1], buf, strlen(buf));}close(pipefd[1]); // 管道声明周期随进程,所以不手动关闭,进程结束后也会自动关闭exit(1);}// 父进程// 3.父进程读,关闭写端close(pipefd[1]);// 4.通信char buf[128];while (true){sleep(3);int n = read(pipefd[0], buf, sizeof(buf) - 1); // 留出一个位置放\0if (n > 0){buf[n]='\0';cout << "我是父进程,子进程给的信息:" << buf << endl;}}close(pipefd[0]);return 0;
}

上面的 写入、读取 代码可以看出,写入速度快,读写数据慢。 写入了很多次,才读取一次。但是下图运行结果,并不是写入一次,就读取一次,而是可以写入多次,然后一次性读取。

从这里可以看出,读写不是强相关的。(这里指的是读写次数的多少)

请添加图片描述

读写规则

  • 如果读端读取了管道内的所有数据,而写端不写入,那么只能等待。
  • 如果写端将管道写满了,读端没有读取数据,那么就无法写入。
  • 如果写端关闭,读端依然打开,在读取完管道内剩余的数据之后,再次读取数据,则 read 返回0。
  • 如果读端关闭,而写端还向管道写入数据,毫无疑问这是没有意义的,操作系统不会运行这样的事情发送。所以,write 操作会产生信号SIGPIPE,进而可能导致write进程退出。

特点

  1. 单向通信(半双工)
  2. 管道的本质是文件,因为 fd 的生命周期随进程,所以管道的生命周期也是随进程的
  3. 管道通信,通常用来 对具有“血缘”关系的进程,进行进程间通信。常用于父子通信 – pipe 打开管道,并不清楚管道的名字(匿名管道)。
  4. 在管道通信中,写入的次数 和 读取的次数是不严格匹配的,读写次数的多少没有强相关,读取是按照字节流来读取的。
  5. 根据上面的读写规则,可以知道,管道具有一定的协同能力,能让 reader 和 writer 按照一定的步骤进行通信——自带同步机制。

📕 命名管道

原理

如下,一个进程打开了磁盘上的一个文件。当另一个进程(和之前的进程没有血缘关系),也打开同一个文件的时候,操作系统不会重新创建一个 struct file 对象,而是直接使用之前的。

那么,此时,两个进程就看到了同一个文件,也就可以进行进程间通信。
但是,如果这个文件是普通文件,那么数据会定期刷新的磁盘里。可是如果我们要进行进程间通信,数据就不应该被刷新到磁盘里面,而是在进程之间进行传输。所以,这就要求创建的文件是一个内存级别的文件,由此诞生了命名管道文件!不需要维护其 datablock,只需要告诉操作系统,这个文件存在!以后 两个进程可以打开这个文件,打开文件就会在内核匹配对应的缓冲区,所以两个进程就看到同一份资源!!

这个原理和上面匿名管道的原理其实是一样的!!
在这里插入图片描述

使用

命名管道可以从命令行上创建,命令行方法是使用下面这个命令:

  • $ mkfifo filename

命名管道也可以从程序里创建,相关函数有:

  • int mkfifo(const char *filename,mode_t mode);

如下是在程序里面实现命名管道,以及进程间通信。 server 进程和 client 进程进行交互。

comm.hpp 头文件

#pragma once#include<iostream>
#include<string>#define NUM 1024const std::string filename="./fifo";mode_t mode=0666;

server.cc 文件


#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include<fcntl.h>
#include <cerrno>
#include <cstring>
#include<unistd.h>#include"comm.hpp"using std::cin;
using std::cout;
using std::endl;int main()
{// 1.创建命名管道umask(0);int n = mkfifo(filename.c_str(),mode);if(n < 0){cout<<"create fifo error:"<<errno<<":"<<strerror(errno)<<endl;return 1;}cout<<"create fifo success"<<endl;// 2.开启管道文件int rfd=open(filename.c_str(),O_RDONLY);if(rfd < 0){cout<<"open fifo file error:"<<errno<<":"<<strerror(errno)<<endl;return 1;}cout<<"open fifo file success"<<endl;// 3. 开始通信char buf[NUM];while(true){// 先将缓冲区置0buf[0]=0;size_t n=read(rfd,buf,sizeof(buf)-1); // 读取是按字节流,所以去掉 \0if(n > 0){buf[n]='\0';cout<<"client#"<<buf<<endl;fflush(stdout);}else if(n==0){cout<<"client quit,i will quit either"<<endl;break;}else{cout<<errno<<":"<<strerror(errno)<<endl;}}close(rfd);unlink(filename.c_str());return 0;
}

client.cc 文件


#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include<cassert>#include "comm.hpp"using std::cin;
using std::cout;
using std::endl;int main()
{// 打开fifoint wfd=open(filename.c_str(),O_WRONLY);if(wfd < 0){cout<<"open fifo error"<<errno<<":"<<strerror(errno)<<endl;return 1;}cout<<"open fifo success"<<endl;// 写入char buf[NUM];while(true){cout<<"请输入你的信息#";char* msg=fgets(buf,sizeof(buf),stdin); // C库的函数,会默认加上 \0assert(msg);(void*)msg;size_t n=write(wfd,buf,sizeof(buf)-1);if(strcasecmp(buf,"quit") == 0) break;}close(wfd);return 0;
}

如下,server 是读端, client 是写端,只有 client 写入消息, server 才会读取,实现进程间通信。
如果单单在 server 写入消息, client 是不会读取的,因为 server是读端, client 是写端。
在这里插入图片描述

匿名管道和命名管道的区别

  • 匿名管道由pipe函数创建并打开。
  • 命名管道由mkfifo函数创建,打开用open
  • FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。
http://www.yayakq.cn/news/540120/

相关文章:

  • 唯样商城网站手机网站微信登陆
  • 网站开发项目流程网站排名如何提升
  • 遵义创意网站设计石家庄58同城招聘信息
  • 在线设计平台现状分析南昌seo网站开发
  • 网站方案制作大连市中心是哪个区
  • 长沙建站模板平台网站建设教程数据库
  • 网站开发都需要哪些图找网站做任务qq红包
  • 网站建设主要产品wordpress建小程序
  • 建设校园门户网站理由沧州网站seo公司
  • 那个网站做租赁好做外贸做网站
  • 建设信用卡积分网站网上自学电脑课程
  • 做网站备案实名需要钱吗沈阳建设工程信息网 等级中项网
  • 一定要知道的网站网站设计评级
  • dw网站建设素材易安卓开发app稳定吗
  • 台州模板建站代理北京建网站软件
  • 做一个网站的流程wordpress 响应分页
  • 利用html5 监控网站性能辽宁建设工程造价信息网官网
  • 北京地铁建设的官方网站个人备案经营网站
  • 常德人才网关键词优化是什么工作
  • 上海这边敲墙拆旧做啥网站的比较多网页设计基础考试题库及答案
  • 京东商城网站建设方案书wordpress跟php
  • 做网站没有做退钱网站怎么做可以合法让别人充钱
  • 智能建站推荐网站功能建设模块
  • 做视频链接的网站吗wordpress影视采集网站
  • 官方网站建设有限公司最好在线网站建设
  • 响应式网站设计案例专业商城网站搭建价格
  • 佛山微信网站建设多少钱成都网站建设联系电话
  • 北京高端网站建设工作自己建设网站容易吗
  • 华企立方做网站济南营销网站制作公司
  • 建设银行网上银行网站进入不了爱网站