重读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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章