您的位置:首页 > 理论基础 > 计算机网络

重读UNP(UNIX网络编程)13章到31章笔记整理(结合TLPI和APUE两书的笔记整理)

2017-07-28 02:20 344 查看
因为UNP第三部分(第三版13-31章)的内容结合APUE(UNIX环境高级编程)和TLPI(The Linux Programming Interface)来看才能比较清晰,所以笔记整理会穿插很多这两本书的内容

13章

13.4节:自定义一个daemon_init函数,涉及到知识点为“如何创建一个daemon(守护进程)”,实现步骤如下:

fork之后杀掉父进程(此时子进程被init收养)这是为了为下一步setsid做准备,因为只有不是进程组首进程的进程才能调用setsid,

setsid,创建一个新的会话并断开与之前的控制终端的关系,

再次fork并杀掉首进程, 这样就确保了子进程不是一个会话首进程, 根据linux中获取终端的规则(只有会话首进程才能请求一个控制终端), 这样进程永远不会重新请求一个控制终端

清楚进程的umask,确保daemon创建文件和目录时拥有相应的权限

修改进程的当前工作目录, 通常修改到/目录

关闭进程所有不再需要的文件描述符

打开/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... */<
4000
/span>

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设置一个更短一点的超时时间

实现步骤:

用fcntl把套接字设置为非阻塞

处理客户端和服务器都在同一主机上的情况

使用select设置超时,并处理超时情况

处理当连接建立的时候,描述符变为可写;以及当连接建立遇到错误的时候, 描述符变为可写并可读的情况

16.6节 : 非阻塞accept,

用于解决下面问题:

“用select检测socket状态,如果有连接就调用accept,这样如果在select检测到由连接请求,在调用accept之前,这个请求断开了,然后调用accept的时候就会阻塞在哪里,除非这时有另外一个连接请求,如果没有,则一直被阻塞在那里。”

解决方案:

使用select在一个监听套接字准备好要被accept时总是把套接字设置为非阻塞

26章和30章

介绍了线程和并发/并行的服务器设计范式,等下篇TLPI/APUE的笔记一起整理吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: