学习_vfork、消息队列和信号处理小小程序

因为自己写的小程序,结构不太严谨

程序实现消息队列的请求和响应步骤,另从子程序发送信号至父程序

实验环境:Linux + vim

进行实验时,应先将b程序生成执行文件b,a程序生成执行文件

命令:gcc -ob b.c

           gcc -oa a.c

 

程序a:

#include     // 吐槽一下UC的头文件....TM真多
#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;
}

你可能感兴趣的:(学习_vfork、消息队列和信号处理小小程序)