zoukankan      html  css  js  c++  java
  • linux 几种服务类型

     采集来自于

    https://blog.csdn.net/hguisu/article/details/7453390

    https://blog.csdn.net/limo120621/article/details/52757390

     https://blog.csdn.net/tennysonsky/article/details/45671215

    综上,在选择select,poll,epoll时要根据具体的使用场合以及这三种方式的自身特点。

    1、表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。

    2、select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善

    同步/异步与阻塞/非阻塞经常看到是成对出现:

    同步阻塞,异步非阻塞,同步非阻塞

    同步与异步

    同步和异步的关注点在于消息通信机制:对于同步而言,是调用者主动等待调用结果,不得到结果不返回。而对于异步,调用在发出后不等结果便返回了,而后被调用者通过状态、通知来告知调用者,或通过回调函数进行处理。

    《Unix网络编程:卷一》6.2.7节中如此描述同步和异步IO:

    • 同步I/O操作 (synchronous I/O operation) :导致请求进程阻塞,直到I/O操作完成;
    • 异步I/O操作 (asynchronous I/O operation):不导致请求进程阻塞。

    根据这个定义,阻塞式IO,非阻塞IO和IO复用这三个模型均属于同步IO,因为在内核数据准备好时,进程调用的IO操作(read、recv)会将数据拷贝至用户空间,此时应用进程将被阻塞。而对比此时的异步IO,当进程发起IO操作调用后直接返回,直到1.数据准备就绪 2.数据由内核拷贝至用户空间 这两个操作完成后被告知IO操作已经完成,在此过程中应用进程完全没有被阻塞。所以,阻塞和非阻塞是针对同步IO而言,对于异步IO而言没有所谓阻塞和非阻塞之分。

    总的而言,在处理IO操作时,阻塞和非阻塞都是同步IO,只有使用特殊 API 时才属于异步IO。

    这里写图片描述

    补充:对于IO复用模型中的epoll调用,因为epoll函数采用 mmap的机制, 使得内核的套接字缓冲区和用户空间中的缓冲区共享了,从而省去了将数据拷贝至用户空间这一步骤,这也意味着, 当epoll回调上层的回调函数来处理套接字数据时, 数据已经从内核层 “自动” 到了用户空间,所以epoll通知应用进程时,数据已经到达了用户空间,这时的read/recv等调用只用读取用户空间中的缓冲区了,而不用进行拷贝操作了。所以epoll这个调用很多时候会被误理解为异步IO,但是epoll在告知应用进程前还是被阻塞了,只不过将阻塞点由IO系统调用转移到了epoll这个系统调用上,所以IO复用模型中的epoll虽然在业务逻辑上有异步,但是从IO操作层面上而言还是属于同步IO的。


    而poll与select的主要区别在于,select需要为读、写、异常事件分配创建一个描述符集合,最后轮询的时候,需要分别轮询这三个集合。而poll只需要一个集合,在每个描述符对应的结构上分别设置读、写、异常事件,最后轮询的时候,可以同时检查三种事件。poll与select在处理思想上是同一个层次,当然poll相对于select又优化,而epoll,则是完全不同的机制,有本质上的区别。

    对于select模型,大多都是说他的缺点,实际上我的观点有点不一样,select模型的跨平台性是比较好的,开发也比较简单,只有当个进程连接数的限制,以及其性能随着连接数增长下降的问题,实际上都得根据项目的实际情况而定的。在内部分布式通讯中,几乎所有的连接都是活跃的情况下,select模型并不比epoll的性能差,只是在一些应用中大部分连接都不活跃的情况,epoll的使用效果要高,可以使单台服务器的承载量大大增加,实际上游戏服务器中玩家绝大部发是活跃的,因此实际性能也还不错。

    与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。


    设置为非阻塞的方法有:

        (1)创建socket的时候,指定socket是异步的,在type的参数中设置SOCK_NONBLOCK标志即可。

    1. int socket(int domain, int type, int protocol);  
    2. int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);  

        (2)使用fcntl函数: 

     
    1. fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);  

        (3)使用ioctl函数:

    1. ioctl(sockfd, FIONBIO, 1);  //1:非阻塞 0:阻塞  

  • 相关阅读:
    .Net使用分布式缓存 C# 使用Redis
    微信申请退款API~~开发
    微信支付和支付宝支付分账接口文档
    Android xUtils3.0使用手册(一)- 基础功能使用
    支付宝支付开发——当面付条码支付和扫码支付
    vue开源项目汇总
    Azure和插件发布
    SqlServer数据库优化笔记
    企业微信通过PostMan获取accesstoken与管理员信息方法
    VisualStudio插件自动加载
  • 原文地址:https://www.cnblogs.com/studyNT/p/9420713.html
Copyright © 2011-2022 走看看