您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    阿里Java二面:从底层聊下IO多路复用模型?这不有嘴就会
    时间:2021-03-05 12:03 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    当我们去面试的时分,问到了 redis,nginx,netty他们的底层模型辨别是什么?

    redis -> epoll

    nginx-> epoll

    netty-> epoll?

    需求从操作系统的层面下去谈

    BIO

    当我们开机的时分,首先被加载进内存的是我们的Kernel(内核),内核是用于管理我们的硬件的,同时内核还会创立一个GDT表,然后划分两个空间(用户空间和内核空间),同时空间中的内容是开启了保护形式,无法被修正的。

    同时还有一个CPU的概念,CPU有本人的指令集,并且指令集是分了几个级别的,辨别是从0~3的,Kernel属于0级别。APP只能用级别为3的指令集。

    从下面我们可以知道,我们的运用顺序是无法直接拜访我们的Kernel的,也就是顺序不能直接拜访我们的磁盘,声卡,网卡等设备,只要内核才可以拜访,那我们怎样办?

    只要APP经过调用Kernel提供的 syscall(系统软中缀和硬中缀)来获取硬件中的内容。

    软中缀

    硬中缀:硬中缀指的是我们的键盘,按下一个按键的时分,就会触发我们的硬中缀,也就是内核会有一个中缀号,然后失掉一个callback的回调函数

    说到这里,其实就是为了引出一个 概念,就是 IO 和 内核之间的成本成绩

    阿里Java二面:从底层聊下IO多路复用模型?这不有嘴就会

    /** 

     * 效劳器读取文件 

     * @author: 陌溪 

     * @create: 2020-07-01-20:40 

     */ 

    public class TestSocket { 

        public static void main(String[] args) throws IOException { 

            ServerSocket server = new ServerSocket(8090); 

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

            while(true) { 

                Socket client = server.accept(); 

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

                new Thread(() -> { 

                    try { 

                        InputStream in = client.getInputStream(); 

                        BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 

                        while(true) { 

                            System.out.println(reader.readLine()); 

                        } 

                    } catch (IOException e) { 

                        e.printStackTrace(); 

                    } 

                }, "t1").start(); 

            } 

        } 

    抓取顺序对内核有没有系统调用,然后输入

    strace -ff -o ./ooxx java TestSocket 

    然后我们执行下面的顺序,失掉我们的结果

    然后我们在经过jps命令,查看以后TestSocket的进程号

    jps  

    2912 Jps  

    2878 TestSocket 

    然后我们在进入下面的这个目录下,启动2878是线程的id号,这个目录就是寄存该线程的一些信息

    cd /proc/2878 

    我们可以看到2878进程下的,经过查看task目录,可以看到一切线程数

    还有一个目录,就是 fd目录,在该目录下,就是我们的一些IO流

    下面的0,1,2,辨别对应着 输入流,输入流和错误流。在java外面我们流就是对象,而在linux系统中,流就是一个个的文件。前面的4,5 就对应着我们的socket通讯,辨别对应着ipv4 和 ipv6

    经过netstat命令查看

    然后我们运用nc衔接 8090端口

    nc localhost 8090 

    我们执行完后,经过netstat命令查看 ,发现多了个衔接的形状

    然后在看文件外面,也多了一个socket

    我们查看系统调用,发现经过系统调用接纳了一个58181端口号的央求,在前面我们还可以看到5,这个5其实就是对应的上图外面的socket,走的是ipv4。

    从这里其实我们就可以知道了,我们原来调用中写的代码

    Socket client = server.accept(); 

    对应到系统层面,也是调用了系统的办法。

    同时关于系统调用,有以下几种方式

    bind

    connect

    listen

    select

    socket

    (责任编辑:admin)