进程间并发通信-IO多路复用

2024-06-03 17:52

本文主要是介绍进程间并发通信-IO多路复用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 select

1.1 源码示例

/*************************************************************************> File Name: write.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 14时50分23秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int fd=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_WRONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 接收终端输入并写入管道文件描述符-向管道写数据 */while(1){fgets(tmpbuff,sizeof(tmpbuff),stdin);write(fd,tmpbuff,strlen(tmpbuff));}/* 4 关闭管道 */close(fd);return 0;
}
/*************************************************************************> File Name: read.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 14时34分49秒************************************************************************/#include<stdio.h>#include <signal.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>int main(void)
{int fd=0;fd_set rdfds;fd_set tmpfds;int ret=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_RDONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 文件描述符集的操作 - 4个宏 - FD_ZERO(initialize)-FD_SET(create)-FD_CLR(delete)-FD_ISSET(retrieve) *//* 3.1 初始化文件描述符集合 */FD_ZERO(&rdfds);//清除文件描述符集合 - 初始化文件描述符集合/* 3.2 增加文件描述符至文件描述符集合 */FD_SET(fd,&rdfds);//添加文件描述符至文件描述符集FD_SET(0,&rdfds);/* 4 管道读(写) - 终端和管道-谁来数据就读谁 */while(1){/* 4.1 初始化监听文件描述符集合 */tmpfds=rdfds;/* 4.2 监听文件描述符集合 -> 监听多个文件描述符,直到有一个或者多个文件描述符准备进行某类IO操作 *//*注意: 一旦监听到某个文件描述符准备进行IO操作,那么这个文件描述符监听前后状态就发生了变化 ( 非ready状态->ready状态 ),* 所以要想一直对某个文件描述符进行监听,每次调用select之前都要重置该文件描述符状态为监听之前的状态(即非ready状态)*/ret=select(fd+1,&tmpfds,NULL,NULL,NULL);if(-1==ret){perror("fail to select");return -1;}/* 4.3 查询文件描述符集合中某个文件描述符状态是否发生改变 */if(FD_ISSET(fd,&tmpfds)){memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("fifo: %s\n",tmpbuff);}if(FD_ISSET(0,&tmpfds)){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);printf("stdin: %s\n",tmpbuff);}}/* 5 关闭文件描述符 */close(fd);return 0;
}

1.2 运行结果

1.3 分析总结

2 poll

1.1 源码示例

/*************************************************************************> File Name: write.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 16时30分10秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int fd=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_WRONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 接收终端输入并写入管道文件描述符-向管道写数据 */while(1){fgets(tmpbuff,sizeof(tmpbuff),stdin);write(fd,tmpbuff,strlen(tmpbuff));}/* 4 关闭管道 */close(fd);return 0;
}
/*************************************************************************> File Name: read.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 16时30分10秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>#include <poll.h>int main(void)
{int fd=0;struct pollfd fds[2];int fready=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_RDONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 初始化文件描述符状态结构体数组*/fds[0].fd=fd;//添加文件描述符至数组fds[0].events=POLLIN;//修改文件描述符状态为 准备读fds[1].fd=0;fds[1].events=POLLIN;/* 4 管道读(写) - 终端和管道-谁来数据就读谁 */while(1){/* 4.1 监听文件描述符状态结构体数组 */fready=poll(fds,2,-1);//文件描述符数组(数组)-文件描述符个数(数组长度)-超时时间(-1 一直等)if(-1==fready){perror("fail to poll");return -1;}/* 4.2 查询文件描述符状态 - 通过位掩码方式查询 - 置位 */if(fds[0].revents&POLLIN){memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("fifo: %s\n",tmpbuff);}if(fds[1].revents&POLLIN){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);printf("stdin: %s\n",tmpbuff);}}/* 5 关闭管道 */close(fd);
}

1.2 运行结果

1.3 分析总结

3 epoll

1.1 源码示例

/*************************************************************************> File Name: write.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 17时22分26秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int fd=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_WRONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 接收终端输入并写入管道文件描述符-向管道写数据 */while(1){fgets(tmpbuff,sizeof(tmpbuff),stdin);write(fd,tmpbuff,strlen(tmpbuff));}/* 4 关闭管道 */close(fd);return 0;
}
/*************************************************************************> File Name: read.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 17时22分26秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>#include <sys/epoll.h>int main(void)
{int fd=0;int epfd=0;struct epoll_event env;int fready=0;int i=0;struct epoll_event retenv[2];char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_RDONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 创建内核事件表 - 并返回表头 */epfd=epoll_create(2);//预期添加到事件表的文件描述符数量if(-1==epfd){perror("fail to epoll_create");return -1;}/* 4 初始化内核epoll事件结构体 - 数据类型 -初始化事件结构体 */env.events=EPOLLIN;//修改文件描述符状态为 准备读 - 事件状态 - 非ready态env.data.fd=fd;//文件描述符 - 这里指有名管道/* 5 操作内核epoll事件表 - EPOLL_CTL_ADD(增-fd)-EPOLL_CTL_DEL(删-fd)-EPOLL_CTL_MOD(改-fd事件) */epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&env);//建立文件描述符fd及其对应的事件env,并将文件描述符fd添加到epoll事件表epfd中env.events=EPOLLIN;env.data.fd=0;epoll_ctl(epfd,EPOLL_CTL_ADD,0,&env);//终端也将发生同样的事件(EPOLLIN),所以将终端(此指stdin)也加入至该内核事件表/* 6 管道读(写) - 终端和管道-谁来数据就读谁 */while(1){/* 6.1 监听内核epoll事件表,并返回ready态的文件描述符数量 */fready=epoll_wait(epfd,retenv,2,-1);//这里通过结构体数组retenv作为出参,将ready态的文件描述符带出-ready态if(-1==fready){perror("fail to epoll_wait");return -1;}/* 6.2 遍历所有ready态的文件描述符 */for(i=0;i<fready;i++){/* 通过ready态文件描述符进一步确认是哪个文件描述符状态被置位 -* 检测(类似于IO输入检测-key检测的思想-位掩码)-查询*/if(retenv[i].data.fd==0){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);printf("stdin: %s\n",tmpbuff);}else if(retenv[i].data.fd==fd){memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("fifo: %s\n",tmpbuff);}}}/* 6 关闭管道*/close(fd);
}

1.2 运行结果

1.3 分析总结

这篇关于进程间并发通信-IO多路复用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027694

相关文章

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

Linux中的进程间通信之匿名管道解读

《Linux中的进程间通信之匿名管道解读》:本文主要介绍Linux中的进程间通信之匿名管道解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基本概念二、管道1、温故知新2、实现方式3、匿名管道(一)管道中的四种情况(二)管道的特性总结一、基本概念我们知道多

Linux进程终止的N种方式详解

《Linux进程终止的N种方式详解》进程终止是操作系统中,进程的一个重要阶段,他标志着进程生命周期的结束,下面小编为大家整理了一些常见的Linux进程终止方式,大家可以根据需求选择... 目录前言一、进程终止的概念二、进程终止的场景三、进程终止的实现3.1 程序退出码3.2 运行完毕结果正常3.3 运行完毕

Windows命令之tasklist命令用法详解(Windows查看进程)

《Windows命令之tasklist命令用法详解(Windows查看进程)》tasklist命令显示本地计算机或远程计算机上当前正在运行的进程列表,命令结合筛选器一起使用,可以按照我们的需求进行过滤... 目录命令帮助1、基本使用2、执行原理2.1、tasklist命令无法使用3、筛选器3.1、根据PID

Nginx实现高并发的项目实践

《Nginx实现高并发的项目实践》本文主要介绍了Nginx实现高并发的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用最新稳定版本的Nginx合理配置工作进程(workers)配置工作进程连接数(worker_co

linux本机进程间通信之UDS详解

《linux本机进程间通信之UDS详解》文章介绍了Unix域套接字(UDS)的使用方法,这是一种在同一台主机上不同进程间通信的方式,UDS支持三种套接字类型:SOCK_STREAM、SOCK_DGRA... 目录基础概念本机进程间通信socket实现AF_INET数据收发示意图AF_Unix数据收发流程图A

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.