java程序運行時發生的系統調用

程序沒法直接訪問數據(硬件:磁盤、網卡),程序須要經過內核訪問,內核提供syscall,syscall的方法不能直接調用(保護模式),因此就有了軟中斷,中斷做用在cpu中,cpu收到中斷後,cpu會根據中斷號去內核中找對應的callback...java

程序測試

下面經過一個簡單的例子進行說明,下面這段代碼是測試socket簡單的一個方法,應該比較好理解(其實就是經過多線程解決多鏈接的問題),將下面這個java文件放在linux執行看下linux

public class TestSocket {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8090);
        System.out.println("step1:new ServerSocket(80)");
        while (true){
            Socket client = server.accept();
            System.out.println("step2:client\t"+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();
                }

            }).start();
        }
    }
}
複製代碼

程序抓取

經過下面這個命令抓取上面程序執行時對於內核有沒有發生系統調用shell

strace -ff -o ./ooxx java TestSocket
複製代碼

執行後能夠看到打印了第一句話,說明程序已經執行,發生了阻塞 markdown

經過其餘窗口進入這個文件夾發現產生了一堆文件網絡

其實這些文件都是線程,那麼哪一個文件是主線程呢?能夠經過代碼中的關鍵字查找下多線程

-- 查找包含step1 的文件
grep 'step1' ./*
複製代碼

果真其中最大的這個163文件有個"write(1, "step1:new ServerSocket(80)", 26) = 26"socket

能夠打開這個文件看下,能夠找到這個操做在文件中的位置(具體的含義咱們後面再分析)測試

進程線程分析

另外能夠經過jps查看線程spa

在linux中一切皆文件,能夠看看162這個進程中有哪些東西,能夠進入linux根目錄下的/proc/進程id 目錄中查看,有看到一堆東西 操作系統

先看下task文件,打開這個會發現這些數字是否是和上面ooxx.*是同樣的呢,沒錯其實這個jdk進程中的線程,知道這個以後你就能夠查看本身應用下的線程數量

還有一個目錄fd,能夠看到一些數據這裏面的東西叫文件描述符,任何一個程序都有io,0、一、2是三個基本的io

  • 0 標準輸入
  • 1 標準輸出
  • 2 錯誤輸出

這些流在java中是對象,在操做系統中都是文件,經過數字的方式表明,相似於java中的變量

  • 三、4 是java程序特有的庫
  • 五、6 實際上是咱們的程序啓動後的server會監聽8090,兩個分部是ipv四、ipv6

經過網絡狀態這個命令 netstat -natp;能夠看到state是LISTEN狀態,只有服務端有監聽狀態,客戶端能夠經過這個端口號鏈接

系統調用分析

那麼咱們用nc命令鏈接看看,能夠看到一個鏈接進來java程序中多一個記錄,而且文件描述符相比以前也多了一個socket

nc localhost 8090
複製代碼

網絡鏈接

文件描述符

而後一開始程序所在的文件夾,找到主線程,打開後查找先鏈接的端口號49482;能夠看到

accept(6, {sa_family=AF_INET, sin_port=htons(49482), sin_addr=inet_addr("127.0.0.1")}, [16]) = 7

回顧下以前的方法有個server.accept(),內核中也有accept,能夠理解java中的一些方法是對內核的包裝;在主線程的文件中能夠看到生成的文件描述符以及程序執行發生具體的系統調用

你也可使用man命令查看各類指令的做用; 先介紹到這裏吧,後面會繼續介紹下nio的一些內容

相關文章
相關標籤/搜索