【操作系统】进程的控制和通信

文章目录

  • 一. 实验目的
  • 二. 实验内容
  • 三. 实验步骤
  • 四. 实验结果

一. 实验目的

(1)加深对进程概念的理解,进一步认识并发执行的实质。
(2)掌握Linux 操作系统中进程的创建和终止操作。
(3)理解进程间通信的概念和方法。
(4)掌握常用的Linux 进程间通信的方法。

二. 实验内容

(1)编写一个C程序,并使用系统调用fork()创建一个子进程。要求如下:

① 在子进程中分别输出当前进程为子进程的提示、当前进程的PID 和父进程的PID、根据用户输入确定当前进程的返回值、退出提示等信息。
② 在父进程中分别输出当前进程为父进程的提示、当前进程的PID 和子进程的PID、等待子进程退出后获得的返回值、退出提示等信息。

(2)编写C程序,使用Linux中的IPC机制,完成 “石头、剪子、布”的游戏。

三. 实验步骤

(1)编写一个C程序,并使用系统调用fork()创建一个子进程。

程序设计

#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>int main()
{pid_t childpid;int retval;int status;childpid=fork();if(childpid==0) // 子进程{printf("CHILD: I am the child process\n");printf("CHILD: My PID: %d\n", getpid());printf("CHILD: My parent's PID: %d\n", getppid());printf("CHILD: The value of fork return is: %d\n", childpid);printf("CHILD: Sleep for 1 second ..\n");sleep(1);printf("CHILD: Enter an exit value (0~255):");scanf("%d",&retval);printf("CHILD: Goodbye!\n");exit(retval);}else if(childpid>0) // 父进程{printf("PARENT: I am the parent process\n");printf("PARENT: My PID: %d\n", getpid());printf("PARENT: my child's PID:%d\n", childpid);printf("PARENT: I will now wait for my child to exit.\n");wait(&status);printf("PARENT: child's exit code is:%d\n",WEXITSTATUS(status));printf("PARENT: Goodbye\n");exit(0);}else // 错误处理{perror("fork error\n");exit(0);}return 0;
}

程序分析

该程序展示了一个父子进程之间的通信方式。它使用了fork()函数创建了子进程并在子进程中输出一些信息,最后子进程通过exit()函数返回一个退出值。在父进程中,它等待子进程的退出并通过wait()函数获取子进程退出的状态码。
首先是fork()函数的调用,它会返回一个值,该值有不同的含义:

  • 返回值为0时,表示当前进程是子进程。
  • 返回值大于0时,表示当前进程是父进程,返回值为子进程的PID。
  • 返回值小于0时,表示创建进程失败。

在子进程中,它会输出一些信息,包括它自己的PID和父进程的PID,以及fork()函数的返回值。然后,它会等待1秒钟,让父进程有时间执行并输出信息。接下来,它通过scanf()函数读取一个退出值,并通过exit()函数返回。
在父进程中,它会输出自己的PID和子进程的PID,并等待子进程退出。它通过wait()函数获取子进程退出时的状态码。wait()函数会阻塞当前进程,直到任意一个子进程退出。如果不关心哪个子进程退出,可以使用wait(NULL)。在该程序中,使用了&status来获取子进程退出的状态码,并通过WEXITSTATUS(status)函数获取子进程通过exit()函数返回的退出值。
最后,父进程输出子进程的退出值,并通过exit()函数退出进程。
总的来说,该程序展示了fork()函数创建子进程、子进程的输出、父进程等待子进程退出和获取子进程退出的状态码等基本操作。

(2)编写C程序,使用Linux中的IPC机制,完成 “石头、剪子、布”的游戏。

程序设计

