同步:发出一个功能调用时,在没得到结果之前,该调用就不会返回
异步:当一个异步调用发出以后,调用者不会立刻得到结果,实际处理这个调用的部件是在调用发出之后,通过状态通知调用者。
同步异步他们是消息通知机制
阻塞和非阻塞,他们是程序在等待消息时的状态。
阻塞:在调用结果返回之前 ,当前线程会被挂起,函数只有在得到结果之后才会返回;
非阻塞:指不能立即得到结果之前,该函数不会阻塞当前线程,而是立即返回。
阻塞I/O模型:
应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。
非阻塞I/O模型
i/O复用模型:
简介:主要是select和epoll;对一个IO端口,两次调用,两次返回,比阻塞IO并没有什么优越性;关键是能实现同时对多个IO端口进行监听;
/O复用模型会用到select、poll、epoll函数,这几个函数也会使进程阻塞,但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。
select模式
首先创建了事件的描述符集合,,对于一个事件,关注其上面的读事件,写事件,异常事件,所以要创建三类事件的描述符,分别用来收集事件的描述符,写事件的描述符,调用select()函数,等待事情发生,然后轮训所有事件的描述符的每个描述符,检查是否有事件的发生,如果有就处理,
poll方式
和select方式相同,都是创建一个描述符的集合,再去等待事件的发生,然后再去轮询描述符的集合,检查有没有事件的发生。
区别在于:select库需要为读事件,写事件,异常事件分别创建一个描述符的集合,再最后轮询的时候需要轮询三个集合,而poll库只需要创建一个集合,再每个描述符对应的结构上分别设置读事件,写事件,或异常事件,最后轮训的时候,可以同时检查这三个事件的是否发生。
他们的处理方式都是创建了一个待处理事件的列表,然后把这个列表发给内核,返回的时候,再去轮询检查这个列表,以判断是否有事情发生,效率低下。
比较好的做法就是把描述符列表的权限交给内核负责,一旦有事情发生,内核会把发生事件的描述符通知给进程,这样就避免了轮询整个描述符列表。
epoll方式
通过相关的调用,通知内核创建了一个描述符的列表,然后给这些描述符设置所关注的事件,并把它添加到内核的事件列表中去,完成设置以后,epoll就开始等待内核通知事件了,某一事件发生以后,内核就将发生事件的描述符上报给epoll库,得知事件列表的epoll库,就开始进行事件的处理了。
epoll有两种模式:水平触发和边缘触发
水平触发:内核通知进程来读取数据,进程没来读取数据,内核需要一次一次通知进程
边缘触发:内核只通知一次让进程来读取数据,进程可以在超时时间内随时来读取数据。