Linux多线程服务端编程笔记 第三章

本文主要解决如下问题:

  1. epoll的线程模型是怎样的?
  2. epoll的缺点是什么?
  3. epoll的几个问题?
  4. 多线程服务器的常用编程模型;
  5. epoll与线程池的使用场景?
  6. 进程间通信使用TCP的好处?

1. epoll的线程模型是怎样的?

while(!done) {
  int timeout_ms = min(1000, getNextTimedCallback());    //获取超时时间;
  int retval = ::poll(fds, nfds, timeout_ms);
  if(retval < 0) {
      //错误处理,回调error_handler
  }
  else {
      //超时处理,回调timer handler
      if(retval > 0) {
          //IO事件处理,回调IO event handler
       }
  }
}

2. epoll的缺点是什么?

  1. 十分适合处理超时事件和IO事件,不适合处理计算密集型事件。
  2. 事件的回调需要非阻塞;使得容易割裂业务逻辑。

3. epoll的几个问题

  1. select是怎么实现大量文件描述符的监控的?
    对于select函数,有两个形参类型为struct fd_set*,这个是一个集合,文件描述符的集合,分别代表读和写事件的文件描述符;将需要监控的文件描述符添加到这个集合中,然后传递到select中,select就可以自动进行监控了。
    epoll是通过epoll_ctl函数来注册文件描述符,也是可以注册很多的文件描述符的。

  2. 为什么select会有额外的文件描述符拷贝操作?
    这里虽然,select函数传递的是一个struct fd_set类型的指针,但fd_set集合是定义在用户空间的,所以需要将struct fd_set内部数据成员拷贝到内核才能进行监控。
    epoll中通过epoll_ctl注册的文件描述符直接就放入到了内核中,所以不用进行拷贝操作了。

  3. 为什么select监控的文件描述符会有数量限制?
    struct fd_set类型的定义中,只有一个成员变量,且是一个数组,数组的大小是提前定义好的,所以select监控的文件描述符会有数量限制。
    epoll管理文件描述符的数据结构是一个红黑树,所以没有数量限制。

  4. 为什么select需要轮训文件描述符,epoll不需要?
    当一个事件到来,内核将事件的数据拷贝到内核(事件数据来源于网卡等),但是不知道该文件描述符是否被select监控,所以需要遍历文件描述符数组,然后看是否返回select;
    epoll是一个红黑树,可以很快速的查找,如果找到,就将文件描述符添加到一个list中,epoll_wait则仅仅是很简单的从list中取值,如果取到,就返回,取不到就阻塞。

4. 多线程服务器的常用编程模型

(1)每个请求一个线程,使用阻塞式IO;(比如条件变量)
(2)线程池 + 阻塞式IO;
(3)使用非阻塞IO + IO多路复用;
(4)Leader/Follower等高级模式(这个有待查询)

网络库的基本模型:epoll + 线程池。

5. epoll线程池的使用场景?

IO事件使用epoll来处理;
密集计算型采用线程池;

线程池可以使用任务队列或者生产者消费者队列来实现。

6. 进程间通信使用TCP的好处?

  1. 如果强调只读的共享数据,当然是共享内存好,但是如果是进程间的消息传递,使用TCP会有一些列优点。

  2. 优点:
    (1)TCP很容易跨主机使用,方便扩展,其他IPC无法跨机器;
    (1)TCP是双向的,比pipe单项来说,很不方便;
    (2)TCP资源会被系统自动回收,不用担心进程锁由于进程崩溃而导致的无法释放的问题(只能重启电脑);
    (3)进程一方崩溃,另一方可以很快的知道(应用层心跳也是需要有的);
    (4)出现问题方便记录与重现:使用wireshark/tcpdump抓包就可以。

  3. TCP长连接的优点:
    (1)定位分布式系统中服务的依赖关系:

netstat -tnpa | grep :port   

(2)可以通过发送队列和接受队列实时了解服务器的故障信息(可以用于监控)

netstat -tn

如上命令中会有两个字段:Recv-Q,Send-Q,这两个数字基本应该是0,如果 有持续变大的情况,说明出了问题:
Recv-Q:当前主机上的进程处理速度过慢;
Send-Q:远端服务器太忙,来不及处理。

你可能感兴趣的:(Linux多线程服务端编程笔记 第三章)