最近碰到的一些服务器问题的总结

      随着业务的熟悉,也多出更多的时间在注意技术。碰到了一下问题,做一下记录。

1.怎么查看服务器当前的网络状态,怎么看socket是否断开,怎么查看各个端口的连接情况。

使用 ifconfig 用来显示所有网络接口的详细情况的,如:ip地址,子网掩码等。

使用 netstat -na 显示当前网络各个端口连接信息,会显示各个连接的状态(a所有,n显示地址,可以加t指定tcp,l指定显示监听的套接字)。

2.linux fd(文件描述符)复用时怎么确保不出错。

3.客户端怎么异步的去连接服务器。

使用多线程或者多进程去连接服务器(线程池)

4.怎么查找一个目录和多个目录下含有指定输出的文件

使用 grep 'xxxx' [目录1] [目录2] -rn,查找目录1,目录2中出现 ‘xxxx’ 的文件,并显示出现在第几行。

5.skynet 不小心再 for 循环中使用了 call,另一个服务没有处理,这种情况怎么解决。

6.lua的table是怎么实现的。

这个我还没有看过,只知道 lua 的 table 是数组和hash一起实现的。有一个有意思的事情是,有一个 table ,table[1000] = 1,这种情况下是数组还是hash(虽然在我们看来是数组,但是实际上却是hash,简单的想,如果是数组也不实际,创建1000个地址,只存贮一个地址)。table 的 取长度,会查找一个整形的key,达成条件

  • table[key] != nil
  • table[key+1] == nil

所以,如果中间含有nil的table,计算长度,会出错。

7.怎么判断服务器是否发生死循环。

  1. top:找出占用cpu过高的程序
  2. top -H -p:记录下占用cpu的线程号
  3. gdb attach <进程号>: 对占用cpu过高的程序进行gdb调试
  4. info thread : 列出线程状态
  5. thread <线程号> : 根据线程号切换到某个线程
  6. bt : 输出堆栈
  7. l : 查看当前代码
  8. print <变量名> :输出必要的变量内容
  9. detach:分离线程
  10. q 退出gdb调试
  11. 处理死循环,重启进程/线程

8.怎么查看自己的服务器到底能够承载多少人。

查看linux服务器的内存,查看一个玩家需要多少内存,进行计算。

9.socket write的时候,对方如果关闭了,内核缓冲区又还没满,尝试继续写会怎样。

先写入缓冲区,再写得话会返回错误,触发信号。

10.动态库静态库那个效率高。C++动态库为什么要声明 extern c。调用动态库的方法。

静态库

当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被 copy 到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,优点,这样运行起来相对就快些。不过会有个缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间。

动态库

与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中。优点,这样就使可执行文件比较小, 节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。缺点,不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率,没有好与坏的区别,只看具体需要了。

另外,一个程序编好后,有时需要做一些修改和优化,如果我们要修改的刚好是库函数的话,在接口不变的前提下,使用共享库的程序只需要将共享库重新编译就可以了,而使用静态库的程序则需要将静态库重新编译好后,将程序再重新编译一便。这也是使用过程当中的差别,以现在的项目举例,在远程更新的时候,如果只是*.so动态库封装内容变化了,那么只需要更新*.so即可。

被extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的

11.skynet 使用的 epoll是什么模式,epoll 的水平触发和边缘触发有什么区别

水平触发(Level_triggered,epoll默认是水平触发的,skynet没做修改。

水平触发(Level_triggered:对于socket读来说,文件描述符关联的读内核缓冲区非空,有数据可以读取,就会触发读就绪,对于socket写来说,描述符关联的内核写缓冲区不满,就可以触发写就绪。

边缘触发(Edge_triggered):对于socket读来说,一旦有消息达到,触发一次读就绪,如果一次没有读完缓冲区,则剩余的消息将会留在缓冲区,不会触发读就绪。对于socket写来说,只触发一次写就绪,如果写满了缓冲区,当缓冲区发送完毕时,会再触发一次写就绪。如果未满,则也不会触发写就绪。

12.C++虚函数怎么实现的。

带有虚函数的类,编译器会为其额外分配一个虚函数表,里面记录的使虚函数的地址,当此类被继承时,子类如果也写了虚函数就在子类的虚函数表中将父类的函数地址覆盖,否则继承父类的虚函数地址。

实例化之后,对象有一个虚函数指针,虚函数指针指向虚函数表,这样程序运行的时候,通过虚函数指针找到的虚函数表就是根据对象的类型来指向的了。

13.skynet定时器是怎么实现的。

猜你喜欢

转载自blog.csdn.net/banfushen007/article/details/108699760