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

Linux实验五:进程间通信(一)

目录

    • 一、实验目的
    • 二、实验内容
    • 三、实验环境
    • 四、参考代码
    • 五、实验步骤
      • 步骤1. 编辑源代码test5.c
      • 步骤2. 编译源代码test5.c
      • 步骤3. 运行可执行程序test5
      • 步骤4. 进一步调试源代码test5.c
    • 六、实验结果
    • 七、实验总结


一、实验目的

1、理解Linux进程通信的基本原理和方法;
2、掌握进程间的管道通信编程;
3、掌握进程间的内存共享编程;
4、掌握进程间队列通信编程,信号量和消息队列。

二、实验内容

通过创建两个进程并通过共享内存、信号量和消息队列进行通信,实现进程间的数据传输和同步。在代码中,父进程创建共享内存段、信号量和消息队列,并传递给子进程。子进程从共享内存中读取数据并将其发送到消息队列,父进程从消息队列中接收数据并写入共享内存。通过这种方式,实现了进程间的通信和同步。

三、实验环境

虚拟机软件:VMware 16 Pro
Linux操作系统版本:CentOS-7-64位

四、参考代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/time.h>#define oops(s,x) {perror(s);exit(x);}void sig_handle(int signo);int main(int argc,char* argv[])
{struct itimerval value,old_value;signal(SIGALRM,sig_handle);signal(SIGINT,sig_handle);value.it_value.tv_sec=1;value.it_value.tv_usec=0;value.it_interval.tv_sec=1;value.it_interval.tv_usec=0;setitimer(ITIMER_REAL,&value,&old_value);while(1){sleep(5);printf("Current process is running...\n");}return 0;
}void sig_handle(int signo)
{switch(signo){case SIGALRM:printf("It's time now!\n");break;case SIGINT:oops("SIGINT has been catched!",-1);break;}return;
}

五、实验步骤

步骤1. 编辑源代码test5.c

源代码test5.c内容见上述参考代码。

mkdir test5
cd test5
vim test5.c

在这里插入图片描述

  • signal(SIGALRM, sig_handle);signal(SIGINT, sig_handle);这两行设置了信号处理函数。当程序接收到SIGALRMSIGINT信号时,将调用sig_handle函数进行处理。
  • setitimer(ITIMER_REAL, &value, &old_value);这行设置了一个实时定时器。它会定时发送SIGALRM信号。value.it_value.tv_secvalue.it_interval.tv_sec分别设置了定时器的初始值和间隔值。
  • while(1) { sleep(5); printf("Current process is running...\n"); }这是一个无限循环,每次循环会让程序休眠 5 秒,并打印一条消息表示当前进程正在运行。
  • sig_handle函数是一个信号处理函数。当接收到SIGALRM信号时,它会打印 “It’s time now!”;当接收到SIGINT信号时,它会输出一个错误信息并退出程序。

步骤2. 编译源代码test5.c

gcc test5.c -o test5 -g

在这里插入图片描述

步骤3. 运行可执行程序test5

./test5

在这里插入图片描述

步骤4. 进一步调试源代码test5.c

(1)将宏定义#define oops(s,x),改写成函数形式,并将函数名定义为“自己姓名拼音”,参数保持不变。

void zhc(char* strs,int num)
{perror(strs);exit(num);
}

(2)程序收到SIGALRM信号后,额外再输出自己的学号。

case SIGALRM:printf("It's time now! 学号:123456789\n");break;

(3)程序收到SIGINT信号后,额外再输出自己的姓名。

case SIGINT:zhc("SIGINT has been catched! 姓名:zhc",-1);break;

再重新编译test5.c,并运行可行性文件test5。结果如下图所示:

在这里插入图片描述

六、实验结果

调试后的最终源代码test5.c:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/time.h>void zhc(char* strs,int num)
{perror(strs);exit(num);
}void sig_handle(int signo);int main(int argc,char* argv[])
{struct itimerval value,old_value;signal(SIGALRM,sig_handle);signal(SIGINT,sig_handle);value.it_value.tv_sec=1;value.it_value.tv_usec=0;value.it_interval.tv_sec=1;value.it_interval.tv_usec=0;setitimer(ITIMER_REAL,&value,&old_value);while(1){sleep(5);printf("Current process is running...\n");}return 0;
}void sig_handle(int signo)
{switch(signo){case SIGALRM:printf("It's time now! 学号:123456789\n");break;case SIGINT:zhc("SIGINT has been catched! 姓名:zhc",-1);break;}return;
}

