Linux操作系统实验 —— 进程间通信

一  实验目的

(1)理解 Linux 关于进程间通信的概念。

(2)掌握几种进程间通信的方法。

(3)巩固进程同步概念和实现进程同步的方法。

二  实验内容

2.1 任务一

编写 C 程序,让父子两个进程通过消息队列相互聊天、发送消息,仅要求实现父(子)进程发送一条后接收一条,如此循环即可,不要求实现连续发送(接收)多条信息。其中每条消息大小不超过 1024 字节。

2.2 任务二

编写 C 程序,实现 reader 和 writer 两个进程,使它们通过共享内存交换数据:writer 从用户处获得输入,然后将其写入共享内存,reader 从共享内存获取信息,再在屏幕上打印出来。

2.3 任务三

使用多线程和信号量解决生产者/消费者问题:有一个长度为 N 的缓冲池被生产者和消费者共同使用。只要缓冲池未满,生产者就可以将消息送入缓冲池;只要缓冲池不空,消费者便可从缓冲池中取走一个消息。生产者向缓冲池放入消息的同时,消费者不能操作缓冲池,反之亦然。

三  实验过程及结果

(1)编写 C 程序,让父子两个进程通过消息队列相互聊天、发送消息,仅要求实现父(子)进程发送一条后接收一条,如此循环即可,不要求实现连续发送(接收)多条信息。其中每条消息大小不超过 1024 字节。

[实验步骤]:

1. 在主目录下创建一个demo目录,存放本次实验的代码文件,进入demo目录

2. 在demo目录下创建test1.c文件,编写代码

3. 安装编译需要的gcc软件包

4. 编译test1.c文件,运行a.out文件,父进程和子进程可以通过消息队列互相发送消息

[结果分析]:消息队列是一个存储消息的容器,它通常由操作系统维护。每个消息都有一个特定的类型,以便接收方可以选择性地接收特定类型的消息。消息队列允许进程通过往队列中发送消息或从队列中接收消息来进行通信。

        在这个例子中,定义了一个消息结构体msg_t,其中包含消息类型msg_type和自定义数据内容。通过ftok函数创建一个key,键值是一个唯一标识符,它允许进程在同一主机上找到相同的消息队列。然后使用msgget函数创建消息队列。父子进程通过msgsnd和msgrcv函数来发送和接收消息,通过msgctl函数删除消息队列。

(2)编写 C 程序,实现 reader 和 writer 两个进程,使它们通过共享内存交换数据:writer 从用户处获得输入,然后将其写入共享内存,reader 从共享内存获取信息,再在屏幕上打印出来。

[实验步骤]:

1. 在demo目录下创建test2.c文件,编写代码

2. 编译test2.c文件,运行a.out文件,writer 从用户处获得输入,然后将其写入共享内存,reader从共享内存获取信息

[结果分析]:以下是共享内存的基本原理:

  1. 内存分配: 进程通过调用系统调用(如 shmget)来请求一块共享内存。这块内存区域被分配一个唯一的标识符(通常是一个键值),允许其他进程通过该标识符连接到同一块内存。
  2. 连接到进程空间: 进程通过调用 shmat 将共享内存连接到自己的地址空间。这样,进程就可以直接访问这块内存区域,就像它是进程私有的一部分一样。
  3. 数据共享: 多个进程可以通过访问共享内存中的相同地址来实现数据共享。这样,一个进程对共享内存的写操作就能被其他进程立即看到,实现了进程间的通信。
  4. 同步机制: 由于多个进程可以同时访问共享内存,需要使用同步机制来确保数据的一致性和避免竞争条件。常见的同步机制包括互斥锁、信号量和条件变量。
  5. 分离和销毁: 当进程不再需要访问共享内存时,通过调用 shmdt 将共享内存分离(从进程地址空间中解除连接)。当所有进程都不再使用共享内存时,通过调用 shmctl 进行控制,可以选择销毁共享内存。

共享内存的优势在于速度快,因为进程直接访问物理内存,而不需要复制数据。然而,由于多个进程可以同时访问共享内存,需要仔细管理同步,以避免数据一致性问题。

(3)使用多线程和信号量解决生产者/消费者问题:有一个长度为 N 的缓冲池被生产者和消费者共同使用。只要缓冲池未满,生产者就可以将消息送入缓冲池;只要缓冲池不空,消费者便可从缓冲池中取走一个消息。生产者向缓冲池放入消息的同时,消费者不能操作缓冲池,反之亦然。

[实验结果]:

1. 在demo目录下创建test3.c文件,编写代码

2.  编译test3.c文件,运行a.out文件,有一个长度为 N 的缓冲 池被生产者和消费者共同使用。只要缓冲池未满,生产者就可以将消息 送入缓冲池;只要缓冲池不空,消费者便可从缓冲池中取走一个消息

[结果分析]:缓冲池是一个用于存储生产者产生的消息和供消费者消费的数据结构。在这个例子中,缓冲池是一个长度为 N 的数组(buffer),用于存储消息。

信号量原理:

信号量是一种用于在线程之间进行同步和互斥的机制。在这个问题中,有三个信号量:empty_sem、full_sem 和 buffer_sem。通过合理使用这三个信号量,可以确保生产者和消费者线程之间的正确同步,避免竞争条件,从而有效解决了生产者-消费者问题。

1)full_sem: 表示满槽位的数量。当生产者将一个消息放入缓冲池时,它会增加 full_sem 的值,表示缓冲池中的空槽位增加了一个。

2)empty_sem: 表示空槽位的数量。当消费者从缓冲池中取走一个消息时,它会增加 empty_sem 的值,表示缓冲池中的满槽位增加了一个。

3)buffer_sem: 用于控制对缓冲池的访问。它的值为 1 表示缓冲池是可用的。在生产者或消费者访问缓冲池时,会对 buffer_sem 进行 P 操作(等待),然后在访问完成后进行 V 操作(释放)。

四  实验总结

本次实验主要围绕Linux环境下的进程间通信(IPC)展开,涉及了不同的通信方法和进程同步的概念。总体而言,进程之间的通信主要有两种方式,分别是消息队列和共享内存,除此之外,我们还学习了如何使用多线程和信号量的方法解决生产者-消费者的问题,增强了对于进程通信和进程同步的理解和掌握。

1.消息队列:

   - 消息队列是一种进程间通信的方式,通过在进程间传递消息实现数据交换。

   - 在实验中,我们通过使用msgget、msgsnd和msgrcv等系统调用来创建消息队列、向队列发送消息和从队列接收消息。

   - 这种通信方式适用于需要异步传递信息的场景,不同进程可以独立进行读取和写入操作。

2.共享内存:

   - 共享内存是一种允许多个进程共享同一块物理内存的通信方式。

   - 通过shmget、shmat和shmdt等系统调用,我们能够创建共享内存区域,并将其附加到进程的地址空间中,以便多个进程可以直接访问共享数据。

   - 这种通信方式的优点是速度快,因为数据直接在内存中传递,但需要谨慎处理同步问题,以防止数据一致性问题。

3. 多线程和信号量解决生产者-消费者问题:

   - 多线程信号量是一种用于解决并发程序中资源访问的同步机制。

   - 在解决生产者-消费者问题时,我们通过使用互斥锁(mutex)和信号量(semaphore)来确保生产者和消费者线程之间的同步。

   - 通过pthread_mutex_init、pthread_mutex_lock、pthread_mutex_unlock等函数,以及sem_init、sem_wait和sem_post等函数,我们实现了对共享数据的安全访问。

        通过这次实验,我们深入理解了Linux环境下的进程间通信的概念,同时掌握了消息队列和共享内存两种通信方式。进一步地,通过解决生产者-消费者问题,我们加强了对进程同步概念以及同步方法的理解。这些知识对于编写高效、可靠的多进程或多线程应用程序至关重要。

  • 22
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值