当前位置: 首页 > article >正文

进程间通信练习题

进行一些进程通信的练习题分享

第一题

创建不相关的两个进程(P1,P2),要求,P1 将自身的PID 写入命名管道,P2 从命名管道中获取P1的PID,P2 向 P1 发送携带数据的信号 SIGUSR1,P1 接收到信号后,获取传递的数据,在数据指定的秒数过后退出。

P1端

#include "head.h"

#define PATH "/home/st/fifofile"//此路径可以改变

void handler(int sig, siginfo_t *info, void *a)
{
    if (sig == SIGUSR1)
    {
        printf("recv a sig = %d, 已获取pid = %d的信号\n", sig, info->si_value.sival_int);
        sleep(3);
        kill(getpid(), 9);
    }
}

int main(int argc, char const *argv[])
{
    if (mkfifo(PATH, 0777) == -1)
    {
        // 根据错误进行判断若管道文件已经存在不报错
        if (errno != EEXIST)
        {
            perror("mkfifo()");
            exit(1);
        }
    }

    char buf[10];
    // 获取该进程pid并转换成字符串
    snprintf(buf, sizeof(buf), "%d", getpid());
    printf("%d---%s", getpid(), buf);
    int fd = open(PATH, O_RDWR);
    if (!fd)
    {
        perror("open()");
        return -1;
    }

    if (write(fd, buf, strlen(buf)) == -1)
    {
        perror("write()");
        return -1;
    }

    close(fd);

    struct sigaction avt;
    // 清空信号集
    sigemptyset(&avt.sa_mask);
    avt.sa_sigaction = handler;
    avt.sa_flags = SA_SIGINFO;

    int r = sigaction(SIGUSR1, &avt, NULL);
    if (r == -1)
    {
        perror("sigaction()");
        return -1;
    }

    puts("等待信号!");
    pause();

    return 0;
}

P2端

#include "head.h"

#define PATH "/home/st/fifofile"//此路径可以改变

int main(int argc, char const *argv[])
{
    if (mkfifo(PATH, 0777) == -1)
    {
        // 根据错误进行判断若管道文件已经存在不报错
        if (errno != EEXIST)
        {
            perror("mkfifo()");
            exit(1);
        }
    }

    char buf[10];
    int fd = open(PATH, O_RDWR);
    if (!fd)
    {
        perror("open()");
        return -1;
    }

    if (read(fd, buf, sizeof(buf)) == -1)
    {
        perror("write()");
        return -1;
    }

    union sigval val;
    val.sival_int = getpid();

    sigqueue(atoi(buf), SIGUSR1, val);
    close(fd);
    return 0;
}

第二题

两个没有亲缘关系的进程之间通过消息队列实现简单的聊天,要求创建消息队列的进程若先退出,给另一个进程通知,另一个进程得到通知后回收消息队列,并退出

发送端:

#include "head.h"

#define PATH "home/st/msgfile"

void fun(int sig)
{
    printf("%d\n", sig);
    kill(getpid(), 9);
}

typedef struct
{
    long type;      // 接收端通过标记访问
    int pid;        // 传递pid
    char data[100]; // 数据
} msg_t;

int main(int argc, char const *argv[])
{
    // 通过文件路径和一个整数获取一个key
    key_t key = ftok(PATH, 222);

    // 创建消息队列
    int msgid = msgget(key, IPC_CREAT | 0777);
    if (msgid == -1)
    {
        perror("msgget()");
        return -1;
    }
    // 定义要发送的信息数组
    char data[100] = {0};
    // 创建数据块对应的结构体成员
    msg_t msg = {0};
    while (1)
    {
        int vpid = 0;       // 存放对方的pid便于后续退出
        msg.pid = getpid(); // 将发送端pid传递给接收端
        // 设置消息的类型
        msg.type = 1;
        // 清理上次发送消息的内容
        memset(data, 0, sizeof(data));
        // 清理消息中的数据
        memset(msg.data, 0, sizeof(msg.data));
        printf("请输入:");
        // 键盘输入要发送的字符串
        fgets(data, sizeof(data), stdin);
        // 将用户输入的内容拷贝到结构体的成员上
        strcpy(msg.data, data);
        // 调用发送函数发送数据块
        int r = msgsnd(msgid, &msg, sizeof(msg), 0);

        // 发送端接收接收端发送过来的数据
        ssize_t r1 = msgrcv(msgid, &msg, sizeof(msg), 2, 0);
        printf("接收端的消息:%s", msg.data);
        vpid = msg.pid;
        if (r1 == 0 || strcmp(msg.data, "bye\n") == 0)
        {
            // 调用定时器函数
            alarm(1);
            // 给定时器绑定处理函数
            signal(SIGALRM, fun);
        }
    }

    // 销毁消息队列
    msgctl(msgid, IPC_RMID, NULL);

    return 0;
}

