vlambda博客
学习文章列表

Socket之IO系统调用详解

    上一篇文章里介绍了目前常用的多路复用机制,偏理论的东西看起来不一定很好理解,所以接下来呢将用几个demo来演示IO(未特殊说明都是同步IO)的发展历程:

Blocking IO -->Non-Blocking IO-->IO Multiplexing

特别强调一下,以上都是系统层面,对于java里常说的NIO指的是New IO,不在上述讨论范围内。

    先来一波传统IO的编程模型,一个简单的socket代码如下:

如果还未了解过socket编程可以网上先学习下,这边只是为了演示需要,分析这段代码的系统调用过程,继续秀一波,展示这段代码的执行过程,通过如下命令:

strace -ff -o ./villiam-test java SocketIOSystemCallTest

效果如下:

Socket之IO系统调用详解

由上图得知,程序已经运行起来。查看当前目录:

Socket之IO系统调用详解

villiam-test前缀后的数字是java线程id,可知,已经启动了这些个线程。通过jps查看:

Socket之IO系统调用详解

可知上面启动的java进程id是12593.进入该进程的目录查看,cd /proc/12593

Socket之IO系统调用详解

分别进入fd目录(文件描述符):

Socket之IO系统调用详解

以上便是该进程的所有文件句柄。

进入task目录:

Socket之IO系统调用详解

该进程下的所有java线程。(通过此可以统计一个进程内的所有线程数量)

通过grep查看

Socket之IO系统调用详解

查看该线程的系统调用 cat villiam-test.12594,查找 "step1"

Socket之IO系统调用详解

调用了系统的write函数,1就是标准输出。如果你对unix的socket的编程了解的话,还可以查看 socket,bind,listen等函数,先看socket函数:

Socket之IO系统调用详解

Socket之IO系统调用详解

接着查看bind及listen函数:

Socket之IO系统调用详解

到此为止,我们的程序还一直在监听等待连接进来,再来一波,通过nc命令来连接8090端口:

Socket之IO系统调用详解

服务端日志:

Socket之IO系统调用详解

可知,客服端连接通过端口49416与之交互,通过netstat -naop 进行查看

Socket之IO系统调用详解

多了一个ESTABLISHED的一条记录,本地端口49416与8090端口建立连接。

查看新增的fd及task:

Socket之IO系统调用详解

多了一个文件句柄为6,多了一个线程id12749.

Socket之IO系统调用详解

接下来我们来验证上面的信息,查看villiam-test.12594 的文件,查找accept关键字:

Socket之IO系统调用详解


Socket之IO系统调用详解

环环相扣,通过如上的分析,我们得知java的socket的编程是对系统层的封装,最后我们发现系统层调用poll函数进行阻塞,等待IO相应,并且得知,java的thread在系统层调用的是clone函数:

输入:

Socket之IO系统调用详解

相应输出:


看到系统调用的recvfrom函数进行阻塞,等待相应。

    最后再带大家学习下几个系统函数,通过man命令。

首先学习man bind ,里面有个例子可以学习:


本篇所讲的内容还都是基于传统的IO模型,也就是阻塞的IO。epoll的模型会通过nginx进行讲解,下回分享~