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

h5手机网站开发国外音乐网站设计

h5手机网站开发,国外音乐网站设计,高端的西安网页设计,建设公司加盟文章目录 一、管道1. 匿名管道2. 命名管道 进程具有独立性,因此进程间通信的前提是两个进程能看到同一份资源 一、管道 对于进程打开的内存文件,操作系统是以引用计数的方式创建的 file 结构体,如果让两个进程与同一个 file 结构体关联&…

文章目录

  • 一、管道
    • 1. 匿名管道
    • 2. 命名管道

进程具有独立性,因此进程间通信的前提是两个进程能看到同一份资源

一、管道

对于进程打开的内存文件,操作系统是以引用计数的方式创建的 file 结构体,如果让两个进程与同一个 file 结构体关联,便可以让两个进程看到同一份资源

由于 file 结构体的缓冲区只有一个,因此只能让一个进程以写的方式,另一个进程以读的方式打开同一个文件,这样便实现了单向的进程间通信
在这里插入图片描述
操作系统提供了仅在内存中创建 file 结构体(不在磁盘上创建对应的文件),这种特殊的文件称为管道文件,其中没有名字的称为 匿名管道,有名字的称为 命名管道

1. 匿名管道

进程创建匿名管道成功后,会以读和写两种方式打开管道文件,因此匿名管道通常用于父子进程的进程间通信

系统调用 pipe,头文件 unistd.h

  • int pipe(int pipefd[2]),创建匿名管道

返回值:匿名管道创建成功返回 0,出错返回 -1,并且 errno 被设置为相应的出错信息

参数:pipefd 为输出型参数,pipefd[0] 存储读端文件描述符,pipefd[1] 存储写端文件描述符

父子进程通信的步骤:

  • 父进程创建管道
    父进程以读和写两种方式打开管道文件
  • 创建子进程
    子进程会拷贝父进程的文件描述符表,因此子进程也会以读和写两种方式打开同一个管道文件
  • 父进程和子进程分别关闭自己不需要的读端或写端
    一个进程向管道中写入,另一个进程从管道中读取

子进程向匿名管道写入,父进程从匿名管道读取

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;int main()
{// 创建匿名管道// pipefd[0] 表示读// pipefd[1] 表示写int pipefd[2] = { 0 };if (pipe(pipefd) < 0){// 创建匿名管道失败cout << "匿名管道创建失败: " << errno << " " << strerror(errno) << endl;exit(1);}// 创建子进程pid_t id = fork();assert(id != -1);if (id == 0){// 子进程向匿名管道写入,需要关闭读close(pipefd[0]);// 开始通信int cnt = 0;char buffer[64];while (true){snprintf(buffer, sizeof(buffer), "我是子进程,这是我给你发的第 %d 个信息", ++cnt);// 向匿名管道中写入write(pipefd[1], buffer, strlen(buffer));cout << cnt << endl;// sleep(1); // 让写端慢一点// if (cnt == 3) break; // 模拟写端关闭}close(pipefd[1]);exit(0);}// 父进程从匿名管道读取,需要关闭写close(pipefd[1]);// 开始通信char buffer[64];while (true){// 从匿名管道中读取// sleep(3); // 让读端慢一点// sleep(3); break; // 模拟读端关闭int n = read(pipefd[0], buffer, sizeof(buffer) - 1);if (n > 0){        buffer[n] = '\0';cout << buffer << endl;}else if (n == 0){cout << "写端已经关闭,我读到文件结尾了" << endl;break;}else{cout << "读取错误" << endl;break;}}close(pipefd[0]);// 读端关闭,写端会收到 13 号信号 SIGPIPEint status;waitpid(id, &status, 0);cout << "子进程退出信号: " << (status & 0x7F) << endl;return 0;
}
  • 放开子进程代码中的 sleep(1),让写端慢一点,匿名管道中没有数据时,读端会等待写端写入
    在这里插入图片描述
  • 放开父进程中的 sleep(3),让读端慢一点,匿名管道中写满数据时,写端会等待读端读取
    在这里插入图片描述
  • 放开子进程中模拟写端关闭的代码,并且让写端慢一点,写端关闭后,读端读取完匿名管道中的数据后,读端会读取到文件结尾
    在这里插入图片描述
  • 放开子进程中模拟读端关闭的代码,并且让写端慢一点,读端关闭时,此时匿名管道无意义,操作系统会向写端发送 SIGPIPE 13 号信号
    在这里插入图片描述

