1> 将标准io文件IO的内容复习一遍
2> 进程线程的相关函数复习一遍
3> 将信号和消息队列的课堂代码敲一遍
1、处理普通信号
#include <myhead.h>
//定义信号处理函数
void handler(int signo)
{
if(signo==SIGINT)
{
puts("按下ctrl+c");
}
}
int main(int argc, const char *argv[])
{
//捕获SIGINT信号,处理方式 自定义函数
if(signal(SIGINT,handler)==SIG_ERR)
{
perror("signal error");
return -1;
}
while(1)
{
puts("赚小钱钱");
sleep(1);
}
return 0;
}
2、 尝试捕获或忽略SIGKILL信号
#include <myhead.h>
int main(int argc, const char *argv[])
{
//尝试忽略SIGKILL信号
if(signal(SIGKILL,SIG_IGN)==SIG_ERR)
{
perror("signal ERROR");
return -1;
}
while(1)
{
puts("明天放假");
sleep(1);
}
return 0;
}
3、使用SIGGHLD信号回收僵尸进程,当子进程退出后,子进程会向父进程发送一个SIGCHLD信号,表示子进程的退出
#include <myhead.h>
//自定义信号处理方式
void handler(int signo)
{
if(signo==SIGCHLD)
{
while(waitpid(-1,NULL,WNOHANG)>0);//循环非阻塞的回收子进程的资源
}
}
int main(int argc, const char *argv[])
{
//将SIGCHLD信号和自定义函数绑定
if(signal(SIGCHLD,handler)==SIG_ERR)
{
perror("SIGNAL ERROR");
return -1;
}
for(int i=0;i<10;i++)//创建10个僵尸进程
{
if(fork()==0)
{
sleep(1);
exit(EXIT_SUCCESS);//退出当前进程
}
}
while(1);
return 0;
}
4、模拟斗地主出牌的案例
#include <myhead.h>
//系统自动出牌函数
void handler(int signo)
{
if(signo==SIGALRM)
{
printf("系统自动为你出了一张牌\n");
alarm(5);
}
}
int main(int argc, const char *argv[])
{
//捕获SIGALRM信号并绑定执行方式
if(signal(SIGALRM,handler)==SIG_ERR)
{
perror("signal error");
return -1;
}
alarm(5);//启动定时器
char ch=0;
while(1)
{
scanf("%c",&ch);//从终端获取你出的牌
getchar();
printf("你出的牌是:%c\n",ch);
alarm(5);//5秒不从终端输入牌,自动转到自定义函数中
}
return 0;
}
5、验证发送信号函数
#include <myhead.h>
//父进程收到信号处理任务
void handler(int signo)
{
if(signo==SIGUSR1)
{
puts("日薄西山,英雄迟暮\n父进程准备自杀");
raise(SIGKILL);//父进程杀死自己
}
}
int main(int argc, const char *argv[])
{
//将SIGUSR1信号绑定
if(signal(SIGUSR1,handler)==SIG_ERR)
{
perror("SIGNAL ERROR");
return -1;
}
pid_t pid=fork();
if(pid>0)
{
while(1)
{
puts("父进程还或者");
sleep(1);
}
}
else if(pid==0)
{
sleep(5);
puts("子进程要独立了");
kill(getppid(),SIGUSR1);//向父进程发生信号
while(1)
{
puts("富贵险中求");
sleep(1);
}
}
return 0;
}
6、 消息队列两个进程间的单向通信
user1代码:
#include <myhead.h>
//定义一个消息类型
struct msgbuf
{
long mtype;//消息类型
char mtext[1024];//消息正文
};
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
int main(int argc, const char *argv[])
{
//创建key值
key_t key =0;
if((key=ftok("./",'k'))==-1)
{
perror("ftok error");
return -1;
}
printf("ftok success key=%#x\n",key);
//根据key值创建一个消息队列
int msqid=-1;
if((msqid=msgget(key,IPC_CREAT|0664))==-1)
{
perror("msgget error");
return -1;
}
printf("msgget success msqid =%d\n",msqid);
//定义一个消息类型
struct msgbuf sbuf;
while(1)
{
bzero(sbuf.mtext,sizeof(sbuf.mtext));//清空容器
printf("请输入当前消息的类型:");
scanf("%ld",&sbuf.mtype);
getchar();//吸收回车
printf("请输入正文内容:");
fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);//从终端获取消息正文
sbuf.mtext[strlen(sbuf.mtext)-1]=0;
//向消息队列中存放消息
msgsnd(msqid,&sbuf,MSGSIZE,0);
printf("发送成功\n");
if(strcmp(sbuf.mtext,"end")==0)
{
break;
}
}
return 0;
}
usr2代码:
#include <myhead.h>
//定义一个消息类型
struct msgbuf
{
long mtype;//消息类型
char mtext[1024];//消息正文
};
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
int main(int argc, const char *argv[])
{
//创建key值
key_t key =0;
if((key=ftok("./",'k'))==-1)
{
perror("ftok error");
return -1;
}
printf("ftok success key=%#x\n",key);
//根据key值创建一个消息队列
int msqid=-1;
if((msqid=msgget(key,IPC_CREAT|0664))==-1)
{
perror("msgget error");
return -1;
}
printf("msgget success msqid =%d\n",msqid);
//定义一个消息类型
struct msgbuf rbuf;
while(1)
{
bzero(rbuf.mtext,sizeof(rbuf.mtext));//清空容器
//从消息队列中获取任意一个消息
msgrcv(msqid,&rbuf,MSGSIZE,0,0);
printf("收到的消息是类型%ld中的消息:%s\n",rbuf.mtype,rbuf.mtext);
if(strcmp(rbuf.mtext,"end")==0)
{
break;
}
}
//删除消息队列
if(msgctl(msqid,IPC_RMID,NULL)!=0)
{
perror("msgctl error");
return -1;
}
return 0;
}
4> 使用消息队列完成两个进程间相互通信
usr1代码:
#include <myhead.h>
//定义一个消息类型
struct msgbuf
{
long mtype;//消息类型
char mtext[1024];//消息正文
};
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
int main(int argc, const char *argv[])
{
//创建key值
key_t key =0;
if((key=ftok("./",'k'))==-1)
{
perror("ftok error");
return -1;
}
printf("ftok success key=%#x\n",key);
//根据key值创建一个消息队列
int msqid=-1;
if((msqid=msgget(key,IPC_CREAT|0664))==-1)
{
perror("msgget error");
return -1;
}
printf("msgget success msqid =%d\n",msqid);
pid_t pid=fork();//创建子进程
if(pid>0)//父进程
{
struct msgbuf sbuf;
sbuf.mtype=1;
while(1)
{
bzero(sbuf.mtext,sizeof(sbuf.mtext));//清空容器
fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);//从终端获取消息正文
sbuf.mtext[strlen(sbuf.mtext)-1]=0;
//向消息队列中存放消息
msgsnd(msqid,&sbuf,MSGSIZE,0);
printf("usr1发送成功\n");
if(strcmp(sbuf.mtext,"end")==0)
{
kill(pid,SIGKILL);
break;
}
}
wait(NULL);
}
else if(pid==0)//子进程
{
struct msgbuf rbuf;
while(1)
{
bzero(rbuf.mtext,sizeof(rbuf.mtext));//清空容器
//从消息队列中获取类型为2一个消息
msgrcv(msqid,&rbuf,MSGSIZE,2,0);
printf("收到的消息是类型%ld中的消息:%s\n",rbuf.mtype,rbuf.mtext);
if(strcmp(rbuf.mtext,"end")==0)
{
kill(getppid(),SIGKILL);
break;
}
}
exit(EXIT_SUCCESS);
}
else{
perror("fork error");
return -1;
}
return 0;
}
usr2代码:
#include <myhead.h>
///定义信号处理函数
void handler(int signo)
{
if(signo == SIGCHLD)
{ wait(NULL);
exit(EXIT_SUCCESS);
}
}
//定义一个消息类型
struct msgbuf
{
long mtype;//消息类型
char mtext[1024];//消息正文
};
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)
int main(int argc, const char *argv[])
{
//创建key值
key_t key =0;
if((key=ftok("./",'k'))==-1)
{
perror("ftok error");
return -1;
}
printf("ftok success key=%#x\n",key);
//根据key值创建一个消息队列
int msqid=-1;
if((msqid=msgget(key,IPC_CREAT|0664))==-1)
{
perror("msgget error");
return -1;
}
printf("msgget success msqid =%d\n",msqid);
struct msgbuf rbuf;
struct msgbuf sbuf;
sbuf.mtype=2;
pid_t pid=fork();//创建进程
if(pid>0)//父进程
{
signal(SIGCHLD,handler);
while(1)
{
bzero(sbuf.mtext,sizeof(sbuf.mtext));//清空容器
fgets(sbuf.mtext,sizeof(sbuf.mtext),stdin);//从终端获取消息正文
sbuf.mtext[strlen(sbuf.mtext)-1]=0;
//向消息队列中存放消息:
msgsnd(msqid,&sbuf,MSGSIZE,0);
printf("usr2发送成功\n");
if(strcmp(sbuf.mtext,"end")==0)
{
kill(pid,SIGKILL);
break;
}
}
}
else if(pid==0)//子进程
{
while(1)
{
bzero(rbuf.mtext,sizeof(rbuf.mtext));//清空容器
//从消息队列中获取类型为1一个消息
msgrcv(msqid,&rbuf,MSGSIZE,1,0);
printf("usr2收到的消息是类型%ld中的消息:%s\n",rbuf.mtype,rbuf.mtext);
if(strcmp(rbuf.mtext,"end")==0)
{
break;
}
}
//删除消息队列
if(msgctl(msqid,IPC_RMID,NULL)!=0)
{
perror("msgctl error");
return -1;
}
exit(EXIT_SUCCESS);
}
else
{
perror("fork error");
return -1;
}
return 0;
}
思维导图: