Модель Unix пять ввода / вывода

Unix пять я модель / O:

  1. Блокировка ввод / вывод: IO приложение вызывает функцию, что приводит к блокированию приложения, если данные готовы, скопировать из ядра в пространство пользователя, или ждать вечно
  2. Неблокирующая I / O:
  3. I / O мультиплексирование (выберите и опрос)
  4. Привод сигнал ввод / вывод (SIGIO)
  5. Асинхронный ввод / вывод (POSIX.1 aio_ ряд функций)

Unix является операция ввода обычно имеет две фазы:
1, готовой ждать данных.
2, процесс копирования данных из ядра.
Для операций ввода на разъеме, первый шаг , как правило , ждать , пока данные поступают в сеть, когда приходит пакет, он копируется в буфер в ядре, второй шаг, чтобы скопировать данные из буфера ядра в буфер приложения область.

Блокировка ввода / вывода (IO) блокирование
приложения вызывает функцию ввода - вывода, что приводит к блокированию приложения, если данные готовы, скопировать из ядра в пространство пользователя, или ждать вечно.

В Linux, по умолчанию, все гнездо блокировка, типичное для чтения процесса операции что-то вроде этого:

IMG

Когда пользовательский процесс вызывает системный вызов recvfrom, ядро ​​начал первый этап ввода-вывода: Prepare данные (для сети IO, много раз данные не достигли в начале, к примеру, не получили полный UDP. пакет. на этот раз ядро ​​должно ждать достаточно данных, чтобы прийти). Этот процесс должен ждать, т.е. данные копируются в буфер в ядре операционной системы представляет собой процесс. В процессе стороны пользователя, весь процесс будет заблокирован (конечно, блокировать процесс их выбора). Когда ожидание ядра до данных будет готово, он будет копировать данные из ядра в память пользователя, а затем возвращает результат ядро, пользовательский процесс до подъема состояния блока, вверх и продолжить игру.

所以,blocking IO的特点就是在IO执行的两个阶段都被block了。

Неблокирующая ввода / вывод модель (неблокирующая IO)

Ставим неблокирующая сокет установлен сообщить ядру , когда запрашиваемая I / O операция не может быть завершена, процесс не будет спать, но возвращает ошибку. Так что наша I / O функция операции будет продолжать испытания, готовы ли данные, если не готовы, не продолжить тестирование , пока данные готов до сих пор. В этом процессе все тестирования, он будет занимать много процессорного времени .

Когда приложение, например, для неблокируемого времени вызовов цикла дескриптора recvfrom, мы называем опрос (опрос). Процесс нанесения непрерывно опрашивает ядро, чтобы увидеть, если операция готова, это большая трата процессорного времени, но эта модель лишь изредка сталкивается, как правило, в какой-то системных функций специализируется только лишь ,

IMG

Когда проблемы пользовательского процесса чтения операция, если ядро ​​данных не готово, то он не блокирует пользовательский процесс, но сразу же возвращает ошибку. С точки зрения пользовательского процесса, он инициирует операцию чтения после того, как, не нужно ждать, но тут же получил результат. Пользовательский процесс является результатом ошибки суждения, он знает, что эти данные не был готов, поэтому он может послать операцию чтения снова. После того, как данные будут готовы к ядру, и снова получил пользовательский процесс системного вызова, то он будет немедленно копировать данные в памяти пользователя, а затем вернуться.

所以,nonblocking IO的特点是用户进程需要不断的主动询问kernel数据好了没有。

Резюме : При блокировании I / O режим, хотя и не занимают много процессорного времени, поток может обрабатывать событие ввода / вывода потока. Если вы хотите обрабатывать несколько потоков, или мульти-процесс (вилка), или многопоточной (pthread_create), к сожалению , эти два метода эффективность не высока. Потом снова считают неблокирующей занят режим опроса ввода / вывода, мы обнаружили , что мы можем обрабатывать множество потоков (один поток переключается из блокирующего режима в режим неблокирующем не будет обсуждаться здесь далее):

while true {  
    for i in stream[]; {  
        if i has data  
        read until unavailable  
    }  
}

До тех пор , пока мы сохраняем весь поток от начала до конца и снова спросил, и снова начать с нуля. Так что вы можете обрабатывать несколько потоков, но это, очевидно , не очень хорошо, потому что если все потоки не имеют никаких данных, то только впустую CPU.

为了避免CPU空转,可以引进了一个代理(一开始有一位叫做select的代理,后来又有一位叫做poll的代理,不过两者的本质是一样的)。这个代理比较厉害,可以同时观察许多流的I/O事件,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有I/O事件时,就从阻塞态中醒来,于是我们的程序就会轮询一遍所有的流(于是我们可以把“忙”字去掉了)

while true {  
    select(streams[])  
    for i in streams[] {  
        if i has data  
        read until unavailable  
    }  
}

于是,如果没有I/O事件产生,我们的程序就会阻塞在select处。但是依然有个问题,我们从select那里仅仅知道了,有I/O事件发生了,但却并不知道是那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。即使用select,我们有**O(n)**的无差别轮询复杂度,同时处理的流越多,没一次无差别轮询时间就越长。

epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll之会把哪个流发生了怎样的I/O事件通知我们。此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))

****I/O多路复用模型****( IO multiplexing)

IO multiplexing就是我们说的select,poll,epoll,有些地方也称这种IO方式为event driven IO。select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select,poll,epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。select,poll,epoll这个function也会使进程阻塞,但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。

IMG

当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。

所以,I/O 多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符(见《I/O模型之二:Linux IO模式及 select、poll、epoll详解》),而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态,select()函数就可以返回。

这个图和blocking IO的图其实并没有太大的不同,事实上,还更差一些。因为这里需要使用两个system call (select 和 recvfrom),而blocking IO只调用了一个system call (recvfrom)。但是,用select的优势在于它可以同时处理多个connection。

所以,如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)

在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

信号驱动I/O模型

我们也可以用信号,让内核在描述符就绪时发送SIGIO信号通知我们。通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,我们的进程继续工作,也就是说它没有被阻塞。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。我们随后既可以在信号处理函数中调用recvfrom读取数据报,并通知主循环数据已经准备好待处理。

优势:等待数据报到达期间进程不被阻塞。主循环可以继续执行,只要等待来自信号处理函数的通知:既可以是数据已准备好被处理,也可以是数据报已准备好被读取。

IMG

异步I/O模型(asynchronous IO)

linux下的asynchronous IO其实用得很少。

告知内核启动某个操作,并让内核在整个操作(包括将内核复制到我们自己的缓冲区)完成后通知我们。

与信号驱动模型的主要区别在于:信号驱动式I/O是由内核通知我们何时可以启动一个I/O操作,而异步模型是由内核通知我们I/O操作何时完成。

IMG

调用aio_read(Posix异步I/O函数以aio_或lio_开头)函数,给内核传递描述字、缓冲区指针、缓冲区大小(与read相同的3个参数)、文件偏移以及通知的方式,然后系统立即返回。我们的进程不阻塞于等待I/0操作的完成。当内核将数据拷贝到缓冲区后,再通知应用程序。

用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。

总结

各种I/O模型的对比:

blocking和non-blocking的区别

调用blocking IO会一直block住对应的进程直到操作完成,而non-blocking IO在kernel还准备数据的情况下会立刻返回。

synchronous IO和asynchronous IO的区别

在说明synchronous IO和asynchronous IO的区别之前,需要先给出两者的定义。POSIX的定义是这样子的:
- A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
- An asynchronous I/O operation does not cause the requesting process to be blocked;

两者的区别就在于synchronous IO做”IO operation”的时候会将process阻塞。按照这个定义,之前所述的blocking IO,non-blocking IO,IO multiplexing都属于synchronous IO。

有人会说,non-blocking IO并没有被block啊。这里有个非常“狡猾”的地方,定义中所指的”IO operation”是指真实的IO操作,就是例子中的recvfrom这个system call。non-blocking IO在执行recvfrom这个system call的时候,如果kernel的数据没有准备好,这时候不会block进程。但是,当kernel中数据准备好的时候,recvfrom会将数据从kernel拷贝到用户内存中,这个时候进程是被block了,在这段时间内,进程是被block的。

而asynchronous IO则不一样,当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。

各个IO Model的比较如图所示:

IMG

Через картинке выше, вы можете найти разницу между неблокирующая IO и асинхронный IO-прежнему очень очевидна. В неблокирующем IO, хотя большая часть времени этот процесс не будет блок, но он по-прежнему требует процесса взять на себя инициативу в проверке, и когда данные готовы после завершения процесса также должен взять на себя инициативу recvfrom вызова еще раз, чтобы скопировать данные в память пользователя , Асинхронный ввод-вывод полностью отличается. Это как весь процесс пользовательского операций ввода-вывода переданы другим лицам (ядро) завершается, то сигнал остальным до конца. В то же время, этот процесс не требует от пользователя, чтобы проверить состояние операций ввода-вывода, вам не нужно брать на себя инициативу, чтобы скопировать данные.

Опубликовано 112 оригинальных статей · вона похвала 20 · просмотров 60000 +

рекомендация

отblog.csdn.net/qzqanzc/article/details/104040474
рекомендация