《Linux环境下C编程指南V2》杨树青
注:本书对于gcc/gdb/make等开发工具讲得比较详细。
0. 杂问
Q:wait()返回第一个已返回的子进程status,其它如何处理?
Q:当父进程没有捕获子进程信号,导致其它子进程阻塞,这些子进程就成为zombie进程???
1. TCP三次握手过程
* Server:调用listen(),并调用accept(),等待Client发起请求
* Client:调用connect(),向server发送SYN1请求
* Server:回复ACK1,并发送SYN2请求给Client,此时,连接被放进一个”未完成连接“对列中
* Cllient:回复ACK2
* Server:接收到ACK2,完成连接,并将连接放进”已完成连接队列“中
* Server:从”已完成连接队列“中取得已建连接的socket
注:监听socket有2个相关的连接队列,”未完成“”已完成“
2. 几个系统调用
int shutdown(int sockfd, int how);
int getsockname(...)
int getpeername(...)
3. 并发服务器实现一个特殊考虑
子进程:close(listen_fd),父进程:close(com_fd)
解释:
父子进程都有文件描述符副本,其本质是对应到一个”打开文件列表“中的一个表项
close(fd)实际动作是删除当前进程中相关表项
另,文件的真实存在由内核中的文件内核对象来表示,close(fd)每执行一次减少内核对象引用计数而已!
4. I/O模式:5种类型
* 阻塞式
等待I/O操作完成,被唤醒并继续执行
socket默认为阻塞式I/O,recvfrom()需要等待数据从内核copy到用户进程空间数据准备好,才会返回
* 非阻塞式
立即返回,若未准备好,则返回error
一般需要轮询数据
* I/O复用模式
通常使用select()
* 信号驱动I/O模式
内核准备好数据后(复制到用户空间),发出SIGIO
在SIGIO的handler中,调用类似recvfrom()等语句来处理数据
#info SIGIO
24.2.4 Asynchronous I/O Signals
-------------------------------
The signals listed in this section are used in conjunction with
asynchronous I/O facilities. You have to take explicit action by
calling `fcntl' to enable a particular file descriptor to generate
these signals (*note Interrupt Input::). The default action for these
signals is to ignore them.
-- Macro: int SIGIO
This signal is sent when a file descriptor is ready to perform
input or output.
On most operating systems, terminals and sockets are the only
kinds of files that can generate `SIGIO'; other kinds, including
ordinary files, never generate `SIGIO' even if you ask them to.
In the GNU system `SIGIO' will always be generated properly if you
successfully set asynchronous mode with `fcntl'.
-- Macro: int SIGURG
This signal is sent when "urgent" or out-of-band data arrives on a
socket. *Note Out-of-Band Data::.
-- Macro: int SIGPOLL
This is a System V signal name, more or less similar to `SIGIO'.
It is defined only for compatibility.
* 异步I/O
效率最高,一直到等待与复制(到用户空间)工作完成后,内核才通知进程
5. 几种主要的高级I/O方式(注:此话题需要稍后详细研究 )
Q:这些东东只和TCP socket有关吗???
* select()
以前比较流行的多路复用方式,尤其对于并发网络服务器编程
但是:
一个进程中对打开的FD数目有限制,默认Linux下为1024,对于大并发系统明显不够用
使用多process方案虽然可缓解此问题,但process相比thread带来的开销在大并发下不可小视
效率随socket数目增加而线性下降,原因是select()要对所有socket进行扫描
* poll()
非阻塞式I/O,采用了轮询
Q:效率方面和select()比如何?更少用吗?
但是:
缺点方面主要仍是随FD数量增加效率线性下降,同select()
* epoll()
实现了“伪"AIO
只扫描”活跃“socket,效率明显高于select()/poll()
最大socket数目无静态限制,主要和内存大小有关,在偶的机器上VMWare/Redhat Enterprise中,数字如下:
[root@localhost ~]# cat /proc/sys/fs/file-max
44281
6. UDP编程
Q:当数据包发生丢失,将导致客户阻塞于recvfrom(),从而形成zombie process?
提供可靠机制的唯一办法是在发送端设置超时重传机制
Q:服务器未启动,但客户端无法检测?异步错误?
7. 原始socket编程
可处理ICMP协议数据?
注:研究一下ping程序的实现