Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)

简介: 通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。

在Linux系统中,进程间通信(IPC, Inter-Process Communication)是指多个进程之间的数据交换和同步手段。常见的IPC机制包括共享内存、消息队列和信号量。本文将详细讲解这三种IPC机制,并提供小项目示例和相关指令。

一、共享内存

共享内存是最快的IPC机制,因为它允许多个进程直接访问同一块内存区域。共享内存的使用涉及几个系统调用:shmgetshmatshmdtshmctl

1.1 创建和附加共享内存

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SHM_SIZE 1024  // 共享内存大小

int main() {
    key_t key = ftok("shmfile", 65);  // 生成唯一键值
    int shmid = shmget(key, SHM_SIZE, 0666|IPC_CREAT);  // 创建共享内存
    char *str = (char*) shmat(shmid, (void*)0, 0);  // 连接共享内存

    printf("Write Data: ");
    fgets(str, SHM_SIZE, stdin);

    printf("Data written in memory: %s\n", str);
    shmdt(str);  // 分离共享内存

    return 0;
}
​

1.2 读取共享内存

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>

#define SHM_SIZE 1024  // 共享内存大小

int main() {
    key_t key = ftok("shmfile", 65);  // 生成唯一键值
    int shmid = shmget(key, SHM_SIZE, 0666|IPC_CREAT);  // 获取共享内存ID
    char *str = (char*) shmat(shmid, (void*)0, 0);  // 连接共享内存

    printf("Data read from memory: %s\n", str);
    shmdt(str);  // 分离共享内存
    shmctl(shmid, IPC_RMID, NULL);  // 销毁共享内存

    return 0;
}
​

1.3 相关指令

  • ipcs:显示当前系统的IPC设施状态。
  • ipcrm:删除指定的IPC对象。

二、消息队列

消息队列允许进程以消息的形式进行通信,每个消息都有一个类型标识符。消息队列的相关系统调用包括 msggetmsgsndmsgrcvmsgctl

2.1 发送消息

#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct mesg_buffer {
    long mesg_type;
    char mesg_text[100];
} message;

int main() {
    key_t key = ftok("msgfile", 65);  // 生成唯一键值
    int msgid = msgget(key, 0666 | IPC_CREAT);  // 创建消息队列

    message.mesg_type = 1;
    printf("Write Data: ");
    fgets(message.mesg_text, 100, stdin);

    msgsnd(msgid, &message, sizeof(message), 0);  // 发送消息

    printf("Data send is : %s\n", message.mesg_text);

    return 0;
}
​

2.2 接收消息

#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct mesg_buffer {
    long mesg_type;
    char mesg_text[100];
} message;

int main() {
    key_t key = ftok("msgfile", 65);  // 生成唯一键值
    int msgid = msgget(key, 0666 | IPC_CREAT);  // 获取消息队列ID

    msgrcv(msgid, &message, sizeof(message), 1, 0);  // 接收消息

    printf("Data Received is : %s\n", message.mesg_text);

    msgctl(msgid, IPC_RMID, NULL);  // 销毁消息队列

    return 0;
}
​

2.3 相关指令

  • ipcs -q:显示当前系统的消息队列。
  • ipcrm -q <msgid>:删除指定的消息队列。

三、信号量

信号量是用于进程同步的IPC机制。信号量的相关系统调用包括 semgetsemopsemctl

3.1 创建和初始化信号量

#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

int main() {
    key_t key = ftok("semfile", 65);  // 生成唯一键值
    int semid = semget(key, 1, 0666 | IPC_CREAT);  // 创建信号量集

    union semun sem_union;
    sem_union.val = 1;
    semctl(semid, 0, SETVAL, sem_union);  // 初始化信号量

    return 0;
}
​

3.2 P操作和V操作

#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>

void sem_op(int semid, int op) {
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = op;
    sb.sem_flg = 0;
    semop(semid, &sb, 1);
}

