重讀UNP(UNIX網絡編程)13章到31章筆記整理(結合TLPI和APUE兩書的筆記整理)

因爲UNP第三部分(第三版13-31章)的內容結合APUE(UNIX環境高級編程)和TLPI(The Linux Programming Interface)來看才能比較清晰,所以筆記整理會穿插很多這兩本書的內容

13章

  • 13.4節:自定義一個daemon_init函數,涉及到知識點爲“如何創建一個daemon(守護進程)”,實現步驟如下:
    1. fork之後殺掉父進程(此時子進程被init收養)這是爲了爲下一步setsid做準備,因爲只有不是進程組首進程的進程才能調用setsid,
    2. setsid,創建一個新的會話並斷開與之前的控制終端的關係,
    3. 再次fork並殺掉首進程, 這樣就確保了子進程不是一個會話首進程, 根據linux中獲取終端的規則(只有會話首進程才能請求一個控制終端), 這樣進程永遠不會重新請求一個控制終端
    4. 清楚進程的umask,確保daemon創建文件和目錄時擁有相應的權限
    5. 修改進程的當前工作目錄, 通常修改到/目錄
    6. 關閉進程所有不再需要的文件描述符
    7. 打開/dev/null使文件描述符0、1、2指向這個設備, 以防止daemon調用在這些描述符上做I/O操作的庫函數而不會意外的失敗
#include    "unp.h"
#include    <syslog.h>

#define MAXFD   64

extern int  daemon_proc;    /* defined in error.c */

int
daemon_init(const char *pname, int facility)
{
    int     i;  
    pid_t   pid;

    if ( (pid = Fork()) < 0)
        return (-1);
    else if (pid)
        _exit(0);           /* parent terminates */

    /* child 1 continues... */

    if (setsid() < 0)           /* become session leader */
        return (-1);

    Signal(SIGHUP, SIG_IGN);
    if ( (pid = Fork()) < 0)
        return (-1);
    else if (pid)
        _exit(0);           /* child 1 terminates */

    /* child 2 continues... */

    daemon_proc = 1;            /* for err_XXX() functions */

    chdir("/");             /* change working directory */

    /* close off file descriptors */
    for (i = 0; i < MAXFD; i++)
        close(i);

    /* redirect stdin, stdout, and stderr to /dev/null */
    open("/dev/null", O_RDONLY);
    open("/dev/null", O_RDWR);
    open("/dev/null", O_RDWR);

    openlog(pname, LOG_PID, facility);

    return (0);             /* success */
}

引申知識,作業控制以及相關命令:

這裏寫圖片描述

  • 另注:

注:但是如上方到後臺執行的進程,其父進程還是當前終端shell的進程,而一旦父進程退出,則會發送hangup信號給所有子進程,子進程收到hangup以後也會退出。

nohup和setsid用法

如果我們要在退出shell的時候繼續運行進程,則需要使用nohup忽略hangup信號,或者setsid將父進程設爲init進程;
這裏寫圖片描述

b@b-VirtualBox:~/my_temp_test$ nohup ./o_multi_thread_process &
[1] 3487
b@b-VirtualBox:~/my_temp_test$ nohup: ignoring input and appending output to ‘nohup.out’
^C
b@b-VirtualBox:~/my_temp_test$ jobs
[1]+  Running                 nohup ./o_multi_thread_process &
b@b-VirtualBox:~/my_temp_test$ ps -ef | grep multi
b         3487  3004  0 20:05 pts/3    00:00:00 ./o_multi_thread_process
b         3488  3487  0 20:05 pts/3    00:00:00 ./o_multi_thread_process
b         3491  3004  0 20:05 pts/3    00:00:00 grep --color=auto multi
b@b-VirtualBox:~/my_temp_test$ bg %1
bash: bg: job 1 already in background
b@b-VirtualBox:~/my_temp_test$ fg %1
nohup ./o_multi_thread_process
^Z
[1]+  Stopped                 nohup ./o_multi_thread_process
b@b-VirtualBox:~/my_temp_test$ bg %1
[1]+ nohup ./o_multi_thread_process &
b@b-VirtualBox:~/my_temp_test$ jobs -l
[1]+  3487 Running                 nohup ./o_multi_thread_process &
b@b-VirtualBox:~/my_temp_test$ fg %1
nohup ./o_multi_thread_process
^C
b@b-VirtualBox:~/my_temp_test$ jobs
b@b-VirtualBox:~/my_temp_test$ ps -ef | grep multi
b         3499  3004  0 20:11 pts/3    00:00:00 grep --color=auto multi
b@b-VirtualBox:~/my_temp_test$ setsid ./o_multi_thread_process &
[1] 3502
b@b-VirtualBox:~/my_temp_test$ ProcessA: 3503 step1
ProcessA: 3503 thread 139947724490496 step2
ProcessA: 3503 thread 139947724490496 step3
ProcessB: 3504 step1
ProcessB: 3504 step2
ProcessB: 3504 step3
^C
[1]+  Done                    setsid ./o_multi_thread_process
b@b-VirtualBox:~/my_temp_test$ ps -ef | grep multi
b         3503  1256  0 20:12 ?        00:00:00 ./o_multi_thread_process
b         3504  3503  0 20:12 ?        00:00:00 ./o_multi_thread_process
b         3507  3004  0 20:12 pts/3    00:00:00 grep --color=auto multi
b@b-VirtualBox:~/my_temp_test$ jobs

disown用法

那麼對於已經在後臺運行的進程,該怎麼辦呢?可以使用disown命令

b@b-VirtualBox:~/my_temp_test$ ./o_multi_thread_process &
[1] 3523
b@b-VirtualBox:~/my_temp_test$ ProcessA: 3523 step1
ProcessA: 3523 thread 140501901821696 step2
ProcessA: 3523 thread 140501901821696 step3
ProcessB: 3524 step1
ProcessB: 3524 step2
ProcessB: 3524 step3
^C
b@b-VirtualBox:~/my_temp_test$ jobs -l
[1]+  3523 Running                 ./o_multi_thread_process &
b@b-VirtualBox:~/my_temp_test$ disown -h %1
b@b-VirtualBox:~/my_temp_test$ jobs
[1]+  Running                 ./o_multi_thread_process &

16章

  • 16.3節 : 非阻塞connect

    • 有三個用途:
      • 我們想在connect的時候處理其他事情
      • 可以同時建立多個連接
      • 可以通過select設置一個更短一點的超時時間
    • 實現步驟:
      1. 用fcntl把套接字設置爲非阻塞
      2. 處理客戶端和服務器都在同一主機上的情況
      3. 使用select設置超時,並處理超時情況
      4. 處理當連接建立的時候,描述符變爲可寫;以及當連接建立遇到錯誤的時候, 描述符變爲可寫並可讀的情況
  • 16.6節 : 非阻塞accept,

    • 用於解決下面問題:

      “用select檢測socket狀態,如果有連接就調用accept,這樣如果在select檢測到由連接請求,在調用accept之前,這個請求斷開了,然後調用accept的時候就會阻塞在哪裏,除非這時有另外一個連接請求,如果沒有,則一直被阻塞在那裏。”

    • 解決方案:

      使用select在一個監聽套接字準備好要被accept時總是把套接字設置爲非阻塞

26章和30章

介紹了線程和併發/並行的服務器設計範式,等下篇TLPI/APUE的筆記一起整理吧

發佈了33 篇原創文章 · 獲贊 14 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章