【1】.信号。所谓的信号就是一种软件中断。内核接受到信号有三种处理方式:忽略,执行默认动作,或者进行捕捉信号(捕捉到信号进行用户自定义的函数操作)。目前我遇到几个用到的信号有:
SIGALRM:超时,在alarm()函数中用到;SIGINT:终端终止符,delete
SIGUSR1,SIGUSR2:用户自定义的信号1,2
SIGCHILD:子进程终止或者停止时,SIGCHILD发送给父进程
【2】.(1)signal函数
形式: void ( *signal ( int signo , void ( *func ) ( int )))( int );
signo是信号名,当函数接收到此信号名,则进行后面的func操作。
func:可以是三种操作,忽略SIG_IGN,执行默认操作SIG_DFL,用户自定义函数操作。
对于第二个参数,这里的int是调用的函数的参数,而在此表达式其实是没有参数的。
(2)执行一个程序时,如果用到了exec则忽略信号,否则均为信号的系统默认操作。信号捕捉函数也可以捕捉父进程得到的相应子进程。
【3】不可靠信号,有几种情况会产生不可靠信号,如:信号发生到调用signal信号之前可能会出现一个新的信号,有些信号不想起发生,但是并不能对其关闭,只能进行忽略操作。
【4】中断的系统调用。保证系统调用执行的完整性不受信号破坏,将系统调用设置为两种:低速系统调用和其他系统调用。低速系统调用保证操作完整性,可能会使进程永远阻塞。包括读写(某些文件),打开(类型文件),pause和wait,进程间通讯ioctl等。
【5】可重入函数,可以在函数执行过程中转而去处理其他函数,返回函数也可以继续进程处理
【6】kill和raise函数。kill(pid_t pid, int signo)//将特定信号signo传送给进程或者进程组pid;raise(int signo)//可以将信号发送给自己
kill函数中,pid== -1时,可以把信号发送给系统所有的进程,当然前提是调用kill函数的用户有权限
【7】alarm函数
unsigned int alarm(unsigned int seconds)//定时器。
(1)返回值:0或者剩余秒数。到达seconds值将产生SIGALRM信号
(2)在原来已经有一个alarm且还没有到超时时间的情况下,设置新的超时时间会重置定时器,函数返回的是以前的剩余时间。特别的如果第二次设置值 为0,则将会取消定时器。
【8】pause函数
使进程挂起直至有信号到达。成功返回-1并将errno设置为EINTR.
程序展示:
【1】10-4
static void sig_alarm(int signo)
{}
unsigned int sleep1(unsigned int nsecs)
{
if(signal(SIGALRM, sig_alrm)== SIG_ERR) //收到了SIGALRM信号,运行sig_alrm函数
{return(nsecs);}
alarm(nsecs); //第一步,运行此函数,运行完后则发出SIGALRM信号
pause(); //第二等待信号到来。第一步运行完则收到SIGALRM信号
return(alarm(0)); //最后
}
【2】
void child_handler(int signo)
{
if(signo == SIGCHLD)
{
printf("end.\n");
wait(NULL); //等着子进程结束了,转去main函数退出
}
}
int main()
{
int pid;
int i = 0;
signal(SIGCHLD,child_handler); //子进程结束则产生此信号
if((pid = fork()) < 0) //fork产生子进程
{
printf("failed");
}else if(pid == 0)
{
printf("son\n");
}else{
sleep(1); //此处sleep(1)使得程序被挂起,到调用程序捕捉到了信号SIGCHLD,转而执行信号处理程序signal函数。不这样写,函数直接从底下运行跑了
}
exit(0);
}