Linux-IO模型之BIO

说到IO模型,先来了解几个专用术语:
我们平时说的阻塞或非阻塞是指应用程序在发起 I/O 操作时,是立即返回还是等待。而同步和异步,是指应用程序在与内核通信时,数据从内核空间到应用空间的拷贝,是由内核主动发起还是由应用程序来触发

有异步阻塞模型吗?
没有,都异步了,还要阻塞?有病吧!

观察IO模型过程中用到的指令:

strace -ff -o out cmd
-ff 捕捉所有线程
-o 捕捉到的每个线程的输出文件以什么开头
cmd 捕捉的命令,比如 java -jar

服务端code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketBIOServer4JDK1_4 {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(9090, 20);

        System.out.println("step1: new ServerSocket(9090) ");

        for (; ; ) {
            Socket client = server.accept();  //阻塞1
            System.out.println("step2:client\t" + client.getPort());


            new MyThread(client).start();
        }
    }

    private static class MyThread extends Thread {
        private Socket client;

        public MyThread(Socket client) {
            this.client = client;
        }

        public void run() {
            InputStream in = null;
            try {
                in = client.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                while (true) {
                    String dataline = reader.readLine(); //阻塞2

                    if (null != dataline) {
                        System.out.println(dataline);
                    } else {
                        client.close();
                        break;
                    }
                }
                System.out.println("客户端断开");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

启动服务端代码
使用jdk1.4编译
/usr/lib/jdk.1.4.2/bin/javac SocketBIOServer4JDK1_4.java
strace -ff -o out /usr/lib/jdk.1.4.2/bin/javac SocketBIOServer4JDK1_4
此时服务端只是起了一个9090端口的LISTEN

[root@optimize-node01 netio]# netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      6729/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      6859/master         
tcp        0      0 10.0.0.5:22             10.0.0.1:6628           ESTABLISHED 8258/sshd: root@pts 
tcp        0      0 10.0.0.5:22             10.0.0.1:2569           ESTABLISHED 7471/sshd: root@pts 
tcp        0     52 10.0.0.5:22             10.0.0.1:6627           ESTABLISHED 8238/sshd: root@pts 
tcp6       0      0 :::22                   :::*                    LISTEN      6729/sshd           
tcp6       0      0 ::1:25                  :::*                    LISTEN      6859/master         
tcp6       0      0 :::9090                 :::*                    LISTEN      8542/java

使用lsof -p pid查看8542进程的文件描述符

[root@optimize-node01 netio]#  lsof -p 8542
COMMAND  PID USER   FD   TYPE DEVICE  SIZE/OFF     NODE NAME
java    8542 root  cwd    DIR  253,0       145 51428137 /opt/io/netio
java    8542 root  rtd    DIR  253,0       256       64 /
java    8542 root  txt    REG  253,0     64940   401302 /usr/lib/jdk.1.4.2/bin/java
java    8542 root  mem    REG  253,0    769342 17325867 /usr/lib/jdk.1.4.2/jre/lib/ext/localedata.jar
java    8542 root  mem    REG  253,0     67964 51665590 /usr/lib/jdk.1.4.2/jre/lib/i386/libnet.so
java    8542 root  mem    REG  253,0     54665 17325869 /usr/lib/jdk.1.4.2/jre/lib/ext/activation.jar
java    8542 root  mem    REG  253,0 106176928 51704868 /usr/lib/locale/locale-archive
java    8542 root  mem    REG  253,0     53248 17325868 /usr/lib/jdk.1.4.2/jre/lib/ext/ldapsec.jar
java    8542 root  mem    REG  253,0    153117 17325866 /usr/lib/jdk.1.4.2/jre/lib/ext/mailapi.jar
java    8542 root  mem    REG  253,0    280984 17325861 /usr/lib/jdk.1.4.2/jre/lib/ext/mail.jar
java    8542 root  mem    REG  253,0    111430 17325863 /usr/lib/jdk.1.4.2/jre/lib/ext/sunjce_provider.jar
java    8542 root  mem    REG  253,0      8674 17325865 /usr/lib/jdk.1.4.2/jre/lib/ext/jta.jar
java    8542 root  mem    REG  253,0   5896381 51665554 /usr/lib/jdk.1.4.2/jre/lib/charsets.jar
java    8542 root  mem    REG  253,0     69571 51665597 /usr/lib/jdk.1.4.2/jre/lib/jce.jar
java    8542 root  mem    REG  253,0    901949 51665532 /usr/lib/jdk.1.4.2/jre/lib/jsse.jar
java    8542 root  mem    REG  253,0     89343 51665529 /usr/lib/jdk.1.4.2/jre/lib/sunrsasign.jar
java    8542 root  mem    REG  253,0  26910912 51665536 /usr/lib/jdk.1.4.2/jre/lib/rt.jar
java    8542 root  mem    REG  253,0     90040 51665579 /usr/lib/jdk.1.4.2/jre/lib/i386/libzip.so
java    8542 root  mem    REG  253,0    142076 51665589 /usr/lib/jdk.1.4.2/jre/lib/i386/libjava.so
java    8542 root  mem    REG  253,0     70980 51665581 /usr/lib/jdk.1.4.2/jre/lib/i386/libverify.so
java    8542 root  mem    REG  253,0     54464 17096577 /usr/lib/libnss_files-2.17.so
java    8542 root  mem    REG  253,0     11902 17325864 /usr/lib/jdk.1.4.2/jre/lib/ext/smtp.jar
java    8542 root  mem    REG  253,0      8896 17325862 /usr/lib/jdk.1.4.2/jre/lib/ext/dnsns.jar
java    8542 root  mem    REG  253,0     16384 17289127 /tmp/hsperfdata_root/8542
java    8542 root  mem    REG  253,0    304600 17325561 /usr/lib/libm-2.17.so
java    8542 root  mem    REG  253,0    112580 17325563 /usr/lib/libnsl-2.17.so
java    8542 root  mem    REG  253,0   5224816   903979 /usr/lib/jdk.1.4.2/jre/lib/i386/client/libjvm.so
java    8542 root  mem    REG  253,0   2107596 16829797 /usr/lib/libc-2.17.so
java    8542 root  mem    REG  253,0     17716 17325559 /usr/lib/libdl-2.17.so
java    8542 root  mem    REG  253,0    133736 17380605 /usr/lib/libpthread-2.17.so
java    8542 root  mem    REG  253,0     33188 33684676 /usr/lib/jdk.1.4.2/jre/lib/i386/native_threads/libhpi.so
java    8542 root  mem    REG  253,0    158768 17325529 /usr/lib/ld-2.17.so
java    8542 root    0u   CHR  136,1       0t0        4 /dev/pts/1
java    8542 root    1u   CHR  136,1       0t0        4 /dev/pts/1
java    8542 root    2u   CHR  136,1       0t0        4 /dev/pts/1
java    8542 root    3u  IPv6  89489       0t0      TCP *:websm (LISTEN)
java    8542 root    4u  sock    0,7       0t0    89487 protocol: TCPv6

3号文件描述符启动了LISTEN监听,肯定是对应9090端口的监听(稍后在后面的out输出文件里会看到)
回到我们启动程序的目录查看,已经多了很多out输出文件,out.后面的数字就代表线程id,可见我们启动这一个java进程的同时也启动了很多java线程(GC线程,main线程…)
此时这个LISTEN在操作系统层面对应了三个系统调用socket,bind,listen
可通过以下三个命令进行查看,需要安装yum install -y man
man 2 socket
man 2 bind
man 2 listen
如果想在追踪的系统调用中看到的话,需要低版本的java,
windows版本
linux版本
linux版本扔到服务器直接解压使用即可

[root@optimize-node01 netio]# ll
total 17104
drwxr-xr-x 3 root root      19 Jul  2 20:47 org
-rw-r--r-- 1 root root  175691 Jul  6 08:48 out.8542
-rw-r--r-- 1 root root  371013 Jul  6 09:09 out.8543
-rw-r--r-- 1 root root    1295 Jul  6 08:48 out.8544
-rw-r--r-- 1 root root    1488 Jul  6 08:48 out.8545
-rw-r--r-- 1 root root    1313 Jul  6 08:48 out.8546
-rw-r--r-- 1 root root    1546 Jul  6 08:48 out.8547
-rw-r--r-- 1 root root   20243 Jul  6 08:48 out.8548
-rw-r--r-- 1 root root 8761142 Jul  6 09:09 out.8549

out.8542对应我们的main线程
其他对应的是工作线程
我们只需关注8542对应的主线程输出即可

我们在主线程里输出了 step1: new ServerSocket(9090)
同样,在out.8542里如果找到这个输出,就证明8542就是主线程id
通过查看文件,找到write(1, "step1: new ServerSocket(9090) ", 30) = 30,你的文件里跟我的不会完全一致
我们继续观察我们的程序和内核有哪些系统调用

可在文件中找到以下内容
回到我们的程序:Socket client = server.accept(); 这里的accept()就会调用内核的accept进行阻塞
这里accept的第一个参数是3,这个3是文件描述符,这里也跟我们上面使用lsof命令看到的文件描述符对应上了

accept(3, {sa_family=AF_INET6, sin6_port=htons(34450), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope     _id=0}, [28]) = 5

我们继续跟踪上面的文件描述符3,既然accept接收这个参数,这个参数肯定是out.8542文件中上面的步骤生成的,通过查找,可以找到以下几行

socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET6, sin6_port=htons(9090), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=htonl(0)}, 24) = 0
listen(3, 20) 

可以看到bind和listen都会使用到3这个文件描述符,3是被socket这个系统调用生成的

ServerSocket server = new ServerSocket(9090);

我们在程序里是使用上述代码来监听9090端口的,可见,在BIO时代,JVM会为我们调用socket,bind,listen三个系统调用来完成上述代码的监听,也就是说通过socket创建一个文件描述符(linux里一切皆文件),调用bind将文件描述符3和端口9090绑定,调用listen对文件描述符3进行监听
可以说:任何的程序只要做服务端,这三个系统调用是必须的,无论是在什么IO模型下,这个三个系统调用完成之后,可以通过accept系统调用去接收客户端的连接

此时,我们的服务端程序还阻塞在accept处,还没有client连接进来
我们此时监控out.8542文件的输出

[root@optimize-node01 netio]# strace -ff -o out /usr/lib/jdk.1.4.2/bin/java org/itliu/sysio/bio/SocketBIOServer4JDK1_4 
step1: new ServerSocket(9090) 
[root@optimize-node01 netio]# tail -f out.8542
listen(3, 20)                           = 0
write(1, "step1: new ServerSocket(9090) ", 30) = 30
write(1, "\n", 1)                       = 1
gettimeofday({tv_sec=1594039721, tv_usec=148811}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148843}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148871}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148995}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=149050}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=149185}, NULL) = 0
accept(3, 

模拟client的连接,在另一台机器操作,输出会更明显

[root@optimize-node02 ~]# nc 10.0.0.5 9090

此时server的输出,接收到了client 48734的连接

[root@optimize-node01 netio]# strace -ff -o out /usr/lib/jdk.1.4.2/bin/java org/itliu/sysio/bio/SocketBIOServer4JDK1_4 
step1: new ServerSocket(9090) 
step2:client	48734

同时,我们的另一个监听out.8542的窗口也同步发生变化

[root@optimize-node01 netio]# tail -f out.8542
listen(3, 20)                           = 0
write(1, "step1: new ServerSocket(9090) ", 30) = 30
write(1, "\n", 1)                       = 1
gettimeofday({tv_sec=1594039721, tv_usec=148811}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148843}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148871}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148995}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=149050}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=149185}, NULL) = 0
accept(3, {sa_family=AF_INET6, sin6_port=htons(48734), inet_pton(AF_INET6, "::ffff:10.0.0.6", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [28]) = 5
gettimeofday({tv_sec=1594042173, tv_usec=263776}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=264111}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=264331}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=273727}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=273836}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=274055}, NULL) = 0
write(1, "step2:client\t48734", 18)     = 18
write(1, "\n", 1)                       = 1
gettimeofday({tv_sec=1594042173, tv_usec=274384}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=274419}, NULL) = 0
stat64("/opt/io/netio/org/itliu/sysio/bio/SocketBIOServer4JDK1_4$MyThread.class", {st_mode=S_IFREG|0644, st_size=1062, ...}) = 0
open("/opt/io/netio/org/itliu/sysio/bio/SocketBIOServer4JDK1_4$MyThread.class", O_RDONLY|O_LARGEFILE) = 6
fstat64(6, {st_mode=S_IFREG|0644, st_size=1062, ...}) = 0
stat64("/opt/io/netio/org/itliu/sysio/bio/SocketBIOServer4JDK1_4$MyThread.class", {st_mode=S_IFREG|0644, st_size=1062, ...}) = 0
read(6, "\312\376\272\276\0\0\0.\0A\n\0\20\0\33\t\0\17\0\34\n\0\35\0\36\7\0\37\7\0 \n"..., 1062) = 1062
close(6)                                = 0
gettimeofday({tv_sec=1594042173, tv_usec=275336}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=275478}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=275562}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=275623}, NULL) = 0
mmap2(NULL, 528384, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xe9dc3000
mprotect(0xe9dc3000, 4096, PROT_NONE)   = 0
clone(child_stack=0xe9e43424, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xe9e43ba8, tls={entry_number=12, base_addr=0xe9e43b40, limit=0x0fffff, seg_32bit=1, contents=0, read_exec_only=0, limit_in_pages=1, seg_not_present=0, useable=1}, child_tidptr=0xe9e43ba8) = 8619
futex(0x838e57c, FUTEX_WAIT_PRIVATE, 1, NULL) = 0
futex(0x838e42c, FUTEX_WAKE_PRIVATE, 1) = 0
sched_setscheduler(8619, SCHED_OTHER, [5]) = -1 EINVAL (Invalid argument)
futex(0x838e5dc, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0x838e3fc, 2) = 1
accept(3, 

对比我们上面tail -f 时的输出,多了很多次系统调用
我们观察上面的输出,有两个accept,第一个accept就是我们第一次使用tail -f 命令输出时阻塞接收client的时候,可以看到这个accept接收了一个端口号为48734,地址为10.0.0.6的连接,与我们服务端的输出对应,而第二个accept同样阻塞再次等待新的连接;并且10.0.0.6:48734这个连接对应的描述符为5
继续使用lsof -p 查看进程的文件描述符

[root@optimize-node01 netio]# lsof -p 8542
COMMAND  PID USER   FD   TYPE DEVICE  SIZE/OFF     NODE NAME
java    8542 root  cwd    DIR  253,0       161 51428137 /opt/io/netio
java    8542 root  rtd    DIR  253,0       256       64 /
java    8542 root  txt    REG  253,0     64940   401302 /usr/lib/jdk.1.4.2/bin/java
java    8542 root  mem    REG  253,0    769342 17325867 /usr/lib/jdk.1.4.2/jre/lib/ext/localedata.jar
java    8542 root  mem    REG  253,0     67964 51665590 /usr/lib/jdk.1.4.2/jre/lib/i386/libnet.so
java    8542 root  mem    REG  253,0     54665 17325869 /usr/lib/jdk.1.4.2/jre/lib/ext/activation.jar
java    8542 root  mem    REG  253,0 106176928 51704868 /usr/lib/locale/locale-archive
java    8542 root  mem    REG  253,0     53248 17325868 /usr/lib/jdk.1.4.2/jre/lib/ext/ldapsec.jar
java    8542 root  mem    REG  253,0    153117 17325866 /usr/lib/jdk.1.4.2/jre/lib/ext/mailapi.jar
java    8542 root  mem    REG  253,0    280984 17325861 /usr/lib/jdk.1.4.2/jre/lib/ext/mail.jar
java    8542 root  mem    REG  253,0    111430 17325863 /usr/lib/jdk.1.4.2/jre/lib/ext/sunjce_provider.jar
java    8542 root  mem    REG  253,0      8674 17325865 /usr/lib/jdk.1.4.2/jre/lib/ext/jta.jar
java    8542 root  mem    REG  253,0   5896381 51665554 /usr/lib/jdk.1.4.2/jre/lib/charsets.jar
java    8542 root  mem    REG  253,0     69571 51665597 /usr/lib/jdk.1.4.2/jre/lib/jce.jar
java    8542 root  mem    REG  253,0    901949 51665532 /usr/lib/jdk.1.4.2/jre/lib/jsse.jar
java    8542 root  mem    REG  253,0     89343 51665529 /usr/lib/jdk.1.4.2/jre/lib/sunrsasign.jar
java    8542 root  mem    REG  253,0  26910912 51665536 /usr/lib/jdk.1.4.2/jre/lib/rt.jar
java    8542 root  mem    REG  253,0     90040 51665579 /usr/lib/jdk.1.4.2/jre/lib/i386/libzip.so
java    8542 root  mem    REG  253,0    142076 51665589 /usr/lib/jdk.1.4.2/jre/lib/i386/libjava.so
java    8542 root  mem    REG  253,0     70980 51665581 /usr/lib/jdk.1.4.2/jre/lib/i386/libverify.so
java    8542 root  mem    REG  253,0     54464 17096577 /usr/lib/libnss_files-2.17.so
java    8542 root  mem    REG  253,0     11902 17325864 /usr/lib/jdk.1.4.2/jre/lib/ext/smtp.jar
java    8542 root  mem    REG  253,0      8896 17325862 /usr/lib/jdk.1.4.2/jre/lib/ext/dnsns.jar
java    8542 root  mem    REG  253,0     16384 17289127 /tmp/hsperfdata_root/8542
java    8542 root  mem    REG  253,0    304600 17325561 /usr/lib/libm-2.17.so
java    8542 root  mem    REG  253,0    112580 17325563 /usr/lib/libnsl-2.17.so
java    8542 root  mem    REG  253,0   5224816   903979 /usr/lib/jdk.1.4.2/jre/lib/i386/client/libjvm.so
java    8542 root  mem    REG  253,0   2107596 16829797 /usr/lib/libc-2.17.so
java    8542 root  mem    REG  253,0     17716 17325559 /usr/lib/libdl-2.17.so
java    8542 root  mem    REG  253,0    133736 17380605 /usr/lib/libpthread-2.17.so
java    8542 root  mem    REG  253,0     33188 33684676 /usr/lib/jdk.1.4.2/jre/lib/i386/native_threads/libhpi.so
java    8542 root  mem    REG  253,0    158768 17325529 /usr/lib/ld-2.17.so
java    8542 root    0u   CHR  136,1       0t0        4 /dev/pts/1
java    8542 root    1u   CHR  136,1       0t0        4 /dev/pts/1
java    8542 root    2u   CHR  136,1       0t0        4 /dev/pts/1
java    8542 root    3u  IPv6  89489       0t0      TCP *:websm (LISTEN)
java    8542 root    4u  sock    0,7       0t0    89487 protocol: TCPv6
java    8542 root    5u  IPv6  89490       0t0      TCP bogon:websm->bogon:48734 (ESTABLISHED)

可以看到最后一行,文件描述符5,对应的是一个端口为48734的TCP连接
看到这里,对应到程序里,还只是停留在下面这句代码的输出,再后面的代码还在被阻塞

System.out.println("step2:client\t" + client.getPort());

后面的代码我们使用的是多线程的方式,new了一个Thread来进行处理的,继续追踪上面tail -f out.8542的输出,为了方便,我将上一次的输出贴到下面

accept(3, [root@optimize-node01 netio]# tail -f out.8542
listen(3, 20)                           = 0
write(1, "step1: new ServerSocket(9090) ", 30) = 30
write(1, "\n", 1)                       = 1
gettimeofday({tv_sec=1594039721, tv_usec=148811}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148843}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148871}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=148995}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=149050}, NULL) = 0
gettimeofday({tv_sec=1594039721, tv_usec=149185}, NULL) = 0
accept(3, {sa_family=AF_INET6, sin6_port=htons(48734), inet_pton(AF_INET6, "::ffff:10.0.0.6", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [28]) = 5
gettimeofday({tv_sec=1594042173, tv_usec=263776}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=264111}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=264331}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=273727}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=273836}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=274055}, NULL) = 0
write(1, "step2:client\t48734", 18)     = 18
write(1, "\n", 1)                       = 1
gettimeofday({tv_sec=1594042173, tv_usec=274384}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=274419}, NULL) = 0
stat64("/opt/io/netio/org/itliu/sysio/bio/SocketBIOServer4JDK1_4$MyThread.class", {st_mode=S_IFREG|0644, st_size=1062, ...}) = 0
open("/opt/io/netio/org/itliu/sysio/bio/SocketBIOServer4JDK1_4$MyThread.class", O_RDONLY|O_LARGEFILE) = 6
fstat64(6, {st_mode=S_IFREG|0644, st_size=1062, ...}) = 0
stat64("/opt/io/netio/org/itliu/sysio/bio/SocketBIOServer4JDK1_4$MyThread.class", {st_mode=S_IFREG|0644, st_size=1062, ...}) = 0
read(6, "\312\376\272\276\0\0\0.\0A\n\0\20\0\33\t\0\17\0\34\n\0\35\0\36\7\0\37\7\0 \n"..., 1062) = 1062
close(6)                                = 0
gettimeofday({tv_sec=1594042173, tv_usec=275336}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=275478}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=275562}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=275623}, NULL) = 0
mmap2(NULL, 528384, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xe9dc3000
mprotect(0xe9dc3000, 4096, PROT_NONE)   = 0
clone(child_stack=0xe9e43424, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xe9e43ba8, tls={entry_number=12, base_addr=0xe9e43b40, limit=0x0fffff, seg_32bit=1, contents=0, read_exec_only=0, limit_in_pages=1, seg_not_present=0, useable=1}, child_tidptr=0xe9e43ba8) = 8619
futex(0x838e57c, FUTEX_WAIT_PRIVATE, 1, NULL) = 0
futex(0x838e42c, FUTEX_WAKE_PRIVATE, 1) = 0
sched_setscheduler(8619, SCHED_OTHER, [5]) = -1 EINVAL (Invalid argument)
futex(0x838e5dc, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0x838e3fc, 2) = 1
accept(3, 

从之前分析的第一个accept继续往下找,可以看到下面这个系统调用,通过clone克隆了一个线程,它的返回值返回了8619,此处也证明了java中的线程就是对应了内核中的一个线程。

clone(child_stack=0xe9e43424, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xe9e43ba8, tls={entry_number=12, base_addr=0xe9e43b40, limit=0x0fffff, seg_32bit=1, contents=0, read_exec_only=0, limit_in_pages=1, seg_not_present=0, useable=1}, child_tidptr=0xe9e43ba8) = 8619

此时查看我们之前查看out文件的目录下,可见新生成了out.8619文件,这个8619就是上面的clone的结果,也是我们程序里new Thread的结果

[root@optimize-node01 netio]# ll
total 34008
drwxr-xr-x 3 root root       19 Jul  2 20:47 org
-rw-r--r-- 1 root root   177999 Jul  6 09:29 out.8542
-rw-r--r-- 1 root root   974275 Jul  6 09:44 out.8543
-rw-r--r-- 1 root root     1295 Jul  6 08:48 out.8544
-rw-r--r-- 1 root root     1488 Jul  6 08:48 out.8545
-rw-r--r-- 1 root root     1313 Jul  6 08:48 out.8546
-rw-r--r-- 1 root root     1546 Jul  6 08:48 out.8547
-rw-r--r-- 1 root root    20243 Jul  6 08:48 out.8548
-rw-r--r-- 1 root root 23053498 Jul  6 09:44 out.8549
-rw-r--r-- 1 root root     1917 Jul  6 09:29 out.8619

现在开始观察out.8619的系统调用,可以看到停留在recv(5,这个系统调用的地方,如果你没有进行操作的话,可以查看下面的内容,此时内容是out.8619的全部内容

set_robust_list(0xe9e43bb0, 12)         = 0
sched_getaffinity(8619, 32, [0, 1, 2, 3]) = 32
mmap2(0xe9dc8000, 40960, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xe9dc8000
sigaltstack({ss_sp=0xe9dc8000, ss_flags=0, ss_size=40960}, NULL) = 0
rt_sigaction(SIGHUP, NULL, {sa_handler=0xf730bfa8, sa_mask=~[KILL STOP RTMIN RT_1], sa_flags=SA_RESTART|SA_SIGINFO}, 8) = 0
rt_sigaction(SIGINT, NULL, {sa_handler=0xf730bfa8, sa_mask=~[KILL STOP RTMIN RT_1], sa_flags=SA_RESTART|SA_SIGINFO}, 8) = 0
rt_sigaction(SIGTERM, NULL, {sa_handler=0xf730bfa8, sa_mask=~[KILL STOP RTMIN RT_1], sa_flags=SA_RESTART|SA_SIGINFO}, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [HUP INT QUIT USR2 TERM CHLD], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [QUIT], NULL, 8) = 0
futex(0x838e57c, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0x838e42c, 2) = 1
futex(0x838e5dc, FUTEX_WAIT_PRIVATE, 1, NULL) = 0
futex(0x838e3fc, FUTEX_WAKE_PRIVATE, 1) = 0
sched_getaffinity(8619, 32, [0, 1, 2, 3]) = 32
sched_getaffinity(8619, 32, [0, 1, 2, 3]) = 32
mmap2(0xe9dd2000, 12288, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xe9dd2000
mprotect(0xe9dd2000, 12288, PROT_NONE)  = 0
gettimeofday({tv_sec=1594042173, tv_usec=278100}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278146}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278180}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278238}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278276}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278383}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278759}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278854}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=278885}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=279001}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=279074}, NULL) = 0
gettimeofday({tv_sec=1594042173, tv_usec=279201}, NULL) = 0
recv(5,

后面就是读取client的消息,继续接收新的连接了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值