因为自己写的小程序,结构不太严谨
程序实现消息队列的请求和响应步骤,另从子程序发送信号至父程序
实验环境:Linux + vim
进行实验时,应先将b程序生成执行文件b,a程序生成执行文件
命令:gcc -ob b.c
gcc -oa a.c
程序a:
#include
#include
#include
#include
#include
#include
//该结构体是信息包的内容
struct emp
{
int id;
char name[20];
double sal;
};
//消息队列所传递接收的信息包
struct msg
{
long mtype; //指定消息包的类型
struct emp em; //消息包的内容
};
//信号处理函数:主要是通过捕获信号来销毁创建的队列
void fa(int signo)
{
//接下来两句应该定义成全局变量的,这样就不用在这里写这两句,只是想着自己练习懒得去改
key_t key = ftok(".",100);
int msgid = msgget(key,IPC_CREAT|0666);
msgctl(msgid,IPC_RMID,0);
printf("队列销毁!\n");
exit(0);
}
int main()
{
signal(40,fa); //信号捕获函数
key_t key = ftok(".",100); //创建消息队列的key,key可以用来创建和获取消息队列,是从用户层与内核交互的钥匙
int msgid = msgget(key,IPC_CREAT|0666); //创建消息队列
if(msgid == -1)
{
perror("msgget");
exit(-1);
}
struct emp em1 = {1,"zhangfei",12000.0}; //信息录入
struct emp em2 = {2,"guanyu",12000.0};
struct msg m1 = {1,em1};
struct msg m2 = {2,em2};
msgsnd(msgid,&m1,sizeof(m1.em),0); //发送信息,将信息传入消息队列中
msgsnd(msgid,&m2,sizeof(m2.em),0);
printf("数据发送完成!\n");
pid_t pid = vfork(); //创建子进程,子进程抢占父进程资源,这时父进程进入阻塞状态
if(!pid)
{
printf("执行读操作\n");
execl("./b","b",NULL); //使用exec家族替换子进程,子进程拥有独立的资源,父进程结束阻塞
perror("execl"); //将名为b的程序替换子进程,并开始运行b
exit(-1);
}
while(1);
}
程序b:
#include
#include
#include
#include
#include
struct emp
{
int id;
char name[20];
double sal;
};
struct msg
{
long mtype;
struct emp em;
};
int main()
{
int ppid = getppid(); //获取父进程的PID,PID是进程的唯一标识。通过它可以向进程进行发送信号等操作
key_t key = ftok(".",100);
int msgid = msgget(key,0); //获取消息队列的id,从而能与父进程对同一块内存进行数据交互
if(msgid == -1)
{
perror("msgget");
exit(-1);
}
struct msg m1;
while(1)
{
int res = msgrcv(msgid,&m1,sizeof(m1.em),-2,IPC_NOWAIT); //获取消息队列中类型小于等于2的信息包,获取不阻塞
if(res == -1)
{
printf("数据读取完成!\n");
break;
}
printf("%ld,%d%s,%lf\n",m1.mtype,m1.em.id,m1.em.name,m1.em.sal);
}
kill(ppid,40); //向父进程发送信号,使父进程销毁队列
return 0;
}