#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>struct Game
{int Round;long Type;	
};void result_send(int num)
{struct Game game;game.Type=1;game.Round= rand()%3;int ret=-1;ret=msgsnd(num,&game,sizeof(int),0);printf("%d msgsnd %d return %d\n",num,game.Round,ret);}int result_announce(int a,int b)
{if ((a+1==b) ||(a-2==b))return -1;else if(a==b)return 0;elsereturn 1;
}void writefile(int *result_list,int len)
{int count_A=0;int count_B=0;int pingju=0;FILE *fin;fin=fopen("result.txt","w");if(fin==NULL) printf("This file wasn't opened");int i;for(i=0;i<len;i++){switch(result_list[i]){case -1:count_A++;fprintf(fin,"No.%d: A win\n",i+1);printf("No.%d: A win\n",i+1);break;case 0:pingju++;fprintf(fin,"No.%d: end in a draw\n",i+1);printf("No.%d: end in a draw\n",i+1);break;case 1:count_B++;fprintf(fin,"No.%d: B win\n",i+1);printf("No.%d: B win\n",i+1);break;}}printf("\nThe final result is A win:%ds \nB win:%ds \nend in a draw %ds\n",count_A,count_B,pingju);fprintf(fin,"\nThe final result is A win: %ds \nB win: %ds \nend in a draw %ds\n",count_A,count_B,pingju);fclose(fin);
}int main()
{int times;int key1=1234;int key2=5678;int *result_list;pid_t pid1,pid2;int msgid1,msgid2;msgid1=msgget(key1,IPC_CREAT | 0666);msgid2=msgget(key2,IPC_CREAT | 0666);if(msgid1==-1){fprintf(stderr,"failed with error");exit(EXIT_FAILURE);}if(msgid2==-1){fprintf(stderr,"failed with error");exit(EXIT_FAILURE);}printf("Game start, please input rounds:");scanf("%d",&times);printf("times=%d\n",times);result_list=(int*)malloc(times*sizeof(int));int i;for(i=0;i<times;i++){printf("********i=%d********\n",i);pid1=fork();if(pid1==0){//printf("in pid1:\n");int pid=getpid();printf("pid of pid1 is %d\n",pid);srand((unsigned)time(0)*3000);result_send(msgid1);exit(11);}pid2=fork();if(pid2==0){//printf("in pid2:\n");int pid=getpid();printf("pid of pid2 is %d\n",pid);srand((unsigned)time(NULL)*i);result_send(msgid2);exit(22);}if(pid1<0 || pid2<0){fprintf(stderr,"Fork Failed");printf("Fork failed!!");exit(-1);}else{//printf("in else before wait:\n");int status1,status2;			wait(&status1);//printf("wait1 ok, status1=%d\n",WEXITSTATUS(status1));wait(&status2);//printf("wait2 ok, status2=%d\n",WEXITSTATUS(status2));struct Game game1,game2;msgrcv(msgid1,&game1,sizeof(game1)-sizeof(long),0,0);printf("%d rcv %d ok\n",msgid1,game1.Round);msgrcv(msgid2,&game2,sizeof(game2)-sizeof(long),0,0);printf("%d rcv %d ok\n",msgid2,game2.Round);int j=result_announce(game1.Round,game2.Round);result_list[i]=j;printf("result_announce is %d.\n",j);}}//end forwritefile(result_list,times);if(msgctl(msgid1,IPC_RMID,0)==-1)fprintf(stderr,"msgctl(IPC_RMID) failed\n");if(msgctl(msgid2,IPC_RMID,0)==-1)fprintf(stderr,"msgctl(IPC_RMID) failed\n");exit(EXIT_SUCCESS);
}

程序分析

该程序是一个石头剪刀布游戏的模拟,通过使用进程间通信机制实现了两个进程间的交互。程序创建了两个消息队列,分别用于进程1和进程2向其父进程发送消息,父进程接收消息并比较得出游戏结果,然后输出到文件中。以下是程序的详细分析:

首先定义了一个结构体Game,用于存储比赛的轮数和玩家出的手势,可以看作一个消息的格式。游戏结果用一个int型数组result_list来存储,其中0表示平局,-1表示A胜利,1表示B胜利。然后是result_send函数,它用于向指定的队列发送一条Game类型的消息。随机产生一个0~2的整数表示玩家出的手势,并设置Type为1表示这是来自进程1的消息。返回值表示发送操作是否成功。
result_announce函数用于比较两个玩家出的手势,返回值为0表示平局,-1表示A胜利,1表示B胜利。
writefile函数用于将游戏结果写入文件result.txt中,同时输出到控制台。其中count_A、count_B、pingju分别表示A胜利的次数、B胜利的次数和平局的次数。

在主函数中,首先创建了两个消息队列,然后询问玩家要进行多少轮游戏,并分配result_list数组的大小。进入for循环后,创建了两个子进程pid1和pid2,分别代表进程1和进程2。
在子进程中,通过调用srand()和result_send()函数来随机选择手势,然后向父进程所绑定的消息队列中发送一条消息。为了让每次产生的随机数不同,可以使用时间函数time()和进程id组合生成随机数的种子。
在父进程中,首先通过wait()函数等待子进程1和子进程2都结束,并获取它们退出时的状态值。然后使用msgrcv()函数从消息队列中接收子进程所发出的消息,也就是两个玩家出的手势。
接下来,调用result_announce()函数比较两个玩家出的手势,获取比赛结果,并将得到的结果保存到result_list数组中。
当所有的比赛都结束后,调用writefile()函数来输出结果到result.txt文件中,并输出到控制台。同时,通过msgctl()函数删除之前创建的两个消息队列。

总的来说,该程序运用了fork()函数创建子进程、消息队列实现进程间通信等基本操作。它模拟了石头剪刀布游戏的过程,同时也展示了使用进程间通信机制进行协作的思路。

四. 实验结果

(1)编写一个C程序,并使用系统调用fork()创建一个子进程。

1

(2)编写C程序,使用Linux中的IPC机制,完成 “石头、剪子、布”的游戏。

2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/122961.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络-应用层(2)

一、DHCP 当需要跨越多个网段提供DHCP 服务时必须使用DHCP 中继代理&#xff0c; 就是在DHCP 客户和服务器之间转发DHCP 消息的主机或路由器。 DHCP 服务端使用UDP 的67号端口来监听和接收客户请求消息&#xff0c; 保留UDP 的68号端口用于接收来自DHCP 服务器的消息回复。 在…

基于 Python 的豆瓣电影分析、可视化系统,附源码

文章目录 1 简介2 技术栈具体实现1.设计豆瓣电影自动化爬虫程序&#xff0c;自动获取电影数据2.对爬取到的数据进行清洗和预处理&#xff0c;包括多维度数据字段清洗和扩充3.将清洗好的数据存储到MySQL数据库中 4 具体效果图5 推荐阅读 1 简介 基于Python flask 的豆瓣电影分析…

win11 右键菜单默认 显示更多选项

win10升级至win11后&#xff0c;一个很大的变化就是右键菜单&#xff0c;其不再显示所有的菜单项&#xff0c;而是默认只显示主要的几项&#xff0c;点击“显示更多选项”后&#xff0c;才会显示所有菜单项。 这对于经常需要用到右键其他菜单项的人来说明&#xff0c;非常的不…

【C++】C++入门(下)--内联函数 auto关键字 nullptr

目录 一 内联函数 1 内联函数概念和定义 2 内联函数特性 二 auto关键字 1 auto概念 2 auto 的使用细则 (1) auto与指针和引用结合起来使用 (2) 在同一行定义多个变量 3 auto不能推导的场景 (1) auto不能作为函数的参数 (2) auto不能直接用来声明数组 4 基于范围的fo…

关于深度学习中Attention的一些简单理解

Attention 机制 Attention应用在了很多最流行的模型中&#xff0c;Transformer、BERT、GPT等等。 Attention就是计算一个加权平均&#xff1b;通过加权平均的权值来自计算每个隐藏层之间的相关度&#xff1b; 示例 Attention 机制 Attention应用在了很多最流行的模型中&am…

C# 海康威视平台API接入 和网页摄像头部署

文章目录 前言相关网址综合安防管理平台网址获取Appkey和Secret/密码和密钥测试个人魔改工具类 海康视频接入获取摄像头Id下载海康Web插件原生Html导入网页设置 JS封装封装代码使用设置成功&#xff01; 前言 最近有个需求是将海康的摄像头视频画面传到我们平台上&#xff0c;…

C# OpenCvSharp Yolov8 Face Landmarks 人脸特征检测

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace OpenCvSharp_Yolov8_Demo {public partial class frmMain…

FL Studio21.2演示版下载

FL Studio 21.2 带有 stem 分离和 FL Cloud&#xff0c;这是一项专为 FL Studio 打造的具有里程碑意义的新服务。其他新功能包括 FL Studio Fruity Edition 的 Audio Clips&#xff08;音频剪辑&#xff09;和一个新的模拟建模合成器 Kepler。 为庆祝 FL Studio 21.2 的发布&am…

Vue实现首页导航和左侧菜单,介绍mock.js并实现登录注册间的跳转,实现左侧栏折叠效果,优化Main.vue组件,使用mock.js生成随机响应数据

目录 1. mockjs 1.1 mockjs介绍 1.2 mockjs使用步骤 1.2.1 安装mockjs依赖 1.2.2 在项目中引入mockjs 1.2.3 创建目录和文件 1.2.4 为每个组件准备模拟数据 1.2.5 测试 1.2.6 前端调试 1.2.7 mockjs生成随机响应数据 1.2.8 根据不同响应&#xff0c;给出不同提示 2…

二进制搭建 Kubernetes+部署网络组件+部署CornDNS+负载均衡部署+部署Dashboard

二进制搭建 Kubernetes v1.20 k8s集群master01&#xff1a;20.0.0.50 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群master02&#xff1a;20.0.0.100k8s集群node01&#xff1a;20.0.0.110 kubelet kube-proxy docker etcd k8s集群node02&#xff1a;20.…

如何通过adb控制安卓手机wifi

一、准备工作 1、先用USB数据线 将手机和电脑连接在一起 1&#xff09; 数据线连接手机和电脑&#xff0c;选择“传输文件”的连接方式&#xff1b; 2&#xff09; 在手机上&#xff0c;打开“开发者选项”、“USB调试”&#xff1b; 2、在电脑上安装adb工具&#xff0c;参考…

MySQL(2):环境搭建

1.软件下载 软装去官网下载&#xff08;社区版&#xff09;&#xff1a;https://downloads.mysql.com/archives/installer/&#xff08;历史版本可选&#xff09; 选择下面的&#xff0c;一步到位 2.软件安装 双击 .msi 文件 选完 Custom 自定义后点 next 按 1&#xff0c…

软通动力:打造AI第二增长曲线,图谋新发展

【科技明说 &#xff5c; 重磅专题】 软通动力对于AI的想法还是比较久了&#xff0c;之前在与业内朋友聊到软通动力之时&#xff0c;曾提到软通动力的根基还是在于其多年来的软件服务能力&#xff0c;目前借助AI技术创新的机遇将软件服务能力进一步放大&#xff0c;扩展到更多行…

人工智能基础_机器学习006_有监督机器学习_正规方程的公式推导_最小二乘法_凸函数的判定---人工智能工作笔记0046

我们来看一下公式的推导这部分比较难一些, 首先要记住公式,这个公式,不用自己理解,知道怎么用就行, 比如这个(mA)T 这个转置的关系要知道 然后我们看这个符号就是求X的导数,X导数的转置除以X的导数,就得到单位矩阵, 可以看到下面也是,各种X的导数,然后计算,得到对应的矩阵结…

高阶数据结构学习 —— 图(2)

文章目录 1、BFS1、DFS 1、BFS 广度优先。确定从哪个点开始&#xff0c;然后用队列来完成遍历。拿出一个点就把和这个点相连的其它点放进去&#xff0c;但是这样前面放进过队列的也有可能被再次放入&#xff0c;所以需要做好标记。一个队列&#xff0c;一个标记容器。在邻接矩…

蓝桥杯每日一题2023.10.25

乘积尾零 - 蓝桥云课 (lanqiao.cn) 题目描述 题目分析 由于需要相乘的数很多&#xff0c;所以我们不能直接进行暴力模拟&#xff0c;我们知道10 2 * 5&#xff0c; 所以我们只需要找出这个数2和5的个数&#xff0c;其中2和5个数小的那个则为末尾0出现的个数 #include<bi…

搭建微信小程序环境及项目结构介绍

一、注册 访问微信公众平台&#xff0c;将鼠标的光标置于账号分类中的小程序上&#xff0c; 点击‘查看详情’ 点击“前往注册” 下方也可以点击注册&#xff1a; 小程序注册页面&#xff1a; 步骤a:进入小程序注册页&#xff0c;根据指引填写信息和提交相应的资料&#x…

黔院长 | 一文了解五脏的脏象!

你知道五脏的脏象是怎样的吗&#xff1f;下面一起来了解一下吧。 首先是我们的心&#xff0c;心主血脉&#xff0c;在体合脉&#xff0c;开窍于舌&#xff0c;其华在面。是说心脏是我们生命的根本&#xff0c;心气推动全身的血脉得以正常运行&#xff0c;心发生的生理和病理可…

应用案例|基于三维机器视觉的曲轴自动化上下料应用方案

Part.1 项目背景 此案例服务对象为国内某知名大型汽车零部件制造工厂&#xff0c;该工厂有针对曲轴工件的自动化上下料需求。由于之前来料码放不规范&#xff0c;工件无序散乱摆放&#xff0c;上料节拍要求高&#xff0c;该工厂上下料效率极低。 Part.2 传统曲轴上下料存在的缺…

【python图像处理】模糊图像

模糊前 模糊后 模糊 import os from PIL import Image, ImageFilterfacesPath face # 图片文件夹路径 faces os.listdir(facesPath) for face in faces:facePath os.path.join(facesPath, face)image Image.open(facePath)blurred_image image.filter(ImageFilter.BLU…