SIGPIPE:
当服务器close一个连接时,若客户端继续向套接字发送数据,根据TCP协议规定,会收到一个RST响应,客户端再往这个套接字发送数据时,系统会发出一个SIGPIPE信号,SIGPIPE的默认处理方式是结束进程。
如果不希望进程在这样的情况下被强制终止,可以忽略该信号,处理方法有一下两种:
1.忽略信号
void signal(SIGPIPE, SIG_IGN);
2.执行自定义信号处理函数
signal(SIGPIPE, handler);
void handler(int sig)
{
if (sig == SIGPIPE)
printf("accept SIGPIPE!!\n");
return;
}
SIGCHILD:
子进程结束时,父进程会收到这个信号。
如果父进程不处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,这时的子进程被称为僵尸进程。这种情况,我们应该避免。
1.忽略信号(类似SIGPIPE),将子进程交由init进程处理
2.执行自定义信号处理函数(类似SIGPIPE)
3.父进程wait/waitpid回收子进程资源
// 父进程调用wait函数,将阻塞等待,直到子进程退出
// 返回值:成功返回子进程id, 失败返回-1(无子进程)。
// status传出子进程的退出状态
pid_t wait(int *status);
if (WIFEXITED(status)) //IFEXITED非0,进程正常退出
{
printf("exited, status=%d\n", WEXITSTATUS(status));
}
else if (WIFSIGNALED(status)) //WIFSIGNALED非0,进程被信号终止
{
printf(killed by signal %d\n", WTERMSIG(status));
}
else if (WIFSTOPPED(status)) //IFSTOPPED非0,进程收到某个信号而暂停
{
printf("stopped by signal %d\n", WSTOPSIG(status));
}
else if (WIFCONTINUED(status)) //IFCONTINUED非0,进程从暂停状态变为继续运行状态
{
printf("continued\n");
}
// 等待指定子进程退出,可以不阻塞父进程
// 返回值:成功返回子进程id, 失败返回-1(无子进程)。
// options:WNOHANG,若pid对应的子进程没有结束,函数不阻塞立即返回,返回值为0;
// WUNTRACED,为了实现某种操作,由pid指定的任一进程已被暂停,而且从来没有报告过,则返回
// 其状态
// 0,同wait,阻塞。
// pid: >0 表示回收指定id的子进程
// -1 表示回收任意子进程(同wait)
// 0 表示回收和当前调用waitpid进程一个组的任意子进程
// <-1 表示回收指定进程组内的任意子进程,比如-5505表示回收进程组id为5505的任意子进程
pid_t waitpid(pid_t pid, int *status, int options);
// 一次wait和waitpid只能回收一个子进程,要回收多个子进程需要循环调用