Linux IO模型漫谈(4)- 非阻塞IO

简介:

首先先说一下,阻塞IO会在哪些地方阻塞住呢?输入操作read, 输出操作write,接受请求操作accept,发送请求操作connect,这四个地方阻塞进程。

非阻塞IO的模型图示在前面的章节有讲过,它和阻塞IO的最大区别就是:如果连接或者操作不能立即建立,那么连接的建立照样能发起,只是会返回一个错误信息。

同样,先说明几个用到的函数和操作:

1 fcntl函数

其全名为”file control“。顾名思义,fcntl可以执行各种操作符控制操作。

#include <fcntl.h>

int fcntl(int fd, int cmd, .. /* int arg */)

第一个参数fd是文件描述符

第二个参数cmd是操作命令,比如设置套接字阻塞非阻塞的命令为F_SETFL, 设置套接字属主的命令为F_SETOWN

第三个参数以后,是操作命令的参数。比如设置非阻塞IO型的F_SETFL的参数为O_NONBLOCK

所以设置非阻塞IO的典型设置代码为:

flags = flags | O_NONBLOCK;

fcntl(fd, F_SETFL, flags);

2 非阻塞IO返回的错误

对于不能满足的非阻塞IO操作,System V会返回EAGAIN错误,而源自Berkeley的实现返回EWOULDBLOCK。大多数当前系统把这两个错误码定义为相同的值。

对不能满足的非阻塞IO连接,系统会返回EINPROGRESS

按照非阻塞的定义,我们只需要将cli做下面修改:

3客户端代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>


int main(int argc, char* argv[])
{
    int socketfd, n;
    socketfd = socket(AF_INET, SOCK_STREAM, 0);
    fcntl(socketfd, F_SETFL, O_NONBLOCK);
    
    struct sockaddr_in serv_addr;
		
    bzero((char *)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(7777);

    for(;;) {
        if(n = connect(socketfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
            if(errno == EINPROGRESS) {
                printf("EINPROGRESS\n");
            }
        } else {
            break;
        }
    }
		
    write(socketfd, "client message", 14);
		
    char buffer[256];
    bzero(buffer, 256);
    read(socketfd, buffer, 255);
		
    printf("server return message:%s\r\n", buffer);
		
    return 0;

}
 

运行方式:

1 server不启动

2 client启动,则会在connect这个地方进入无限循环。

 

好吧,是不是觉得有问题?

1 这种模型,客户端使用轮询不断调用IO操作,那么,CPU就会一直用于轮询,造成cpu的浪费。

2 这种模型,代码量比阻塞的模型大很多

所以这个模型实际上是很少使用的。

目录
相关文章
|
3月前
|
Linux
Linux 下的五种 IO 模型详细介绍
根据上述定义,我们的前4种模型——阻塞式I/O模型、非阻塞式I/O模型、I/O复用模型和信号驱动式I/O模型都是同步I/O模型,因为其中真正的I/O操作(recvfrom )将阻塞进程。异步请求:A调用B,B的处理是异步的,B在接到请求后先告诉A我已经接到请求了,然后异步去处理,处理完之后通过回调等方式再通知A。和上面的阻塞IO模型相比,非阻塞IO模型在内核数据没准备好,需要进程阻塞的时候,就返回一个错误,以使得进程不被阻塞。阻塞请求:A调用B,A一直等着B的返回,别的事情什么也不干。
35 0
Linux 下的五种 IO 模型详细介绍
|
3月前
|
Unix Linux
Linux五种IO模型
Linux五种IO模型
|
3月前
|
网络协议 Linux API
Linux异步IO之 io_uring 详解及使用代码示例
Linux异步IO之 io_uring 详解及使用代码示例
|
9月前
|
网络协议 Java Unix
【Java面试】说说NIO和IO的区别,再说说Linux支持那些IO模型?
【Java面试】说说NIO和IO的区别,再说说Linux支持那些IO模型?
72 0
|
存储 安全 Java
Linux基础IO【文件理解与操作】
文件操作是 基础IO 学习的第一步,我们在 C语言 进阶中,就已经学习了文件相关操作,比如 fopen 和 fclose,语言层面只要会用就行,但对于系统学习者来说,还要清楚这些函数是如何与硬件进行交互的
17150 3
Linux基础IO【文件理解与操作】
|
存储 缓存 监控
|
网络协议 Linux 调度
Linux 五种Io模型
异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。比如:调用aio_read系统调用时,不必等IO操作完成就直接返回,调用结果通过信号来通知调用者。
Linux 五种Io模型
|
缓存 运维 Unix
浅析Linux中的五种IO模型(上)
IO是什么 I/O(Input/Output),中文名为输入/输出,指的是一切操作程序或设备与计算机之间发生的数据传输的过程。它分为IO设备和IO接口两个部分。
|
网络协议 Linux 调度
浅析Linux中的五种IO模型(下)
IO是什么 I/O(Input/Output),中文名为输入/输出,指的是一切操作程序或设备与计算机之间发生的数据传输的过程。它分为IO设备和IO接口两个部分。
|
缓存 算法 固态存储
浅淡linux的IO和磁盘IO的检测
浅淡linux的IO和磁盘IO的检测
浅淡linux的IO和磁盘IO的检测