由tail -f x.log | grep "a"引發的思考
由一條命令引發的進程通信猜想:
tail -f catalina.log | grep "exception" 會產生幾個進程?
從進程通信的角度來看, | 屬於pipe(無名管道)的實現,理論上應該是2個,ps aux 看一下:
sean 22805 0.0 0.0 4288248 956 s001 S+ 3:53PM 0:00.00 grep exception sean 22804 0.0 0.0 4287216 760 s001 S+ 3:53PM 0:00.00 tail -f catalina.log
嗯,看來猜對了 :)這是為什麼呢?上面我們聯想到了pipe, 談到pipe又不禁會聯想到父子進程間通信。(其實也是java中nio的pipe, 殊途同歸),我們先看下單進程怎麼自己跟自己"對話":
#include <unistd.h>#include <stdio.h>#include <stdlib.h>void ps_pipe() { /** * 單進程的pipe讀寫測試, "自言自語/自娛自樂" * 既然是無名管道,那麼這個文件是不存在的,既然文件是不存在的,那麼也不存在oflag * 管道中的東西讀完就刪除了,如果管道中沒有任何東西可以讀取了,則會產生讀阻塞,讀進程的狀態就成了S(sleeping) * pipe的本質是單向的queue */ int pipe_fds[2]; int ret_pipe = pipe(pipe_fds); if (ret_pipe == -1) { perror("create a pipe error"); exit(-1); } pid_t pid = getpid(); // 寫入pipe char write_buf[] = "write something by pipe"; write(pipe_fds[1], write_buf, sizeof(write_buf)); printf("ps[%d] : write to pipe, content:[%s]
", pid, write_buf); // 讀取pipe char read_buf[sizeof(write_buf)]; read(pipe_fds[0], read_buf, sizeof(read_buf)); printf("ps[%d] : read from pipe, content:[%s]
", pid, read_buf); // close fd close(pipe_fds[0]); close(pipe_fds[1]); return;}
單進程"自言自語"的輸出結果:
ps[2311] : write to pipe, content:[write something by pipe] ps[2311] : read from pipe, content:[write something by pipe]
下面再改造下上述代碼,以fork創建父子進程進行pipe通信測試:
#include <unistd.h>#include <stdio.h>#include <stdlib.h>void ps_fork_pipe() { int fd[2]; int ret_pipe = pipe(fd); if (ret_pipe != 0) { perror("create nameless pipe error"); } char buf[] = "im a pipe"; int pid = fork(); if (pid == 0) {//child ps : write to pipe int pid = getpid(); write(fd[1], buf, sizeof(buf)); printf("process[%d] write buf[%s] to pipe
", pid, buf); } else if (pid > 0) {//parent ps : read from pipe char read_buf[sizeof(buf)]; int pid = getpid(); read(fd[0], read_buf, sizeof(read_buf)); printf("process[%d] read from pipe, content : %s
", pid, read_buf); } else { perror("fork error"); exit(-1); } return;}
輸出結果:
process[2891] write buf[im a pipe] to pipe process[2890] read from pipe, content : im a pipe
觀察上面的進程ID,不難發現 2890和2891是連續數字,這個是父子進程血緣關係的直觀體現,那麼本文最上面列印的ps aux,2個進程ID分別是22805和22804,不難聯想到他們內部的實現也應該是父子進程的pipe通信模式了。
推薦閱讀:
※如何在 Linux 中使用一個命令升級所有軟體
※如何優雅地使用 rm 防止誤刪除?
※《Hacknet》故事向攻略 —— 第三章 生涯起始(上)
※如何在 Linux 中使用 history 命令
※Linux運維工程師學習經驗分享!Redhat+CentOS
TAG:Linux |