(1)用户通过终端输入 (2)进程执行(3)一个进程调用kill向另一个进程发送信号
1)同步信号 异步信号
2)可靠信号 : 信号被递送多次 不可靠信号: 只被递送一次的信号
//捕捉信号
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void capture(int signum){ printf("SIGINT is capture!\n"); } int main(int argc, char *argv[]){ int i=10; if(signal(SIGINT,capture) == SIG_ERR){ printf("Can't catch SIGINT"); exit(1); } printf("waiting for signal...\n"); while(i > 0){ printf("Now i=%d \n",i); sleep(1); i--; } return 0; }//忽略信号
#include <stdio.h> #include <signal.h> #include <unistd.h> int main(int argc,char *argv[]){ int i=10; signal(SIGINT,SIG_IGN); printf("waiting for signal ...\n"); while(i > 0){ sleep(1); i--; printf("Now i = %d,but you can't stop this program by Ctrl + C\n",i); } return 0; }//恢复信号的默认处理
#include <stdio.h> #include <signal.h> void capthensfl(int signum){ printf("SIGINT is capture !\n"); signal(SIGINT,SIG_DFL); printf("SIGINT now is defaulted !\n"); } int main(int argc,char *argv[]){ int i=10; signal(SIGINT,capthensfl); printf("waiting for signal...\n"); while(i > 0){ sleep(1); printf("Now i = %d\n",i); i--; } return 0; }sigaction的结构:
struct sigaction{ union{ _sighandler_t _sa_handler; void(*_sa_sigaction)(int , struct siginfo *, void *); } _u; sigset_t sa_mask; unsigned long sa_flags; };sa_sigaction的说明: void (sa_sigaction)(int, struct siginfo ,void *);
第一个参数:要响应的信号 。
第二个参数:记录导致产生信号的原因、类型等 。
第三个参数:信号发生时被中断的上下文环境 信号能传递简单的信息。
//使用sa_sigaction类型函数
#include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> void fun(int signo, siginfo_t *info, void *context){ printf("Test for sa_sigaction !\n"); } int main(int argc,char *argv[]){ struct sigaction action,oldaction; sigemptyset(&action.sa_mask); action.sa_flags=SA_SIGINFO; action.sa_sigaction=fun; sigaction(SIGINT,&action,&oldaction); printf("waiting for signal...\n"); while(1){ pause(); } return 0; }要求:发送信号的进程的用户ID和目标进程的用户ID相同,或发送信号的进程的owner是一个超级用户。
//kill 使用示例
#include <stdio.h> #include <stdlib.h> #include <signal.h> void fun(int signo){ printf("Process capture SIGINT"); signal(SIGINT,SIG_DFL); } int main(int argc,char *argv[]){ int pid; if((pid=fork()) == -1){ perror("fork"); exit(EXIT_FAILURE); } else if( pid == 0){ signal(SIGINT,fun); printf("Child %d waiting for parent %d send signal\n",getpid(),getppid()); pause(); pause(); } else{ sleep(1); printf("Parent %d will send signal to child %d \n",getppid(),getpid()); kill(pid,SIGINT); wait(NULL); } return 0; }/* * **信号的应用示例: 父进程执行文件复制操作,如果收到SIGUSR1信号,就打印出当前的复制进度 子进程每隔一个固定时间向父进程发送SIGUSR1信号** */
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <fcntl.h> int count; //当前复制大小 int file_size; //文件的大小 //父进程对SIGUSR1信号的处理函数 void sig_usr(int signum){ float i; //求出复制进程 i = (float)count/(float)file_size; printf("current over : %0.0f%%\n",i*100); } //子进程对SIGUSR1信号的处理,即向父进程发送SIGUSR1信号 void sig_alarm(int signo){ kill(getppid(),SIGUSR1); } //主函数 int main(int argc ,char *argv[]){ pid_t pid; int i; int fd_src,fd_des; char buf[128]; if(argc != 3){ printf("the format must be : command src_file des_file \n"); return -1; } //以只读方式打开源文件 if((fd_src = open(argv[1],O_RDONLY)) == -1){ perror("open fd_src"); exit(EXIT_FAILURE); } //获取源文件大小 file_size = lseek(fd_src,0,SEEK_END); //重新设置读写位置为文件头 lseek(fd_src,0,SEEK_SET); //以读写方式打开目标文件,如果不存在就创建 if((fd_des = open(argv[2],O_RDWR|O_CREAT,0644)) == -1){ perror("open fd_des"); exit(EXIT_FAILURE); } //进程创建失败 if((pid = fork() == -1)){ perror("fork"); exit(EXIT_FAILURE); } //父进程 else if(pid > 0){ //安装信号 signal(SIGUSR1,sig_usr); do{ memset(buf,'\0',128); //复制数据 if((i = read(fd_src,buf,1)) == -1){ perror("read"); exit(EXIT_FAILURE); } //如果复制完成,向子进程发送SIGINT信号,终止 else if(i == 0){ kill(pid,SIGINT); break; } else{ //执行复制操作 if(write(fd_des,buf,i) == -1){ perror("write"); exit(EXIT_FAILURE); } count += i; //更新已经复制的文件的大小 } }while(i != 0); //等待子进程退出 wait(pid,NULL,0); exit(EXIT_SUCCESS); } //子进程 else if(pid == 0){ usleep(1); signal(SIGALRM,sig_alarm); ualarm(1,1); while(i){ ; } exit(EXIT_SUCCESS); } return 0; }