趣谈 Linux 操作系统
刘超
前网易杭州研究院云计算技术部首席架构师
85459 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 72 讲
趣谈 Linux 操作系统
15
15
1.0x
00:00/00:00
登录|注册

40 | IPC(上):不同项目组之间抢资源,如何协调?

释放权利
读取数据
判断共享内存数据状态
申请访问共享内存的权利
释放权利
写入数据
判断共享内存数据状态
申请访问共享内存的权利
使用semop函数
使用semctl函数
使用semget函数
使用shmdt函数
使用shmat函数
使用shmget函数
循环
创建共享内存和信号量
循环
创建共享内存和信号量
P操作和V操作
信号量的初始化
创建信号量集合
key的生成
使用完毕解除映射
映射到进程的虚拟地址空间
创建共享内存
key的生成
信号量大于1的情况下的应用场景
解除共享内存映射
信号量保护共享内存
共享内存映射
创建与初始化流程
消费者
生产者
信号量
共享内存
课堂练习
总结
生产者和消费者模型
共享内存和信号量配合

该思维导图由 AI 生成,仅供参考

我们前面讲了,如果项目组之间需要紧密合作,那就需要共享内存,这样就像把两个项目组放在一个会议室一起沟通,会非常高效。这一节,我们就来详细讲讲这个进程之间共享内存的机制。
有了这个机制,两个进程可以像访问自己内存中的变量一样,访问共享内存的变量。但是同时问题也来了,当两个进程共享内存了,就会存在同时读写的问题,就需要对于共享的内存进行保护,就需要信号量这样的同步协调机制。这些也都是我们这节需要探讨的问题。下面我们就一一来看。
共享内存和信号量也是 System V 系列的进程间通信机制,所以很多地方和我们讲过的消息队列有点儿像。为了将共享内存和信号量结合起来使用,我这里定义了一个 share.h 头文件,里面放了一些共享内存和信号量在每个进程都需要的函数。
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <string.h>
#define MAX_NUM 128
struct shm_data {
int data[MAX_NUM];
int datalength;
};
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
int get_shmid(){
int shmid;
key_t key;
if((key = ftok("/root/sharememory/sharememorykey", 1024)) < 0){
perror("ftok error");
return -1;
}
shmid = shmget(key, sizeof(struct shm_data), IPC_CREAT|0777);
return shmid;
}
int get_semaphoreid(){
int semid;
key_t key;
if((key = ftok("/root/sharememory/semaphorekey", 1024)) < 0){
perror("ftok error");
return -1;
}
semid = semget(key, 1, IPC_CREAT|0777);
return semid;
}
int semaphore_init (int semid) {
union semun argument;
unsigned short values[1];
values[0] = 1;
argument.array = values;
return semctl (semid, 0, SETALL, argument);
}
int semaphore_p (int semid) {
struct sembuf operations[1];
operations[0].sem_num = 0;
operations[0].sem_op = -1;
operations[0].sem_flg = SEM_UNDO;
return semop (semid, operations, 1);
}
int semaphore_v (int semid) {
struct sembuf operations[1];
operations[0].sem_num = 0;
operations[0].sem_op = 1;
operations[0].sem_flg = SEM_UNDO;
return semop (semid, operations, 1);
}

共享内存

我们先来看里面对于共享内存的操作。
首先,创建之前,我们要有一个 key 来唯一标识这个共享内存。这个 key 可以根据文件系统上的一个文件的 inode 随机生成。
然后,我们需要创建一个共享内存,就像创建一个消息队列差不多,都是使用 xxxget 来创建。其中,创建共享内存使用的是下面这个函数:
int shmget(key_t key, size_t size, int shmflag);
其中,key 就是前面生成的那个 key,shmflag 如果为 IPC_CREAT,就表示新创建,还可以指定读写权限 0777。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

共享内存和信号量在进程间通信中的配合机制是System V系列的进程间通信机制中的重要部分。共享内存允许两个进程像访问自己内存中的变量一样访问共享内存的变量,但也存在同时读写的问题,因此需要信号量这样的同步协调机制来保护共享内存。本文详细介绍了共享内存和信号量的创建、操作方法以及如何结合使用。通过示例代码展示了在生产者和消费者进程中使用共享内存和信号量进行数据交换和同步的方法。生产者负责往共享内存中放入数据,而消费者负责处理共享内存中的数据,实现了进程间的高效通信和协作。总结时刻部分提供了对共享内存和信号量配合机制的流程概述,以及对信号量大于1的情况下的使用建议。通过本文,读者可以深入理解共享内存和信号量的使用方法和原理,为进程间通信提供了一种有效的解决方案。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(13)

  • 最新
  • 精选
  • Amark
    请教一个问题,CPU调度是以进程为单位的吗,还是以线程?

    作者回复: 以task,在内核里面,进程和线程都是task

    2019-06-29
    16
  • 莫名
    System V IPC具有很好的移植性,但缺点也比较明显,不能接口自成一套,难以使用现有的fd操作函数。建议对比讲一下比较流行的POSIX IPC。

    作者回复: 赞

    2019-06-28
    13
  • nightmare
    信号量大于1的情况,可以让进程不操作共享变量,比如操作不同的变量,比如对一批数据做操作,然后做完之后给消费端读取

    作者回复: 是的

    2019-06-30
    4
  • 许童童
    信号量大于 1 的情况下,应该如何使用? 可以让多个进程同时访问一个共享内存。

    作者回复: 这个不行,大于1的时候,不能排他,但是可以控制资源

    2019-06-28
    2
    1
  • Jason
    老师好,ftok提示我的机器里没有“/root/sharememory/semaphorekey”这个文件,我随便新建一个文件可以吗?

    作者回复: 是的,创建一个就行

    2019-08-28
    2
  • trllllllll
    老师,share.h 里面 include 了两次 ipc.h。

    作者回复: 谢谢指正

    2019-07-07
  • Amark
    如果线程是掉用的到基本单位,那么进程的共享资源呢?

    作者回复: 内存,变量,文件,都是共享的呀

    2019-06-29
  • 有风
    信号量大于1,可以用于限流。如线程或进程的个数,访问请求的个数等。
    2022-02-16
    2
  • Tianz
    超哥,现在是不是推荐使用 POSIX 系列的 IPC 呢?
    2019-06-28
    2
  • 艾瑞克小霸王
    信号量和锁的区别就是 信号量可以控制资源数量(>1), 而锁是 互斥排他的?
    2019-12-06
    1
收起评论
显示
设置
留言
13
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部