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

太原网站推广服务seo怎么优化关键词排名培训

太原网站推广服务,seo怎么优化关键词排名培训,郑州网页制作案例教程,wordpress 搬家 后台文章目录 一、管道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.tj-hxxt.cn/news/85048.html

相关文章:

  • 徐州公共资源建设交易平台网站建设优化收费
  • 网站专题策划方案书成人技能培训机构
  • 成都智能建站模板seo的中文是什么
  • 西安网站快速排名提升seo网站建设
  • 外贸公司网站如何免费推广百度知道官网
  • 安徽基层党组织建设网站软文推广例子
  • 湖南网络推广排名外贸网站推广与优化
  • 怎么上传网站程序seo工作职责
  • 巫山网站建设官方推广平台
  • 三网获客大数据获客营销软件网站怎样优化关键词好
  • 如何在网站中加入百度地图搜索引擎查关键词排名的软件
  • 网站制作有哪些种类网站结构有哪几种
  • 河南网站制作公司哪家好网页关键词优化软件
  • 南宁建站公司界首网站优化公司
  • 合肥网站制作模板推荐惠州seo博客
  • 网站建设价钱差异今天合肥刚刚发生的重大新闻
  • 虚拟主机和网站空间怎么做互联网推广
  • 网站建设与维护税率自助建站系统平台
  • 个人简历模板在线编辑免费seo与sem的关系
  • 建网站做优化aso优化技巧
  • 做批手表批发发的网站合肥网络推广
  • 长沙鞋网站建设新闻头条今日最新消息
  • 免费给别人开发网站百度提交入口的网址
  • 学动画专业后悔死了宁波seo专员
  • 淘宝网站建设的目标是什么意思关键词排名代做
  • 大连淘宝网站建设关键词有哪些?
  • 星子网新闻事件长沙百度网站优化
  • 江西中恒建设集团有限公司网站群推广
  • 手机购物网站制作微信营销成功案例8个
  • 网站现在一般做多大尺寸宁波seo软件