重读UNP(UNIX网络编程)13章到31章笔记整理(结合TLPI和APUE两书的笔记整理)
2017-07-28 02:20
344 查看
因为UNP第三部分(第三版13-31章)的内容结合APUE(UNIX环境高级编程)和TLPI(The Linux Programming Interface)来看才能比较清晰,所以笔记整理会穿插很多这两本书的内容
fork之后杀掉父进程(此时子进程被init收养)这是为了为下一步setsid做准备,因为只有不是进程组首进程的进程才能调用setsid,
setsid,创建一个新的会话并断开与之前的控制终端的关系,
再次fork并杀掉首进程, 这样就确保了子进程不是一个会话首进程, 根据linux中获取终端的规则(只有会话首进程才能请求一个控制终端), 这样进程永远不会重新请求一个控制终端
清楚进程的umask,确保daemon创建文件和目录时拥有相应的权限
修改进程的当前工作目录, 通常修改到/目录
关闭进程所有不再需要的文件描述符
打开/dev/null使文件描述符0、1、2指向这个设备, 以防止daemon调用在这些描述符上做I/O操作的库函数而不会意外的失败
另注:
注:但是如上方到后台执行的进程,其父进程还是当前终端shell的进程,而一旦父进程退出,则会发送hangup信号给所有子进程,子进程收到hangup以后也会退出。
有三个用途:
我们想在connect的时候处理其他事情
可以同时建立多个连接
可以通过select设置一个更短一点的超时时间
实现步骤:
用fcntl把套接字设置为非阻塞
处理客户端和服务器都在同一主机上的情况
使用select设置超时,并处理超时情况
处理当连接建立的时候,描述符变为可写;以及当连接建立遇到错误的时候, 描述符变为可写并可读的情况
16.6节 : 非阻塞accept,
用于解决下面问题:
“用select检测socket状态,如果有连接就调用accept,这样如果在select检测到由连接请求,在调用accept之前,这个请求断开了,然后调用accept的时候就会阻塞在哪里,除非这时有另外一个连接请求,如果没有,则一直被阻塞在那里。”
解决方案:
使用select在一个监听套接字准备好要被accept时总是把套接字设置为非阻塞
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的笔记一起整理吧相关文章推荐
- SSAS 工作笔记(3) 结合网上资料和个人实践理解整理
- 《Effective STL》重读笔记整理
- 《Effective STL》重读笔记整理
- 《Effective STL》重读笔记整理
- 《Effective STL》重读笔记整理
- 重读UNIX网络编程第二章笔记修正
- JavaScript学习笔记整理
- 从GLM广义线性模型到线性回归、二项式及多项式分类——机器学习笔记整理(一)
- java学习笔记知识点整理02
- xsj的Java学习笔记整理——JDBC
- map,set,vector,string笔记整理(C++)
- Linux内核【链表】整理笔记(1)
- 正则表达式注册表验证笔记整理
- 弱鸡的笔记整理
- 从0开始学Swift笔记整理(三)
- Javascript进阶篇——(流程控制语句)笔记整理
- 读《50 Android Hacks》笔记整理Hack 1~Hack 8
- Spring学习笔记(网易博客整理版本)
- 汇编debug中的常用指令,以及一些常用寄存器的使用方法整理,仅一些笔记,不喜勿喷
- 近期的bug常见[从以前的零散笔记中整理]