操作系统综合实验1(一)

简介: 操作系统综合实验1

一、实验目的与要求


综合利用进程控制的相关知识,结合对shell功能的和进程间通信手段的认知,编写简易shell程序,加深操作系统的进程控制和shell接口的认识。


二、实验内容


使用Linux操作系统;学习使用Linux进程间控制,进程间通信,管道,消息队列,共享内存等手段以及处理机调度

学会使用POSIX信号量实现生产者与消费者间同步关系

编写简易shell程序


三、实验步骤与过程


1 Linux学习与实践


1.1 管道


进程间的管道通信有两种形式,无名管道用于父子进程间,命名管可以用于任意进程间— —命名管道在文件系统中有可访问的路径名。管道通信方式主要用于单向通信,如果需要双向 通信则建立两条相反方向的管道。管道实质是由内核管理的一个缓冲区(一边由进程写入,另 一边由进程读出),因此要注意,如果缓冲区满了则写管道的进程将会阻塞。另外管道内部没 有显式的格式和边界,需要自行处理消息边界,如果多进程间共享还需要处理传送目标等工作。


无名管道


管道(pipe),或称无名管道,是所有 Unix 都提供的一种进程间通信机制。管道是单向的 信道,进程从管道的写端口写入数据,需要数据的进程从读端口中获取数据,数据在管道中按 到达顺序流动。Unix 命令中使用“|”来连接两个命令时使用的就是管道,例如“ls | more”将 ls命令的标准输出内容写入到管道中,管道的输出内容作为 more 命令的标准输入。注意,重定向技术虽然看起来和管道很相似,例如“ls > temp”,但重定向并不使用管道。


如下面图 1,以 pipe()为例展示父子进程间使用管道进行通信的方法,pipe()将通过两个文件描述符(整数)来指代管道缓冲区的读端和写端(代码中用 fds[] 变量记录)。其中父进程关闭管道的读端 fds[0]并往管道的写端 fds[1]写出信息,子进程关闭了管道的写端 fds[1]并从管道的读端 fds[0]读回信息。


8b95997e208742d4937304921ae3c6ec.png


图 1 pipe-demo.c 代码


6687abad1eb94606a6766ddde6edfba9.png


图 2 pipe-demo.c输出


图 2是图 1中pipe-demo运行的输出,其表明父进程发送了消息到管道,子进程成功接收到了“Message from parent”。


命名管道


前面提到的无名管道有一个主要缺点,只能通过父子进程之间(及其后代)使用文件描述符的继承来访问,无法在任意的进程之间使用。命名管道(named pipe)或者叫 FIFO 则突破了这个限制。可以说 FIFO 就是无名管道的升级版——有可访问的磁盘索引节点,即 FIFO 文件将出现在目录树中(不像无名管道那样只存在于 pipefs 特殊文件系统中)。


下面图 3我们用 mkfilo 命令来创建命名管道 os-exp-fifo,如屏显 4-2 所示,其中 ls 命令查看时可以看出其类型是管道“p”。


a9e0481b7c8c4cef955d14947309e3f9.png


图 3 mkfifo 创建命名管道


此时可以用 cat os-exp-fifo 命令尝试从管道中读入数据,但是此时管道中还没有写入任何数据,因此 cat 将进入阻塞状态,如图 4:


f7bbb08226a6417293667074d4b415d1.png


图 4 用 cat 尝试读取空的管道文件(阻塞)


如果此时在另一个终端上用“echo Hello, Named PIPE! >os-exp-fifo”则cat 会被唤醒并读入管道数据回显字符串“Hello, Named PIPE!”,如图 5


a3d3ef107c724416a7584d21c7e70632.png


图 5 用 echo 向管道写入数据


1.2 System V IPC


Linux 的进程通信继承了 System V IPC。System V IPC 指的是 AT&T 在 System V.2 发行版中 引入的三种进程间通信工具:


信号量,用来管理对共享资源的访问

共享内存,用来高效地实现进程间的数据共享

消息队列,用来实现进程间数据的传递。

我们把这三种工具统称为 System V IPC 的对象,每个对象都具有一个唯一的IPC标识符 ID。为了使不同的进程能够获取同一个 IPC 对象,必须提供一个IPC 关键字(IPCkey),内核负责把 IPC 关键字转换成 IPC 标识符 ID。下面我们观察这三种IPC 工具。


在Linux中执行ipcs命令可以查看到当前系统中所有的System V IPC对象,如图 6所示。


9deb1f3055524d3cae5fab7d90ae198a.png


图 6 ipcs 命令的输出


查看这些 IPC 对象时还可以带上参数,ipcs -a 是默认的输出全部信息、ipcs -m 显示共享内 存的信息、ipcs -q 显示消息队列的信息、ipcs -s 显示信号量集的信息。另外用还有一些格式控 制的参数,–t 将会输出带时间信息、-p 将输出进程 PID 信息、-c 将输出创建者/拥有者的 PID、 -l 输出相关的限制条件。例如用 ipcs -ql 将显示消息队列的限制条件,如图 7所示。


913db72809654802be8b4c2f6408841f.png


图 7 ipcs -ql 的输出


删除这些 IPC 对象的命令是 ipcrm,它会将与 IPC 对象及其相关联的数据也一起删除, 管 理员或者 IPC 对象的创建者才能执行删除操作。该命令可以使用 IPC 键或者 IPC 的 ID 来指定 IPC 对象:ipcrm -M shmkey 删除用 shmkey 创建的共享内存段而 ipcrm -m shmid 删除用 shmid 标识的共享内存段、ipcrm -Q msgkey 删除用 msqkey 创建的消息队列而 ipcrm -q msqid 删除用 msqid 标识的消息队列、ipcrm -S semkey 删除用 semkey 创建的信号而 ipcrm -s semid 删除用 semid 标识的信号。


1.2.1 消息队列


消息队列有些项邮政中的邮箱,里面的消息有点像信件——有信封以及写有内容的信纸。 由于各条消息可以通过类型(type)进行区分,因此可以用于多个进程间通信。比如一个任务 分派进程,创建了若干个执行子进程,不管是父进程发送分派任务的消息,还是子进程发送任务执行的消息,都将 type 设置为目标进程的 PID,目标进程只接收消息类型为 type 的消息就 实现了子进程只接收自己的任务,父进程只接收任务结果。


下面图 8图 9给出代码 msgtool.c,其每次启动都是以新的进程形式运行,因此各次运行都是相互独立的。其中发送消息的核心函数是 msgsnd(),第一个参数是消息队列的 ID,第二个参数时被发送消息的起始地址(消息的第一个成员是一个整数用于指出消息类型),第三个参数时消息长度,第四个参数指定写消息时的一些行为(此例子用 0);接受消息的函数是 msgrcv(),第一个参数用于指定消息队列的ID,第二个参数是接受缓冲区地址,第三个参数指出希望接受的消息类型(0 表示接受任意类型的一条消息,>0表示接受指定类型的消息,


2d119cfba7ee4bac95b2b74bf5d56c93.png


图 8 msgtool.c 代码


55241d6480944a6e9324cc7827c4fa1c.png


图 9 msgtool.c 代码


执行 msgtool s 1 Hello,my_msg_queue!发送类型为 1 的消息,然后用ipcs -q 查看新创建的消息队列,里面有 20 个字节的一条消息。此时再执行 msgtool -r 1(另一个进程了)读走类型为 1 的消息,然后再用 ipcs -q 可以看到该消息队列为空(0 字节)了。上述操作的输出如图 10:


64c34f9dc5114f57afae68c8246633fa.png


图 10 msgtool 的执行结果


1.2.2 共享内存


System V IPC 的共享内存是由内核提供的一段内存,可以映射到多个进程的续存空间上, 从而通过内存上的读写操作而完成进程间的数据共享。我们首先来看看如何创建共享内存的, 示例代码如图 11所示,它创建了一个 4096 字节的共享内存区。shmget()的第一个参数 IPC_PRIVATE(=0,表示创建新的共享内存),第二个参数是共享内存区的大小,第三个是访问 模式。虽然也可以像前面的消息队列的例子那样通过 ftok()将键值转换成 ID,但这里没有指定 ID,而是创建共享内存后由系统返回一个 ID 值(后面的进程要使用该共享内存时需要指定该 ID)。


d9e0d2b4b41443dfbf5c2dfbad6d1e8e.png


图 11 shmget-demo.c代码


执行该程序,其输出如图 12所示。输出结果表明新创建的共享内存的 ID为24,长度为 4096 字节,当前还没有进程将他映射到自己的进程空间(连接数列为 0)。


b37f0a1071374d1e90995c1dbff79773.png


图 12 shmget-demo.c的运行结果


下面展示另一个进程通过影射该共享内存而使用它的过程,具体如图 13所示


f876bed69c234da7bd9c9fc112accdf4.png


图 13 shmatt-write-demo.c 代码


我们运行 shatt-demo 24(命令行参数中指出共享内存的 ID 为 24),其第一段输出结果如图 14所示。完成共享内存的映射后,shmatt-write-demo 往共享内存中写入一个 字符串“Hello shared memory!”。shmatt-write-demo 还通过 system()执行了“ipcs -m”,因此 也输出了当前的共享内存信息,可以看到 ID 为 24 的共享内存已经有被映射了一次 (nattach 列为 1)。


05870a99fa104690a31a8171fce55176.png


图 14 shmatt-write-demo.c运行结果


接下来使用 ps -a 指令,可以看到 shmatt-write-de 的 PID为4898,如图 15


416c8ed8e13447c28de8b9cbfba762de.png


图 15  ps -a 指令查看matt-write-de 的 PID


使用 cat /proc/4898/maps 查看进程的进程空间,可以看到进程布局如图 16所示


1d375c113a9a46238e6c0bcd71a8b2ec.png


图 16 运行之后的进程布局


在 shmatt-write-demo击键回车后将解除共享内存的映射,此时ipcs -m显示对应的共享内存区没有人使用(连接数为 0),如图 17所示。此时如果检查内存布局可以发现原来区间的虚存已经消失。


13b406e059ee42e88a2eae78cf3e3b7d.png


图 17 运行write后的共享内存


此时再尝试用另一个程序去映射该共享内存并从中读取数据,shmatt-read-demo 代码如图 18所示。


6bcac05c60b241cda11b73ad5e72924f.png


图 18 shmatt-read-demo.c代码


如图 19,可以看到虽然创建该共享内存的进程已经结束了,可是shmatt-read-demo映射 ID 为 24 的共享内存后仍读出了原来写入的字符串。


c0abbccc23584b638046cdc822d56626.png


图 19 运行read后的共享内存


从上面实验看出共享内存是比较灵活的通信方式,不需要像管道一样用文件接口read()、write()等函数,也不需要像消息队列那样用 msgsend()/msgrcv()等函数来操作,直接用内存指针的方式就可以操作。虽然实验中没有验证其容量,但是共享内存的容量远比管道和消息队列大。


1.2.3 信号量数组/信号量集


在操作系统原理性课程中我们以及学习过信号量和信号量集机制。Linux 支持的System V IPC 中的信号量实际上是信号量数组(信号量集),一次可以创建多个信号量。创建或者获得信号量集之后,可以对各个信号量进行 P/V 操作(或者称up/down 操作),进程进行 P/V 操作时遵循信号的同步约束关系——由操作系统完成进程的阻塞或唤醒。


1.3 进程间同步


Linux 同时支持 System V IPC 中的信号量集和 POSIX 信号量。前者常用于进程间通信、是基于内核实现的(不随进程结束而消失);而后者是常用于线程间同步、方便使用且仅含一个信号量。POSIX 信号量分成有名信号量和无名信号量,前者和一个文件的路径名相关联,创建 后不随进程结束而消失(可用于进程间通信),反之无名信号量则只在进程生命周期内存在且 只能在该进程创建的线程间使用。 上述两种信号量的编程接口函数是很容易被区分:对于所有 System V信号量函数,在它们的名字里面没有下划线(例如,有semget()而不是sem_get()),然而所有的 POSIX 信号量 函数都有一个下划线(例如,有sem_post()而不是sempost())。Linux操作系统内核内部也有多个并发的执行流,它们之间使用内核的信号量,和这里讨论的用户态信号量又不相同。


1.3.1 System V IPC 信号量集


进程间的 System V IPC 信号量集的同步机制已经在前面 System V IPC 中和进程间通信主题一并讨论过,这里不再重复。


1.3.2 POSIX 信号量


POSIX 信号量又分成有名信号量和无名信号量,前者可以用于在多个进程间或多个线程间的同步,无名信号量只能用于线程间同步。两者的创建函数不同,但是响应的P/V操作函数是一样的。有名信号量由于可以通过标识来访问,因此可以同时用于进程间同步和线程间同步。有名信号量的创建使用 sem_open()完成,代码 psem-named-open.c 如图 20所示,其先用 sem_open()创建了一个信号量,该信号量由一个字符串所标识。

85306b6330104636b4a184d5e2ac08ca.png

图 20 psem-named-open.c代码


然后用 gcc psem-named-open.c -o psem-named-open -lpthread(参数-lpthread 用于指出链接时所用的线程库)完成编译,然后运行 psem-named-open。如果没有输入作为标识的文件名字符串,则给出提示要求用户输入;如果输入一个文件名字符串,正常情况将完成创建过程,如图 21所示。


43e589fcfeca4c3582c64373a84051e6.png


图 21 psem-named-open 的输出


之后尝试执行 P/V 操作中的 V 操作(即对信号量进行减 1 操作,可能引发阻塞),程序psem-named-wait-demo.c如图 22所示,它通过 sem_wait()来执行V 操作(减1 操作),并且通过 sem_getvalue()来查看信号量的值。同样出于代码简洁的考虑,这里的代码也是没有检查 sem_open()是否成功获得了信号量。因此,如果输入错误的标识字符串,则无法成功获得所指定的信号量,sem_wait()引用无效的信号量而引发段错误。


604f0d661c074b649aa93f9233ddf66c.png


图 22 psem-named-wait-demo.c 代码


相关文章
|
3月前
|
弹性计算 运维
阿里云操作系统智能助手OS Copilot实验测评报告
**OS Copilot 产品体验与功能反馈摘要** 运维人员发现OS Copilot易上手,文档清晰,助其高效排查故障(8/10分)。愿意推荐并参与开源开发。亮点在于知识问答,能快速筛选答案。相较于竞品,优点是新手友好、文档清晰,但功能扩展性待增强。期望增加系统错误排查与解决方案,并集成ECS等,以优化系统安装流程。
阿里云操作系统智能助手OS Copilot实验测评报告
|
3月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot实验测评报告
OS Copilot是针对Linux的智能助手,助力学习、运维及编程。用户界面直观,自然语言交互方便新手。官方文档详尽,但初次配置略复杂,适合学生和开发者。在提高代码编写和调试效率、系统学习上得分高,功能亮点包括代码生成、问答和命令执行。用户期待更多操作系统支持、自动错误分析和系统排查功能。
182 3
|
3月前
|
弹性计算 人工智能 运维
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云操作系统智能助手OS Copilot实验测评报告
108 2
|
3月前
|
弹性计算 运维 监控
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云OS Copilot助力学生提升学习效率,简化Linux操作。作为学生,体验者发现它在代码理解和诊断上极具价值,给予新手友好体验,但存在命令执行限制和错误处理问题。评分10/10,愿推荐并参与未来开发。功能上,知识问答、辅助编程和命令执行深受喜爱。对比其他产品,OS Copilot简洁集成,但需改善多命令支持和错误分析。期望支持更多操作系统及与ACK等工具联动,增强系统管理和故障排查。
43 1
|
3月前
|
弹性计算 运维 Linux
阿里云操作系统智能助手OS Copilot实验测评报告
体验OS Copilot对于新人使用是友好的,教程给出的比较全面,还支持语言问答,命令执行等优点,还允许用户直接在操作系统内部使用阿里云,完成ECS的实例查询等操作。但是在系统兼容上表现出不足,对于服务器地区不明确。但总体来说测评者对OS Copilot其智能化、高效化、专业化评价是高的。
|
3月前
|
弹性计算 运维
阿里云操作系统智能助手OS Copilot的实验测评报告
OS Copilot 产品体验摘要 用户角色与场景:一位计算机学生使用辅助学习和解决问题,特别是通过代码解释功能加深理解。 易用性与文档:初者可能会觉得有些细节不明确。 帮助程度:用户给予极高评价,对学习帮助大,评分10分,快速定位和解决代码问题,提升学习效率。 推荐与参与:用户愿意推荐给他人。 功能体验:用户尝试了所有功能,对知识问答、辅助编程和命令执行特别感兴趣,尤其是命令执行帮助大。 对比其他产品:OS Copilot优点是便捷、准确。 期望功能:用户希望增加自动报错分析和系统错误排查。 联动体验:用户期待,以实现更全面的工具集。 总结:整体体验积极,用户看好其潜力,期待改进和未来联动。
|
3月前
|
弹性计算 运维 Python
阿里云操作系统智能助手OS Copilot实验测评报告
**OS Copilot 产品测评摘要** - 学生使用,用于学习和编码,发现上手难度较高,指引文档不清晰,特别是Access ID设置和代码复制流程。 - 功能上,评分9分,辅助编程和知识问答功能显著提升了学习效率,减少了错误。 - 愿意推荐,并有兴趣参与开源开发以提升自我。 - 希望增强错误排查,提供具体错误原因和位置。 - 联动ACK智能助手可增强学习效果。 [链接]: https://developer.aliyun.com/topic/instructions-for-os-copilot
|
3月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot的实验测评报告
阿里云OS Copilot是AI驱动的Linux操作系统助手,助于系统管理和运维。学生反馈它在代码解释和编写上有很大帮助,给予8-9分的评价。功能亮点包括自然语言问答、辅助编程和命令解释,简化操作,提升效率。尽管易用,但需基础Linux知识。用户期待更多功能如系统优化建议和代码优化。与ACK智能助手配合,实现故障排查和运维。适合寻求效率提升的个人和团队。
65 0
|
3月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云OS Copilot是面向Linux的智能助手,助运维工程师提升效率。易上手,文档清晰,对新人友好。提供自然语言问答、编程辅助,尤善理解与响应。评分10/10,推荐给同行。目前侧重辅助编程,期望支持更多OS、并发命令执行及错误分析。适合集成于ECS等,打造自动化工作流。期待开源版本与社区合作。
93 0
|
3月前
|
弹性计算 运维 安全
操作系统智能助手OS Copilot实验测评报告
**阿里云OS Copilot摘要** OS Copilot是面向开发者和学生的智能助手,尤其对学习编程和运维有显著帮助。虽然初期上手复杂,但其知识问答、辅助编程功能深受好评,评分10分。用户愿推荐给他人,并期待开源参与开发。产品优点包括多功能、便捷性和高准确度,但新手引导需改进。期望增加Windows支持和自动化错误分析功能。通过与ECS等产品联动,OS Copilot能提升整体效率,简化操作,展现云服务的未来潜力。
59 0