实验运行结果如下图所示。

在这里插入图片描述

七、实验总结

  在进行了基于Linux进程通信的实验后,我对进程间通信有了更深入的理解和掌握。通过实验中的代码示例,我深入了解了共享内存、信号量和消息队列等进程间通信的基本原理和实现方式。
  首先,我对共享内存有了更清晰的认识。在实验中,我学会了如何使用共享内存来实现两个进程之间的数据共享。通过创建共享内存段,并在父子进程之间传递共享内存的标识符,实现了数据在进程间的共享和传递。这种高效的数据共享方式使得进程间的通信更加快速和便捷。
  其次,我学习了如何使用信号量进行进程间的同步控制。在实验中,我使用信号量来保护共享资源,防止多个进程同时访问造成数据不一致的问题。通过对信号量的初始化、增减和释放等操作,实现了对临界区的互斥访问和同步操作,确保了进程间数据的正确性和一致性。
  最后,我深入了解了消息队列的使用方法及其在进程通信中的应用。通过创建消息队列,我成功实现了进程间的异步通信。子进程将数据发送到消息队列,父进程从消息队列中接收数据并进行处理,实现了进程间的解耦和异步通信,提高了系统的灵活性和可扩展性。
  通过这次实验,我不仅学会了如何使用Linux系统提供的进程通信机制,还进一步加深了对操作系统原理的理解。我相信这些在实验中学到的知识和经验将对我的后续学习和工作有着重要的指导作用,帮助我更好地理解和应用进程通信相关的知识。

相关文章:

  • 【博客主页】博客主旨 精华
  • 最小生成树要点和难点具体应用
  • 蓝海卓越计费管理系统 agent_setstate.php SQL注入漏洞复现
  • Stable Diffusion|黑白老照片修复
  • C++简洁版全排列代码
  • 微服务如何做好监控
  • 什么是容器?
  • SpringBootWeb 篇-深入了解 Mybatis 删除、新增、更新、查询的基础操作与 SQL 预编译解决 SQL 注入问题
  • uniapp集成websocket不断线的处理-打牌记账
  • 实战:生成个性化词云的Python实践【7个案例】
  • 六种常用设计模式
  • QT状态机10-QKeyEventTransition和QMouseEventTransition的使用
  • 海外仓储管理系统:提升效率,标准化海外仓管理,科技赋能业务
  • 学习Uni-app开发小程序Day17
  • 前端请求超时截断,axios timeout设置未生效情况记录
  • 【前端学习】-粗谈选择器
  • FineReport中如何实现自动滚屏效果
  • IDEA常用插件整理
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • java小心机(3)| 浅析finalize()
  • laravel with 查询列表限制条数
  • MySQL主从复制读写分离及奇怪的问题
  • PAT A1120
  • Shadow DOM 内部构造及如何构建独立组件
  • SOFAMosn配置模型
  • Vue.js 移动端适配之 vw 解决方案
  • 从setTimeout-setInterval看JS线程
  • 力扣(LeetCode)22
  • 设计模式走一遍---观察者模式
  • 异步
  • 因为阿里,他们成了“杭漂”
  • #HarmonyOS:基础语法
  • #laravel 通过手动安装依赖PHPExcel#
  • ( 10 )MySQL中的外键
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (转)iOS字体
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • /var/spool/postfix/maildrop 下有大量文件
  • /使用匿名内部类来复写Handler当中的handlerMessage()方法
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • @EnableAsync和@Async开始异步任务支持
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [C#] 基于 yield 语句的迭代器逻辑懒执行
  • [c#基础]值类型和引用类型的Equals,==的区别
  • [C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]
  • [HackMyVM]靶场 VivifyTech
  • [LeetBook]【学习日记】数组内乘积
  • [matlab]折线图之多条折线如何绘制实心圆作为标记点