信号
信号是一种终端机制,程序运行到一半的时候接收到了某种通知,程序就会立刻中断运行,转而去处理通知。
登记信号
一个进程只会接收默认的几个信号
如果想要让一个进程接收特定信号的话,必须提前在该进程中登记一下想要接收的信号
typedef void (*sighandler_t)(int);原型:sighandler_t signal(int signum, sighandler_t handler); .
调用:signal(1/2/3/.....,handler)
功能描述:将signum信号,登记为当前进程所能捕获的信号。当进程捕获到 signum 信号之后,就会中断当前的运行,转而运行 handler函数
参数 signum:想要登记的信号的编号,使用 kill -l 查看
参数 handler:void(int)类型的函数指针,信号处理函数handler除了传入一个函数指针之外,还有2个选项SIG_IGN:该信号捕获到之后,忽略处理SIG_DFL:该信号被捕获到之后,执行默认的操作原型 void handler(int signum)
调用:signal(1/2/3/.....,handler)
功能描述:一旦进程捕获到一个被signal登记的信号之后,就会调用handler函数
参数 signum:当前被捕获到的几个常用信号SIGINT:当键盘键入 ctrl + c 时候发出SIGTSTP:当键盘键入 ctrl + z 时候发出SIGCHLD:当子进程死亡的时候,自动的向其父进程发出的信号只能默认处理的信号:SIGKILL 和 SIGSTOP 无法自定义处理 或者 忽略处理
不能被忽略的信号:SIGSEGV段错误信号,但是段错误信号可以自定义处理
练习
父子进程同时捕获登记SIGINT信号
父进程:输出我是父进程
子进程:输出我是子进程
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;pid_t pid;void handler(int signum)
{printf("%d\n",getpid());if(signum == SIGINT){if(pid>0){printf("我是父进程\n");exit(0);}else if(0==pid){printf("我是子进程\n");exit(0);}}
}int main(int argc, const char *argv[])
{pid_t pid=fork();if(pid>0){signal(SIGINT,handler);printf("%d\n",getpid());}else{signal(SIGINT,handler);printf("%d\n",getpid());}while(1);return 0;
}
当一个子进程死亡的时候,会自动的向其父进程发出SIGCHLD信号 要求实现:当父进程接收
到子进程死亡信息的时候,回收子进程的资源,防止僵尸进程的出现
当一个子进程死亡的时候,会自动的向其父进程发出SIGCHLD信号 要求实现:当父进程接收
到子进程死亡信息的时候,回收子进程的资源,防止僵尸进程的出现
追加要求:父进程使用
循环创建500个子进程,每一个子进程创建完毕后,立刻死亡
要求测试,是否产生僵尸进程,
并做到没有僵尸进程
标准的不会产生僵尸进程的模型
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;int i=0;void handler(int signum)
{while(1){ pid_t w=waitpid(-1,0,WNOHANG);if(-1==w)return;}printf("子进程的资源已被回收\n");
}int main(int argc, const char *argv[])
{for(int i=0;i<500;i++){pid_t pid=fork();if(pid>0){printf("ppid=%d\n",getpid());signal(SIGCHLD,handler);//wait(0);}else{int p=getpid();printf("pid=%d\n",p);kill(getpid(),SIGKILL);break;}}while(1);return 0;
}
4:有2个.c文件,每个.c文件都拥有一对父子进程,总共4个进程 A a B b 现在要求实现一个多
米诺骨牌的效果:
按ctrl+c结束a进程的运行,a进程结束运行之前,通过kill函数向b进程发送SIGINT信号,b进
程死亡后,B进程回收b进程的资源后,B进程再使用kill函数向A进程发送SIGTSTP信号后,大B进程结束运行。A进程接受到B进程的SIGTSTP信号后,会后a进程的资源后也结束运行
注意:kill函数要求获得另一个进程的pid,使用文件IO
这个题需要预习一个函数叫做 kill 函数
A.c文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;void handle(int signum)
{if(signum==SIGINT){FILE* p=fopen("./b的pid","r");pid_t b_pid;fread(&b_pid,4,1,p);kill(b_pid,SIGINT);fclose(p);printf("a死亡\n");exit(0);}if(signum==SIGTSTP){wait(0);printf("A结束\n");exit(0);}
}int main(int argc, const char *argv[])
{pid_t pid=fork();if(pid>0){ signal(SIGINT,SIG_IGN);FILE* p1=fopen("./A的pid","w");pid_t A_pid=getpid();fwrite(&A_pid,4,1,p1);fclose(p1);signal(SIGTSTP,handle);}else{signal(SIGINT,handle);}while(1);return 0;
}
B.c文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;void handle(int signum)
{if(signum==SIGINT){sleep(1);printf("b死亡\n");exit(0);}if(signum==SIGCHLD){sleep(1);while(waitpid(-1,0,WNOHANG)!=-1); FILE* p1=fopen("./A的pid","r");pid_t A_pid;fread(&A_pid,4,1,p1);kill(A_pid,SIGTSTP);fclose(p1);printf("B死亡\n");exit(0);}
}int main(int argc, const char *argv[])
{pid_t pid=fork();if(pid>0){signal(SIGCHLD,handle);}else{FILE* p=fopen("./b的pid","w");pid_t b_pid=getpid();fwrite(&b_pid,4,1,p);fclose(p);signal(SIGINT,handle);}while(1);return 0;
}