int main() {
    key_t key = ftok("semfile", 65);  // 生成唯一键值
    int semid = semget(key, 1, 0666);  // 获取信号量ID

    printf("Waiting for semaphore...\n");
    sem_op(semid, -1);  // P操作
    printf("Enter critical section...\n");

    // 进入临界区
    sleep(5);  // 模拟临界区操作
    printf("Leaving critical section...\n");

    sem_op(semid, 1);  // V操作

    return 0;
}
​

3.3 相关指令

  • ipcs -s:显示当前系统的信号量集。
  • ipcrm -s <semid>:删除指定的信号量集。

四、小项目:生产者-消费者问题

4.1 生产者代码

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define SHM_SIZE 1024

void sem_op(int semid, int op) {
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = op;
    sb.sem_flg = 0;
    semop(semid, &sb, 1);
}

int main() {
    key_t key = ftok("shmfile", 65);
    int shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);
    char *str = (char*) shmat(shmid, (void*)0, 0);

    key_t sem_key = ftok("semfile", 65);
    int semid = semget(sem_key, 1, 0666 | IPC_CREAT);
    union semun sem_union;
    sem_union.val = 1;
    semctl(semid, 0, SETVAL, sem_union);

    while (1) {
        sem_op(semid, -1);
        printf("Write Data: ");
        fgets(str, SHM_SIZE, stdin);
        sem_op(semid, 1);
        sleep(1);
    }

    shmdt(str);
    shmctl(shmid, IPC_RMID, NULL);
    semctl(semid, 0, IPC_RMID);

    return 0;
}
​

4.2 消费者代码

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define SHM_SIZE 1024

void sem_op(int semid, int op) {
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = op;
    sb.sem_flg = 0;
    semop(semid, &sb, 1);
}

int main() {
    key_t key = ftok("shmfile", 65);
    int shmid = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);
    char *str = (char*) shmat(shmid, (void*)0, 0);

    key_t sem_key = ftok("semfile", 65);


 int semid = semget(sem_key, 1, 0666 | IPC_CREAT);

    while (1) {
        sem_op(semid, -1);
        printf("Data read from memory: %s\n", str);
        sem_op(semid, 1);
        sleep(1);
    }

    shmdt(str);
    shmctl(shmid, IPC_RMID, NULL);
    semctl(semid, 0, IPC_RMID);

    return 0;
}
​

分析说明表

IPC机制 描述
共享内存 允许多个进程共享同一块内存,速度最快,但需要同步机制防止数据冲突。
消息队列 通过消息形式在进程间传递数据,适合异步通信,支持消息优先级。
信号量 用于进程间同步,控制对公共资源的访问,通过P操作和V操作实现。
生产者-消费者 一个典型的同步问题,通过共享内存和信号量实现生产者和消费者的协作。

思维导图

进程间通信
|
|-- 共享内存
|   |-- 创建和附加共享内存
|   |-- 读取共享内存
|   |-- 相关指令
|
|-- 消息队列
|   |-- 发送消息
|   |-- 接收消息
|   |-- 相关指令
|
|-- 信号量
|   |-- 创建和初始化信号量
|   |-- P操作和V操作
|   |-- 相关指令
|
|-- 生产者-消费者
|   |-- 生产者代码
|   |-- 消费者代码
|
|-- 分析说明表
​

通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。

目录
相关文章
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
2029 14
|
9月前
|
Linux 数据安全/隐私保护
Linux文件权限调整:chmod指令解析
在日常使用或系统管理中,对 `chmod`的熟练应用是提高工作效率和维持系统稳定性的关键。掌握如何给予或限制权限是每个Linux使用者都应该具备的技能。
616 17
|
9月前
|
移动开发 Linux Windows
Linux常用基本指令
对Linux中常用命令,包括文件创建与销毁,压缩与打包,查看搜索文件的方式等指令的介绍
291 1
|
消息中间件 Linux
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
525 48
|
10月前
|
存储 人工智能 Unix
Linux常见指令汇总
最常见的就是 ll (为ls -l的省略)
375 0
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
1278 5
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
687 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。
下一篇
开通oss服务