signal
子进程结束时, 父进程会收到这个信号。
如果父进程没有处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,这时的子进程称为僵尸进程。
这种情况我们应该避免(父进程或者忽略SIGCHILD信号,或者捕捉它,或者wait它派生的子进程,或者父进程先终止,这时子进程的终止自动由init进程来接管)。
使用signal(SIGCHLD,SIG_IGN)来处理僵尸进程
第二个参数为处理函数,配合waitpid 可处理僵尸进程,当子进程结束,会向父进程发送信号.
内核一旦发现进程指定的一个或多个IO条件就绪(也就是输入已准备好被读取,或者描述符已能承接更多的输出)他就通知进程,这个能力被称作I/O复用
适用场合:
1 当客户处理多个描述符(通常是交互式输入和网络套接字),必须用I/O复用,
2 如果一个TCP服务器既要处理监听套接字,又要处理已连接的套接字,一般就要用I/O
3 如果一个服务器既要处理TCP,又要处理UDP,一般就要用I/O
4 如果一个服务器要处理多个服务或者多个协议,一般就要用I/O
5种I/O模型
<1> 阻塞式I/O
<2> 非阻塞式
<3> I/O复用(select .poll. epoll...)
<4> 信号驱动式I/O(SIGIO)
<5> 异步I/O (POSIX的aio_系列函数)
select 函数
该函数允许进程指示内核等待多个事件中的任何一个发生,并只有一个或多个事件发生或经历一段指定时间后才会
唤醒它。
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptest,const struct timval *timeout);
timeout: 它告知内核等待所指定描述符中任何一个就绪荷花多长时间,timeval结构用于这段时间的秒数和微秒数
struct timeval{
long tv_sec;
long tv_usec;
};
该参数有三种可能
(1)永远等待下去,仅在有一个描述符准备好I/O时才返回。为此参数设置为空指针
(2)等待固定的时间,在有一个描述符准备好I/O时才返回。但是不超过该参数设置好的时间。
(3)不等待,检查描述符后立即返回,这称为轮询,设置为0。
中间的三个参数readset,writeset和exceptset指定我们要让内核测试读,写和异常条件的描述符.目前只支持的
异常条件只有2个
<1>某个套接字的带外数据的到达
<2>某个已置为分组模式的伪终端存在可从其主端读取的控制状态信息