《操作系统》实验报告——进程通信

article/2025/9/14 10:36:28

理论知识

Linux——Linux C语言编程基础知识

Linux——进程通信

一、实验目的

(1) 熟悉并掌握管道机制,并实现进程间通信

(2) 熟悉并掌握共享内存机制,并实现进程间通信

二、实验内容

任务一:

(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。

(2)编写程序:父进程利用管道将一字符串交给子进程处理。子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。

任务二:

(1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。

1、ipcs命令的作用:用于查看系统中共享存储区,消息队列和信号量的情况。如下图:

[x02620101@localhost x02620101]$ ipcs------ Shared Memory Segments --------
key        shmid      owner      perms      bytes     nattch  status
0x0000000f 262145     x02620101 644        1000       0
0x00000000 294914     x02620101 644        20         0------ Semaphore Arrays --------
key        semid      owner      perms      nsems------ Message Queues --------
key        msqid      owner    perms      used-bytes   messages

2、ipcrm命令的作用:用于删除系统中存在的共享存储区,消息队列等。如:

ipcrm  -M key 表示根据关键字删除共享存储区

ipcrm -m id表示根据标识符删除共享存储区

ipcrm -Q key表示根据关键字删除消息队列

ipcrm -q id表示根据标识符删除消息队列

(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。

注:把&加在一个命令的最后,可以把这个命令放到后台执行 ,如gftp &,

(3)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。

注:

需要包含头文件:

#include <sys/wait.h>

举例:

sleep(1);   休眠一秒

三、代码及运行结果分析

任务一:

(1)

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>int main()
{int x,fd[2];char buf[30],s[30];pipe(fd);while ((x=fork())==-1);if (x==0){close(fd[0]);printf("Child Process!\n");strcpy(buf,"This is an example\n");write(fd[1],buf,30);exit(0);}else{close(fd[1]);printf("Parent Process!\n");read(fd[0],s,30);printf("%s\n",s);}return 0;
}

 

分析: 

调用pipe(fd);创建一个管道后,接着调用fork()函数产生两个进程,首先开始执行子进程,关闭管道出口,通过管道入口向管道中写入内容。父进程中,管道入口关闭,通过管道出口端从管道中读取之前写入内容,最后输出出来。

(2)

#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(){int x,count,left,right,temp,fd[2],fe[2];char c,buf[30],s[30];pipe(fd);pipe(fe);printf("please input a line of char:\n");scanf("%s",buf);while((x=fork())==-1);if(x==0){close(fd[0]);close(fe[1]);printf("Child Process!\n");write(fd[1],buf,30);read(fe[0],buf,30);printf("%s\n",buf);exit(0);}else{close(fd[1]);close(fe[0]);count=0;do{read(fd[0],&c,1);s[count++]=c;}while(c!='\0');printf("Parent Process!\n");printf("%s\n",s);count-=2;for(left=0,right=count;left<=count/2;left++,right--){temp=s[left];s[left]=s[right];s[right]=temp;}write(fe[1],s,30);wait(0);}
}

 

任务二:

(1)

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main(){key_t key=200; /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/int shmid_1,shmid_2;if ((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){perror("shmget shmid_1");exit(1);}printf("First shared memory identifier is %d\n",shmid_1);if ((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){perror("shmget shmid_2");exit(2);}printf("Second shared memory identifier is %d\n",shmid_2);exit(0);return 0;
}

分析: 

成功,返回共享内存段的标识符,内核中用于唯一的标识一个对象。对存在于内核存贮空间中的每个共享内存段,内核均为其维护着一个数据结构shmid_ds。 失败,返回-1,设置errno。 

①第一个参数key(键值)用来创建IPC标识符,shmget()返回的标识符与key值一一对应,不同的key值返回不同的标识符。 

②第二个参数size,决定了共享内存段的大小(若访问已存在的内存段,该参数可设为0)。有最大字节数的限制 

③第三个参数shmflag,用于设置访问权限及标识创建条件。 

对两次的结果进行比较:

两次运行结束后的 第二个共享标识符是不一样的。在用ipcs查看时,共享内存段中的关键字,共享内存标识符,访问权限,字节等都是不一样的。

(2)

程序1:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 200  /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K  1024
int shmid;
int main (){int i,*pint;char *addr;//extern int shmat();extern cleanup();for(i=0;i<20;i++) signal(i,cleanup);shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址 */printf ("addr 0x%x\n",addr);pint=(int *)addr;for (i=0;i<256;i++) *pint++=i;pause();/*等待接收进程读 */
}
cleanup()
{shmctl(shmid,IPC_RMID,0);exit(0);
}

程序2: 

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 200  /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K  1024
int shmid;
int main ()
{int i,*pint;char *addr;//extern char * shmat ();shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */addr=shmat(shmid,0,0);/*连接共享区*/pint=(int *)addr;for (i=0;i<256;i++)printf("%d\n",*pint++);/*打印共享区中的内容*/
}

分析: 

首先系统通过调用shmctl对预定义的shmid指向的内存段进行删除操作,防止冲突,接着系统调用shmget创建一个16*1024字节的共享内存段,成功返回共享内存段的标识符给shmid,系统再次调用shmat连接内存段,返回该共享内存段连接到调用进程地址空间上的地址addr。

程序1后台运行时,该程序开始执行,系统调用shmget创建一个8*1024字节的共享内存段,再通过调用shmat挂接内存段,由系统选择挂接地址,最终输出转换后的挂接地址。最后输出前255的内容。共享存储区机制只为通信进程提供了访问共享存储区的操作条件,而对通信的同步控制则要依靠信号量机制等才能完成。

(3)

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 200
#define K 1024
int shmid_1,shmid_2;
int main ()
{int x,y,i,*pint;char *addr_1,*addr_2;char words[26]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','X'};shmid_1=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */addr_1=shmat(shmid_1,0,0);/*挂接,并得到共享区首地址*/pint=(int *)addr_1;printf ("addr_1 0x%x\n",addr_1);for (i=0;i<26;i++) {*pint=words[i];pint++;}while((x=fork())==-1);if(x==0){shmid_2=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */addr_2=shmat(shmid_2,0,0);/*挂接,并得到共享区首地址*/pint=(int *)addr_2;for(i=0;i<26;i++){printf("%c ",*pint);*pint=*pint+32;pint++;if(i==25)printf("\n");}y=shmdt(addr_2);exit(0);}else{sleep(5);pint=(int *)addr_1;for(i=0;i<26;i++){printf("%c ",*pint);pint++;if(i==25)printf("\n");}}
}

四、实验心得

通过本次实验了解了管道进程间通信形式,掌握利用管道进行进程通信的程序设计,管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统。数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。基本达到了本次实验的要求。另外,对于共享内存通信的工作机制也有了一定的了解,掌握线程与进程在组成成分上的差别,以及与其相适应的通讯方式和应用目标。知道了操纵共享内存共有shmget()、shmat()、shmdt()、shmctl()4个系统调用。ipcs命令的作用:用于查看系统中共享存储区,消息队列和信号量的情况,ipcrm命令的作用:用于删除系统中存在的共享存储区,消息队列。也让我对管道及共享区的作用和用法,以及对操作系统中各进程之间的通信和协同作用等方面有了更深的了解。总之,本次实验自己收获了很多。

 

参考文章

实验三、进程通信(一) ——管道及共享内存

实验三、 操作系统(OS)--进程通信(管道及共享内存)

实验三 进程通信(一)

linux c 休眠函数sleep usleep

Linux后台进程管理以及ctrl+z(挂起)、ctrl+c(中断)、ctrl+\(退出)和ctrl+d(EOF)的区别

 


http://chatgpt.dhexx.cn/article/DXWiDl38.shtml

相关文章

多进程通信

多进程&#xff1a; 首先&#xff0c;先来讲一下fork之后&#xff0c;发生了什么事情。 由fork创建的新进程被称为子进程&#xff08;child process&#xff09;。该函数被调用一次&#xff0c;但返回两次。两次返回的区别是子进程的返回值是0&#xff0c;而父进程的返回值则…

进程间通信详解

目录 一.进程间通信介绍 1.进程间通信的目的 2.进程间通信的本质 3.进程间通信分类 二.什么是管道 三.匿名管道 1. 匿名管道只能用于具有亲缘关系的进程之间进行通信&#xff0c;常用于父子。 2.pipe函数 3. 匿名管道的使用 4.管道的读写…

QProcess实现进程通信

QProcess实现进程通信的方式有点类似于管道。 QProcess父进程通过write来写入标准输入stdin&#xff0c;通过ReadyRead信号来接收子进程的消息。 QProcess子进程通过QFile来读取标准输入来接收父进程信息。通过QFile绑定QSocketNotifier来接收标准输入的实时信号&#xff0c;…

进程通信原理

目录 进程通信原理 1、同主机间的消息通讯机制 1.1 管道&#xff08;pipe&#xff09;,流管道(s_pipe)和有名管道&#xff08;FIFO&#xff09; 1.2 信号&#xff08;signal&#xff09; 1.3 消息队列 1.4 共享内存 信号量 套接字&#xff08;socket) 进程间通信各种方式效率比…

Linux进程通信

笔者在学习linux的过程中对linux进程通信进行记录学习。现在在 Linux 中使用较多的进程间通信方式主要有以下几种。 &#xff08;1&#xff09;管道&#xff08;Pipe&#xff09;及有名管道&#xff08;named pipe&#xff09;&#xff1a;管道可用于具有亲缘关系进程间的通信…

【Linux】进程间通信

目录 1. 进程间通信 1.1. 进程间通信的目的 1.2. 如何实现进程间通信 2. 管道通信 2.1. 匿名管道 2.1.1 创建匿名管道 2.1.2 . 深入理解匿名管道 2.2. 命名管道 2.2.1. 创建命名管道 3. system V 标准进程间通信 3.1. 共享内存 3.1.1. 实现原理 3.1.2. 代码实现 3…

认知智能理论三体论介绍简介

三体论是探索研究宇宙&#xff0c;信息和人类大脑三者关系的理论体系。是认知智能的奠基理论体系之一。宇宙和信息&#xff0c;信息和人类大脑&#xff0c;人类大脑和宇宙&#xff0c;三者之间存在着某种未被完全揭示的奥秘。三体论的核心思想体系就是基于宇宙&#xff0c;信息…

认知智能三大技术体系之类脑模型简介

认知智能三大技术体系之类脑模型简介 类脑模型是认知智能核心三大技术体系之一&#xff0c;类脑结构&#xff0c;功能机制的总称。类脑模型技术体系核心指导思想来自认知智能三大奠基理论&#xff0c;脑科学&#xff0c;心理学&#xff0c;逻辑学&#xff0c;情感学&#xff0c…

认知智能CI和人工智能AI的区别介绍简介

认知智能CI和人工智能AI的区别 人工智能和认知智能都是计算机科学的分支学科之一。人工智能是智能时代的第二个阶段&#xff0c;认知智能是智能时代的第三个阶段。认知智能也并不是智能时代发展的最终阶段&#xff0c;最终阶段应该是通用智能强智能时代。 本文主要就人工智能和…

什么是认知智能?

认知智能是计算机科学的一个分支科学&#xff0c;是智能科学发展的高级阶段&#xff0c;它以人类认知体系为基础&#xff0c;以模仿人类核心能力为目标&#xff0c;以信息的理解、存储、应用为研究方向&#xff0c;以感知信息的深度理解和自然语言信息的深度理解为突破口&#…

认知智能是什么?

认知智能是计算机科学的一个分支科学&#xff0c;是智能科学发展的高级阶段&#xff0c;它以人类认知体系为基础&#xff0c;以模仿人类核心能力为目标&#xff0c;以信息的理解、存储、应用为研究方向&#xff0c;以感知信息的深度理解和自然语言信息的深度理解为突破口&#…

人工智能导论

目录 1.1 人工智能导论 1.2 人工智能应用 1.3 人工智能产业发展 1.4 人工智能发展的成功因素 1.5 人工智能迅速发展的技术领域 1.6人工智能的基础知识 1.1 人工智能导论 人工智能的三个层面&#xff1a; 计算智能&#xff1a;能算能存 感知智能&#xff1a;能听会说&…

如何用AI技术增强企业认知智能?超详细架构解读

认知的高度决定了创造价值的高度。 企业在从创办、发展、竞争、成功到衰亡的全生命周期中&#xff0c;会面临复杂多样的决策场景。 然而&#xff0c;时代演变产生的海量、分散、实时的信息&#xff0c;仅靠人类个体是难以高效、准确地感知、认知和决策的。 因此&#xff0c;企…

深度KWeaver:价值驱动,认知智能走向开源共创

文|智能相对论 作者|叶远风 在底层硬件创新之外&#xff0c;软件创新对提升中国前沿科技竞争力同样重要&#xff0c;这其中&#xff0c;开源的必要性毋庸置疑。但是&#xff0c;在全球范围内开源项目硕果累累的大背景下&#xff0c;中国开源过去的发展却不够快&#xff0c;直…

AI的下一个战场:认知智能的突围

2020-01-20 14:32 导语&#xff1a;AI的下一种可能 “深度学习的钥匙丢在了黑暗角落。”张钹院士不止一次提出这个论点。深度学习方法易受欺骗、易受攻击已经是研究者们达成的共识&#xff0c;追其根本原因&#xff0c;张钹归结为&#xff1a;大家只是在灯亮的方向对模型修修补…

认知智能介绍发展道翰天琼

计算智能、感知智能和认知智能&#xff0c;是探索人工智能道路上的三个台阶。 在计算智能方面&#xff0c;机器早已远远超过人类。而在感知智能方面&#xff0c;机器也已达到可媲美人类的水平。科大讯飞在语音识别错误率上每年相对下降30%以上。在2018年CHiME-5国际多通道语音分…

【干货】认知智能时代:知识图谱实践案例集.pdf(附下载链接)

大家好&#xff0c;我是文文&#xff08;微信号&#xff1a;sscbg2020&#xff09;&#xff0c;今天给大家分享中国电子技术标准化研究院于2021年1月份发布的干货报告《认知智能时代&#xff1a;知识图谱实践案例集.pdf》&#xff0c;关注知识图谱及人工智能伙伴们别错过了&…