命令行中的 | 即为匿名管道,| 会将前一个进程的标准输出重定向到匿名管道,后一个进程的标准输入重定向到匿名管道

在这里插入图片描述

通过匿名管道创建进程池:

// processpool.hpp
#include <iostream>
#include <vector>
#include <functional>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>namespace starrycat
{class EndPoint{public:EndPoint(){}EndPoint(pid_t cid, int wfd) : _cid(cid), _wfd(wfd){}~EndPoint(){}public:pid_t _cid;int _wfd;};const int NUM = 5;class ProcessPool{using fun_t = std::function<void(int)>;public:ProcessPool(fun_t Command, int num = NUM){std::vector<int> tmpfd; // 保存子进程不需要的父进程的文件描述符for (int i = 0; i < num; ++i){// 创建管道int pipefd[2] = {0};if (pipe(pipefd) < 0){std::cout << "创建管道失败: " << errno << " " << strerror(errno) << std::endl;exit(1);}// 创建子进程int id = fork();assert(id != -1);if (id == 0){// 子进程从管道中读取,需要关闭写close(pipefd[1]);for (auto e : tmpfd) close(e); // 关闭不需要的文件描述符// 开始通信while (true){// 读取四字节整数的命令int cmd = 0;int n = read(pipefd[0], &cmd, sizeof(int));if (n == sizeof(int)){// 测试std::cout << getpid() << " ";// 执行命令Command(cmd);}else if (n == 0){// 测试std::cout << getpid() << " 读取到文件结尾了" << std::endl;break;}else{std::cout << "读取异常" << std::endl;break;}}close(pipefd[0]);exit(0);}// 父进程向管道中写入,需要关闭读close(pipefd[0]);_endPoints.push_back(EndPoint(id, pipefd[1]));tmpfd.push_back(pipefd[1]);}}ProcessPool(const ProcessPool &p) = delete;ProcessPool &operator=(const ProcessPool &p) = delete;~ProcessPool(){for (auto& e : _endPoints) {close(e._wfd);waitpid(e._cid, nullptr, 0);// 测试std::cout << "等待子进程:" << e._cid  << "成功" << std::endl;sleep(1);}}// 规定命令为四字节整数void push(int command){// 以轮训的方式调用子进程static int index = 0;write(_endPoints[index]._wfd, &command, sizeof(int));index++;index %= _endPoints.size();}private:std::vector<EndPoint> _endPoints;};
}// myctrlprocess.cc
#include "processpool.hpp"
#include <iostream>
#include <string>using namespace std;// 子进程个数
const int num = 5;void PrintLog()
{cout << "打印日志任务,正在被执行..." << endl;
}void InsertMySQL()
{cout << "执行数据库任务,正在被执行..." << endl;
}void NetQuest()
{cout << "执行网络请求任务,正在被执行..." << endl;
}void CommandError()
{cout << "任务不存在" << endl;
}void Command(int cmd)
{switch (cmd){case 0:PrintLog();break;case 1:InsertMySQL();break;case 2:NetQuest();break;default:CommandError();break;}
}int main()
{starrycat::ProcessPool ppool(Command);int command = 0;while (true){cout << "请输入命令: ";cin >> command;// 测试if (command == -1) break;ppool.push(command);sleep(1);}return 0;
}

2. 命名管道

命名管道支持两个毫不相关的进程通信,其使用和文件一样

系统调用 mkfifo,头文件 sys/types.h、sys/stat.h

  • int mkfifo(const char *pathname, mode_t mode),创建命名管道

返回值:命名管道创建成功返回 0,出错返回 -1,并且 errno 被设置为相应的出错信息

参数:

  • pathname 表示创建命名管道的路径名(如果只有文件名,则表示在进程所在的路径下创建)
  • mode 表示创建命名管道的文件权限,受 umask 影响

客户端向命名管道写入,服务端从命名管道读取

// namepipe.h
#pragma once// 命名管道文件名
const char* const fifoname = "fifo";// client.cc
#include "namepipe.h"
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>using namespace std;int main()
{// 以写方式打开命名管道int wfd = open(fifoname, O_WRONLY);if (wfd < 0){cout << "打开文件失败" << errno << " " << strerror(errno) << endl;exit(1);}// 开始通信char buffer[1024];while (true){cout << "请输入: ";char* str = fgets(buffer, sizeof(buffer), stdin);if (str == NULL){cout << "客户端退出" << endl;break;}buffer[strlen(buffer) - 1] = '\0'; // 去掉输入的回车符// 输入 quit 表示客户端退出if(strcmp(buffer, "quit") == 0) {cout << "客户端退出" << endl;break;}// 向命名管道写入write(wfd,  buffer, strlen(buffer));}close(wfd);return 0;
}// server.cc
#include "namepipe.h"
#include <iostream>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>using namespace std;int main()
{// 创建命名管道umask(0);  // 设置进程的权限掩码if (mkfifo(fifoname, 0666) < 0){cout << "创建管道失败: " << errno << " " << strerror(errno) << endl;exit(1);}// 以读方式打开命名管道int rfd = open(fifoname, O_RDONLY);if (rfd < 0){cout << "打开文件失败" << errno << " " << strerror(errno) << endl;}// 开始通信char buffer[1024];while (true){// 从命名管道读取int n = read(rfd, buffer, sizeof(buffer) - 1);if (n > 0){buffer[n] = '\0';cout << "客户端: " << buffer << endl;}else if (n == 0){cout << "客户端退出了,服务端也退出" << endl;break;}else{cout << "读取异常" << endl;break;}}close(rfd); unlink(fifoname); // 删除命名管道return 0;
}

先启动 myserver,在启动 myclient

在这里插入图片描述

命名管道和匿名管道的通信特性是一样的

mkfifo 文件名
功能:创建命名管道

在这里插入图片描述

http://www.yayakq.cn/news/679182/

相关文章:

  • 网站怎么做才能将名声打响免费的电脑优化软件
  • 注册公司如何做网站网站建设商务代表故事
  • 怎么在百度建设网站wordpress常见的15个问题
  • 域名注册网站制作营销策划公司名字
  • 找外包做网站要多久自己制作手机app软件
  • 网站 谁建设 谁负责郑州网站建设修改
  • 代做硬件毕业设计网站山东济南市网站建设
  • 北京城乡建设学校网站wordpress自适应框架
  • 在哪些网站能接到活做做的最好的手机网站
  • 关于网站建设的折页广告注册门户网站
  • 平台式网站模板下载地址新校区建设网站管理规定
  • 怎么做网站流量赚钱吗温州网站建设价格
  • 东营网站设计制作zac博客seo
  • asp与sql网站建设wordpress搭建个人博客linux
  • 江门网站优化快速排名互联网传媒 网站
  • 易县网站建设电子商务网站开发实训总结
  • 做网站和做网页有什么区别网站开发seo要求
  • 商城开发网站wordpress 4.9.6
  • 北京哪些做网站的公司好望京做网站
  • 成都网站建设网络公司学校网站建设的风险分析
  • 网站建设期末论文建设银行信用卡中心网站首页
  • 儿童教育网站模板凡科门店通
  • 惠州网站制作推广成都市seo网站公司
  • 东莞网站推广行者seo08网站建设费用无形资产如何摊销
  • 嘉定区网站建设注册贸易公司流程及费用
  • node js 网站开发企业网站快速优化排名
  • 河源市建设网站企业怎样做好网站建设
  • 大连建设银行网站网站建好了怎么做淘宝客
  • 用自己照片做衣服_杯子的是哪个网站中国建筑招聘网官网
  • 网站开发 案例详解推广赚佣金项目