接收端:

#include "head.h"

#define PATH "home/st/msgfile"

typedef struct
{
    long type;      // 接收端通过标记访问
    int pid;        // 传递pid
    char data[100]; // 数据
} msg_t;

int main(int argc, char const *argv[])
{
    // 通过文件路径和一个整数获取一个key
    key_t key = ftok(PATH, 222);

    // 创建消息队列
    int msgid = msgget(key, IPC_CREAT | 0777);
    if (msgid == -1)
    {
        perror("msgget()");
        return -1;
    }
    // 创建接收数据块的结构体遍历
    msg_t msg = {0};
    msg.pid = getpid();
    // 定义要发送的信息数组
    char data[100] = {0};
    while (1)
    {
        // 调用接收函数接收发送过来的数据
        ssize_t r1 = msgrcv(msgid, &msg, sizeof(msg), 1, 0);
        printf("发送端的数据:%s", msg.data);
        if (r1 == 0 || strcmp(msg.data, "bye\n") == 0)
        {
            break;
        }

        // 设置消息的类型
        msg.type = 2;
        // 清理上次发送消息的内容
        memset(data, 0, sizeof(data));
        // 清理消息中的数据
        memset(msg.data, 0, sizeof(msg.data));
        printf("请输入:");
        // 键盘输入要发送的字符串
        fgets(data, sizeof(data), stdin);
        // 将用户输入的内容拷贝到结构体的成员上
        strcpy(msg.data, data);
        // 调用发送函数发送数据块
        int r = msgsnd(msgid, &msg, sizeof(msg), 0);
        if (r == -1 || strcmp(data, "bye\n") == 0)
        {
            break;
        }
    }

    // 销毁消息队列
    msgctl(msgid, IPC_RMID, NULL);

    return 0;
}

http://www.kler.cn/a/509482.html

相关文章:

  • LLM - 大模型 ScallingLaws 的迁移学习与混合训练(PLM) 教程(3)
  • 物联网网关Web服务器--Boa服务器移植与测试
  • 【经济学通识——国债】
  • 51单片机——DS18B20温度传感器
  • git操作(Windows中GitHub)
  • PHP中的魔术函数
  • 记录一下在Win上搭建RustDesk
  • 【JsonViewer】Json格式化
  • Vulnhub DC-8靶机攻击实战(一)
  • Applitools与AI图像识别技术在测试中的应用
  • RCD-IoT:在高数据包传输率下,利用资源受限设备实现工业监测与控制
  • boss直聘 __zp_stoken__ 逆向分析
  • 网络编程-TCP套接字
  • 基于Spring Cloud的电商系统设计与实现——用户与商品模块的研究(下)
  • 数据库存储上下标符号,sqlserver 2008r2,dm8
  • 如何通过 Apache Airflow 将数据导入 Elasticsearch
  • 4.若依 BaseController
  • Gin 源码概览 - 路由
  • Android笔记: 实现点击事件透传到底部
  • Django缓存系统详解:使用Redis提升应用性能
  • 快手极速版如何查找ip归属地?怎么关掉
  • PP-OCR系统
  • CloudberryDB(四)并行执行
  • 【Linux系统编程】—— 深入理解Linux中的环境变量与程序地址空间
  • 电路笔记(通信模块): 基于ESP32-S3实现的XVC(Xilinx Virtual Cable) JTAG下载器硬件
  • 【LOJ 6198】谢特 题解(可持久化Trie+后缀数组SA+启发式分裂+RMQ)