进程组
1、进程在其proc结构中有p_pgrp域
2、p_pgrp相同的进程共同构成一个进程组
3、p_pgrp和p_pid的进程是该进程组的组长
4、setsid()系统调用将proc中的p_pgrp改为自己的p_pid,从而脱离原进程组,成为新进程组的组长
5、fork()创建的进程集成父进程的p_pgrp,与父进程同组。
注:kill命令pid为0时,向与本进程同组的所有进程发送信号。
信号机制
信号是送到进程的“软件中断”,通知进程发生了非正常事件。
信号的产生
1、进程自己或其他进程发出的kill(),alarm()调用。
2、核心产生信号
段违例信号SIGSEGV:当进程试图存取它的地址空间以外的存贮单元时,内核向进程发送段违例信号
浮点溢出信号SIGFPE:零做除数时,内核向进程发送浮点溢出信号
信号SIGPIPE:关闭管道读端则写端write导致进程收到信号SIGPIPE
信号类型
在“sys/signal.h”文件中定义宏
SIGTERM 软件终止信号。用kill命令时产生
SIGHUP 挂断。当从注册shell中logout时,
同一进程组的所有进程都收到SIGHUP
SIGINT 中断。用户按Del键或Ctrl-C键时产生
SIGQUIT 退出。按Ctrl-\时产生,产生core文件
SIGALRM 闹钟信号。计时器时间到,与alarm()有关
SIGCLD 进程的一个子进程终止。
SIGKILL 无条件终止,该信号不能被捕获或忽略。
SIGUSR1,SIGUSR2 用户定义的信号
SIGFPE 浮点溢出
SIGILL 非法指令
SIGSEGV 段违例
进程对于信号的处理
有3种处理方法,
1、忽略(不甩你)
2、设置为缺省处理方式
3、信号被捕捉,用户自己事先定义一个函数,当信号发生就去执行这个函数。
缺省
signal(SIGINT,SIG_DFL);
信号被忽略
signal(SIGINT, SIG_IGN);
在执行了这条语句之后,进程就不再收到SIGINT信号了。
注:被忽略了的信号作为进程的一种属性会被子进程所继承。
信号被捕捉
信号被捕捉并由一个用户函数来处理
信号到达时,这个函数将被调用来处理那个信号
#include
sig_handle(int sig)
{
printf(”HELLO! Signal %d catched.\n”,sig);
}
main()
{
signal(SIGINT, sig_handle);
signal(SIGQUIT, sig_handle);
for(;;) sleep(500);
}
注意:在信号的用户函数被调用之前,自动被重置到它的缺省行为。
僵尸进程
僵尸子进程:子进程终止,僵尸进程出现,父进程使用wait系统调用收尸后消除僵尸。
僵尸进程对系统资源的占用:僵尸进程不占用内存资源,但占用内核proc表项,僵尸进程太多会导致proc表耗尽而无法再创建新进程。
子进程终止后的通知机制:子进程终止后,会向父进程发送信号SIGCLD
不导致僵尸子进程出现的方法:
1、忽略对SIGCLD信号的处理,signal(SIGCLD, SIG_IGN);
2、捕捉SIGCLD信号,执行wait()系统调用。
捕获信号SIGCLD
int subprocess_die(int sig)
{
int pid, status;
pid = wait(&status);
.
.
.
signal(SIGCLD, subprocess_die);
}
int main()
{
signal(SIGCLD, subprocess_die);
.
.
.
}