1.处理普通信号
程序代码:
- 1 #include
- 2 //定义信号处理函数
- 3 void handler(int signo)
- 4 {
- 5 if(signo==SIGINT)
- 6 {
- 7 printf("enter ctrl+c\n");
- 8 }
- 9 }
- 10 //处理普通信号
- 11 int main(int argc, const char *argv[])
- 12 {
- 13 /* //忽略SIGINT信号,处理方式SIG_IGN 忽略
- 14 if(signal(SIGINT,SIG_IGN)==SIG_ERR)
- 15 {
- 16 perror("signal error");
- 17 return -1;
- 18 }
- 19 //默认SIGINT,SIG_DFL 默认处理当前信号
- 20 if(signal(SIGINT,SIG_DFL)==SIG_ERR)
- 21 {
- 22 perror("signal error");
- 23 return -1;
- 24 }*/
- 25 //捕获SIGINT信号,处理方式 自定义函数
- 26 if(signal(SIGINT,handler)==SIG_ERR)
- 27 {
- 28 perror("signal error");
- 29 return -1;
- 30 }
- 31 while(1)
- 32 {
- 33 printf("多活一会\n");
- 34 sleep(1);
- 35 }
- 36 return 0;
- 37 }
运行结果:
2.捕获或忽略SIGKILL信号(杀死进程)
程序代码:
- 1 #include
- 2 //定义信号处理函数
- 3 void handler(int signo)
- 4 {
- 5 if(signo==SIGINT)
- 6 {
- 7 printf("enter ctrl+c\n");
- 8 }
- 9 if(signo==SIGKILL)
- 10 {
- 11 printf("捕获SIGKILL信号\n");
- 12 }
- 13 }
- 14 int main(int argc, const char *argv[])
- 15 {
- 16 /* //尝试忽略SIGKILL信号
- 17 if(signal(SIGKILL,SIG_IGN)==SIG_ERR)
- 18 {
- 19 perror("signal error");
- 20 return -1;
- 21 }
- 22 //尝试捕获SIGKILL信号
- 23 if(signal(SIGKILL,handler)==SIG_ERR)
- 24 {
- 25 perror("signal error");
- 26 return -1;
- 27 }*/
- 28 //尝试默认操作SIGKILL信号
- 29 if(signal(SIGKILL,SIG_DFL)==SIG_ERR)
- 30 {
- 31 perror("signal error");
- 32 return -1;
- 33 }
- 34 while(1)
- 35 {
- 36 printf("再活会\n");
- 37 sleep(1);
- 38 }
- 39 return 0;
- 40 }
运行结果:
3.使用SIGCHLD信号回收僵尸进程,当子进程退出后,子进程给父进程发送SIGCHLD信号,表示子进程的退出
程序代码:
- 1 #include
- 2 //信号处理函数
- 3 void handler(int signo)
- 4 {
- 5 if(signo==SIGCHLD)
- 6 {
- 7 while(waitpid(-1,NULL,WNOHANG)>0);
- 8 }
- 9 }
- 10 int main(int argc, const char *argv[])
- 11 {
- 12 //将子进程退出时发出的SIGCHLD信号捕获
- 13 if(signal(SIGCHLD,handler)==SIG_ERR)
- 14 {
- 15 perror("signal error");
- 16 return -1;
- 17 }
- 18 //创建僵尸进程
- 19 for(int i=0;i<6;i++)
- 20 {
- 21 if(fork()==0)
- 22 {
- 23 sleep(1);
- 24 exit(EXIT_SUCCESS);
- 25 }
- 26 }
- 27 while(1);
- 28 return 0;
- 29 }
运行结果:
4.SIGALRM信号,创建定时器,模拟出牌
程序代码:
- 1 #include
- 2 //定义信号处理函数
- 3 void handler(int signo)
- 4 {
- 5 if(signo==SIGALRM)
- 6 {
- 7 printf("系统随机出一张:\n");
- 8 alarm(5);
- 9 }
- 10 }
- 11 int main(int argc, const char *argv[])
- 12 {
- 13 //捕获SIGALRM信号
- 14 if(signal(SIGALRM,handler)==SIG_ERR)
- 15 {
- 16 perror("signal error");
- 17 return -1;
- 18 }
- 19 //启动定时器
- 20 alarm(5);
- 21 char ch=0;
- 22 while(1)
- 23 {
- 24 scanf("%c",&ch);
- 25 getchar();
- 26 printf("出了个:%c\n",ch);
- 27 alarm(5);
- 28 }
- 29 return 0;
- 30 }
运行结果:
5.验证发送信号函数
程序代码:
- 1 #include
- 2 void handler(int signo)
- 3 {
- 4 if(signo==SIGUSR1)
- 5 {
- 6 printf("活不了啦\n");
- 7 raise(SIGKILL);//向自己发送一个死亡信号
- 8 }
- 9 }
- 10 int main(int argc, const char *argv[])
- 11 {
- 12 //将SIGUSR1信号绑定
- 13 if(signal(SIGUSR1,handler)==SIG_ERR)
- 14 {
- 15 perror("signal error");
- 16 return -1;
- 17 }
- 18 //创建两个进程
- 19 pid_t pid=fork();
- 20 if(pid>0)
- 21 {
- 22 //父进程
- 23 while(1)
- 24 {
- 25 printf("多活一会\n");
- 26 sleep(1);
- 27 }
- 28 }else if(pid==0)
- 29 {
- 30 //子进程
- 31 sleep(5);
- 32 //向父进程发送信号,让父进程退出
- 33 printf("苍天已死,黄天登立\n");
- 34 kill(getppid(),SIGUSR1);
- 35 while(1)
- 36 {
- 37 printf("岁在甲子,天下大吉\n");
- 38 sleep(1);
- 39 }
- 40 }
- 41 return 0;
- 42 }
运行结果:
6.消息队列,msgsnd向消息队列存放消息
程序代码:
msgsnd.c:
- 1 #include
- 2 //定义一个消息类型
- 3 struct msgbuf
- 4 {
- 5 long mtype;//消息类型
- 6 char mtext[1024];//消息正文
- 7 };
- 8 //定义一个宏,表示消息正文大小
- 9 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
- 10 int main(int argc, const char *argv[])
- 11 {
- 12 //创建key值
- 13 key_t key=0;
- 14 if((key=ftok("/",'k'))==-1)
- 15 {
- 16 perror("ftok error");
- 17 return -1;
- 18 }
- 19 printf("ftok success key=%#x\n",key);
- 20 //根据key值创建一个消息队列
- 21 int msqid=-1;
- 22 if((msqid=msgget(key,IPC_CREAT|0664))==-1)
- 23 {
- 24 perror("msgget error");
- 25 return -1;
- 26 }
- 27 printf("msgget success msqid=%d\n",msqid);
- 28 //定义一个消息
- 29 struct msgbuf sbuf;
- 30 while(1)
- 31 {
- 32 //清空正文容器
- 33 bzero(sbuf.mtext,sizeof(sbuf.mtext));
- 34 printf("请输入当前消息类型:");
- 35 scanf("%ld",&sbuf.mtype);
- 36 getchar();//回收垃圾字符
- 37 printf("请输入消息正文:");
- 38 fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);
- 39 sbuf.mtext[strlen(sbuf.mtext)-1]=0;
- 40 //将消息存放队列中
- 41 msgsnd(msqid,&sbuf,MSGSIZE,0);
- 42 printf("发送成功\n");
- 43 if(strcmp(sbuf.mtext,"quit")==0)
- 44 break;
- 45 }
- 46 return 0;
- 47 }
msgrcv.c:
- 1 #include
- 2 //定义一个消息类型
- 3 struct msgbuf
- 4 {
- 5 long type;//消息类型
- 6 char mtext[1024];//消息正文
- 7 };
- 8 //定义一个宏,表示消息正文大小
- 9 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
- 10 int main(int argc, const char *argv[])
- 11 {
- 12 //创建一个key值
- 13 key_t key=0;
- 14 if((key=ftok("/",'k'))==-1)
- 15 {
- 16 perror("ftok error");
- 17 return -1;
- 18 }
- 19 printf("ftok success key=%#x\n",key);
- 20 //根据key值创建一个消息队列
- 21 int msqid=-1;
- 22 if((msqid=msgget(key,IPC_CREAT|0664))==-1)
- 23 {
- 24 perror("msgget error");
- 25 return -1;
- 26 }
- 27 printf("msgget success msqid=%d\n",msqid);
- 28 //定义一个消息
- 29 struct msgbuf rbuf;
- 30 while(1)
- 31 {
- 32 //清空容器
- 33 bzero(rbuf.mtext,sizeof(rbuf.mtext));
- 34 //从消息队列中读取一个消息
- 35 //msgrcv(msqid,&rbuf,MSGSIZE,0,0);
- 36 //第一个0:表示一直读取队列中第一个消息
- 37 //第二个0:表示阻塞读取
- 38 msgrcv(msqid,&rbuf,MSGSIZE,1,0);//只接受类型为1
- 39 printf("收到消息:%s\n",rbuf.mtext);
- 40 if(strcmp(rbuf.mtext,"quit")==0)
- 41 break;
- 42 }
- 43 //删除消息队列
- 44 if(msgctl(msqid,IPC_RMID,NULL)!=0)
- 45 {
- 46 perror("msgctl error");
- 47 return -1;
- 48 }
- 49 return 0;
- 50 }
运行结果:
7.使用消息队列完成两个进程间相互通信
程序代码:
msgsend1:
- 1 #include
- 2 //定义一个消息类型
- 3 struct msgbuf
- 4 {
- 5 long mtype;
- 6 char mtest[1024];
- 7 };
- 8
- 9 //定义宏,消息正文大小
- 10 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
- 11 int main(int argc, const char *argv[])
- 12 {
- 13 //1、创建key值
- 14 key_t key=0;
- 15 if((key=ftok("/",'k'))==-1){
- 16 perror("ftok error");
- 17 return -1;
- 18 }
- 19 //根据key值创建一个消息队列
- 20 int msqid=-1;
- 21 if((msqid=msgget(key,IPC_CREAT|0664))==-1){
- 22 perror("msgget error");
- 23 return -1;
- 24 }
- 25 //创建一个子进程
- 26 pid_t pid=fork();
- 27
- 28 if(pid>0){
- 29 //父进程向消息队列中写入类型为1的消息正文
- 30 //定义一个消息
- 31 struct msgbuf sbuf;
- 32 sbuf.mtype=1;
- 33 while(1)
- 34 {
- 35 //清空容器
- 36 bzero(sbuf.mtest,sizeof(sbuf.mtest));
- 37
- 38 printf("发送的消息:");
- 39 fgets(sbuf.mtest,sizeof(sbuf.mtest),stdin);
- 40 sbuf.mtest[strlen(sbuf.mtest)-1]='\0';
- 41
- 42 //将消息存放到消息队列
- 43 msgsnd(msqid,&sbuf,MSGSIZE,0);
- 44 printf("发送成功\n");
- 45
- 46 if(strcmp(sbuf.mtest,"quit")==0){
- 47 break;
- 48 }
- 49 }
- 50 wait(NULL);
- 51 }else if(pid==0){
- 52 //子进程从消息队列中取出类型为2的消息正文
- 53 //定义一个消息
- 54 struct msgbuf rbuf;
- 55
- 56 while(1)
- 57 {
- 58 //清空容器
- 59 bzero(rbuf.mtest,sizeof(rbuf.mtest));
- 60
- 61 //从消息队列中读取类型为2的消息正文
- 62 msgrcv(msqid,&rbuf,MSGSIZE,2,0);
- 63
- 64 printf("收到的消息为:%s\n",rbuf.mtest);
- 65 if(strcmp(rbuf.mtest,"quit")==0){
- 66 break;
- 67 }
- 68 }
- 69 exit(EXIT_SUCCESS);
- 70 }else{
- 71 perror("fork error");
- 72 return -1;
- 73 }
- 74
- 75 return 0;
- 76 }
msgrcv1:
- 1 #include
- 2 //定义一个消息类型
- 3 struct msgbuf
- 4 {
- 5 long mtype;
- 6 char mtest[1024];
- 7 };
- 8 //宏表示消息正文大小
- 9 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
- 10 int main(int argc, const char *argv[])
- 11 {
- 12 //1、创建key值
- 13 key_t key=0;
- 14 if((key=ftok("/",'k'))==-1){
- 15 perror("ftok error");
- 16 return -1;
- 17 }
- 18 //根据key值创建一个消息队列
- 19 int msqid=-1;
- 20 if((msqid=msgget(key,IPC_CREAT|0664))==-1){
- 21 perror("msgget error");
- 22 return -1;
- 23 }
- 24 //创建一个子进程
- 25 pid_t pid=fork();
- 26
- 27 if(pid>0){
- 28 //父进程从消息队列中取出类型为1的消息正文
- 29 //定义一个消息
- 30 struct msgbuf rbuf;
- 31 while(1)
- 32 {
- 33 //清空容器
- 34 bzero(rbuf.mtest,sizeof(rbuf.mtest));
- 35
- 36 //从消息队列中读取类型为1的消息正文
- 37 msgrcv(msqid,&rbuf,MSGSIZE,1,0);
- 38
- 39 printf("收到的消息为:%s\n",rbuf.mtest);
- 40 if(strcmp(rbuf.mtest,"quit")==0){
- 41 break;
- 42 }
- 43 }
- 44 wait(NULL);
- 45 }else if(pid==0){
- 46 //子进程向消息队列中写入类型为2的消息正文
- 47 //定义一个消息
- 48 struct msgbuf sbuf;
- 49 sbuf.mtype=2;
- 50 while(1)
- 51 {
- 52 //清空容器
- 53 bzero(sbuf.mtest,sizeof(sbuf.mtest));
- 54
- 55 printf("发送的消息:");
- 56 fgets(sbuf.mtest,sizeof(sbuf.mtest),stdin);
- 57 sbuf.mtest[strlen(sbuf.mtest)-1]='\0';
- 58
- 59 //将消息存放到消息队列
- 60 msgsnd(msqid,&sbuf,MSGSIZE,0);
- 61 printf("发送成功\n");
- 62
- 63 if(strcmp(sbuf.mtest,"quit")==0){
- 64 break;
- 65 }
- 66 }
- 67 exit(EXIT_SUCCESS);
- 68 }else{
- 69 perror("fork error");
- 70 return -1;
- 71 }
- 72
- 73 return 0;
- 74 }
运行结果: