深入了解Linux IPC

一、进程间通信概述

进程间通信,即Inter-Process Communication(IPC),是指不同进程之间进行信息交换和共享的机制。在Linux系统下,IPC有多种方法,包括管道、套接字、消息队列、共享内存等。

管道:是一种单向通信机制,只能在父子进程之间共享数据,并且只能用于有亲缘关系的进程间通信。使用C语言实现的例子:

#include <stdio.h>
#include <unistd.h>

#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1

int main(void) {
    char write_msg[BUFFER_SIZE] = "Hello, world!";
    char read_msg[BUFFER_SIZE];
    int fd[2];
    pid_t pid;

    if (pipe(fd) == -1) {
        fprintf(stderr, "Pipe failed");
        return 1;
    }

    pid = fork();

    if (pid  0) {
        close(fd[READ_END]);
        write(fd[WRITE_END], write_msg, strlen(write_msg)+1);
        close(fd[WRITE_END]);
    }
    else {
        close(fd[WRITE_END]);
        read(fd[READ_END], read_msg, BUFFER_SIZE);
        printf("Received message: %s\n", read_msg);
        close(fd[READ_END]);
    }

    return 0;
}

套接字:是一种双向通信机制,可以在不同的进程之间进行信息交换。可以分为面向连接(TCP)和无连接(UDP)套接字。使用Python实现的例子:

import socket

HOST = '127.0.0.1'
PORT = 12345

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen(1)
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

消息队列:是内核维护的一种队列,进程可以在队列中发送和接收消息。使用C语言实现的例子:

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

#define MSGSZ     128

typedef struct msgbuf {
    long mtype;
    char mtext[MSGSZ];
} message_buf;

int main() {
    int msqid;
    key_t key;
    message_buf rbuf;
    size_t buflen;

    key = ftok("msgq.txt", 'A');
    msqid = msgget(key, 0666 | IPC_CREAT);

    rbuf.mtype = 1;
    sprintf(rbuf.mtext, "Hello, world!");
    buflen = strlen(rbuf.mtext) + 1;

    msgsnd(msqid, &rbuf, buflen, IPC_NOWAIT);

    msgrcv(msqid, &rbuf, MSGSZ, 1, 0);
    
    printf("Received message: %s\n", rbuf.mtext);

    msgctl(msqid, IPC_RMID, NULL);

    return 0;
}

共享内存:是多个进程共享同一块物理内存的机制。使用C语言实现的例子:

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

#define SHMSZ     27

int main() {
    int shmid;
    key_t key;
    char *shm, *s;

    key = ftok("shmfile", 'A');

    shmid = shmget(key, SHMSZ, 0666 | IPC_CREAT);

    shm = shmat(shmid, NULL, 0);

    s = shm;
    for (char c = 'a'; c <= 'z'; c++) {
        *s++ = c;
    }
    *s = '\0';

    while (*shm != '*') {
        sleep(1);
    }

    shmdt(shm);

    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

二、信号量机制

信号量(Semaphore)是一种保证多个进程之间互斥访问共享资源的机制。多个进程可以在信号量上进行等待和唤醒操作,并互相通知。在Linux系统下,信号量可以使用System V IPC 或 POSIX IPC实现。

System V IPC实现信号量,使用C语言实现的例子:

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

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

int main() {
    int sem_id;
    key_t key;
    struct sembuf sembuf;
    union semun arg;

    key = ftok("semfile", 'A');
    sem_id = semget(key, 1, 0666 | IPC_CREAT);

    arg.val = 1;
    semctl(sem_id, 0, SETVAL, arg);

    sembuf.sem_num = 0;
    sembuf.sem_op = -1;
    sembuf.sem_flg = SEM_UNDO;
    semop(sem_id, &sembuf, 1);

    printf("Semaphore locked!\n");

    sembuf.sem_op = 1;
    semop(sem_id, &sembuf, 1);

    printf("Semaphore unlocked!\n");

    semctl(sem_id, 0, IPC_RMID);

    return 0;
}

POSIX IPC也可以实现信号量机制,使用C语言实现的例子:

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

#define SEM_NAME "/mysem"

int main() {
    sem_t *sem;

    sem = sem_open(SEM_NAME, O_CREAT, 0666, 1);

    sem_wait(sem);
    printf("Semaphore locked!\n");
    sem_post(sem);
    printf("Semaphore unlocked!\n");

    sem_unlink(SEM_NAME);
    sem_close(sem);

    return 0;
}

三、共享内存机制

共享内存是一种高效的进程间通信机制,多个进程可以将同一块物理内存映射到自己的地址空间中,实现共享。在Linux系统下,共享内存可以使用System V IPC或 POSIX IPC实现。

System V IPC实现共享内存,使用C语言实现的例子:

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

#define SHMSZ     27

int main() {
    int shmid;
    key_t key;
    char *shm, *s;

    key = ftok("shmfile", 'A');

    shmid = shmget(key, SHMSZ, 0666 | IPC_CREAT);

    shm = shmat(shmid, NULL, 0);

    s = shm;
    for (char c = 'a'; c <= 'z'; c++) {
        *s++ = c;
    }
    *s = '\0';

    while (*shm != '*') {
        sleep(1);
    }

    shmdt(shm);

    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

POSIX IPC也可以实现共享内存机制,使用C语言实现的例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>

#define SHMSZ     27

int main() {
    int fd;
    char *shm, *s;

    fd = shm_open("shmfile", O_CREAT | O_RDWR, 0666);
    ftruncate(fd, SHMSZ);

    shm = mmap(NULL, SHMSZ, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    s = shm;
    for (char c = 'a'; c <= 'z'; c++) {
        *s++ = c;
    }
    *s = '\0';

    while (*shm != '*') {
        sleep(1);
    }

    munmap(shm, SHMSZ);

    shm_unlink("shmfile");

    return 0;
}

四、消息队列机制

消息队列是一种专门用于进程间通信的机制,多个进程可以通过消息队列发送和接收消息。在Linux系统下,消息队列可以使用System V IPC或 POSIX IPC实现。

System V IPC实现消息队列,使用C语言实现的例子:

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

#define MSGSZ     128

typedef struct msgbuf {
    long mtype;
    char mtext[MSGSZ];
} message_buf;

int main() {
    int msqid;
    key_t key;
    message_buf rbuf;
    size_t buflen;

    key = ftok("msgq.txt", 'A');
    msqid = msgget(key, 0666 | IPC_CREAT);

    rbuf.mtype = 1;
    sprintf(rbuf.mtext, "Hello, world!");
    buflen = strlen(rbuf.mtext) + 1;

    msgsnd(msqid, &rbuf, buflen, IPC_NOWAIT);

    msgrcv(msqid, &rbuf, MSGSZ, 1, 0);
    
    printf("Received message: %s\n", rbuf.mtext);

    msgctl(msqid, IPC_RMID, NULL);

    return 0;
}

POSIX IPC也可以实现消息队列机制,使用C语言实现的例子:

#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>

#define QUEUE_NAME "/test_queue"
#define MSGSZ     128

int main() {
    mqd_t qd;
    char msgbuf[MSGSZ];
    struct mq_attr attr;

    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MSGSZ;
    attr.mq_curmsgs = 0;

    qd = mq_open(QUEUE_NAME, O_CREAT | O_RDWR, 0666, &attr);

    mq_send(qd, "Hello, world!", 13, 0);

    mq_receive(qd, msgbuf, MSGSZ, NULL);

    printf("Received message: %s\n", msgbuf);

    mq_close(qd);
    mq_unlink(QUEUE_NAME);

    return 0;
}

五、总结

Linux IPC提供了多种机制用于进程间通信,包括管道、套接字、消息队列、共享内存和信号量。任何一种IPC机制都可以被应用于相应的场景中。

原创文章,作者:SDTSW,如若转载,请注明出处:https://www.506064.com/n/368220.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
SDTSWSDTSW
上一篇 2025-04-12 01:13
下一篇 2025-04-12 01:13

相关推荐

  • 如何在Linux中添加用户并修改配置文件

    本文将从多个方面详细介绍在Linux系统下如何添加新用户并修改配置文件 一、添加新用户 在Linux系统下创建新用户非常简单,只需使用adduser命令即可。使用以下命令添加新用户…

    编程 2025-04-27
  • 如何解决linux jar包 invalid or corrupt jarfile问题

    对于许多开发人员和系统管理员在Linux环境下使用Java开发过程中遇到的一个常见的问题是 invalid or corrupt jarfile(无效或损坏的jar文件)错误。当您…

    编程 2025-04-27
  • 在Linux上安装JRE并配置环境变量

    本文将从以下几个方面为您详细阐述如何在Linux系统上,通过自己账户安装JRE,并且配置环境变量。 一、安装JRE 在进行安装前,我们需要下载JRE的安装包并解压,可以从官方网站下…

    编程 2025-04-27
  • GTKAM:Linux下的照片管理器

    GTKAM是用于Linux操作系统的一款照片管理器,它支持多种相机及存储设备,并提供了一系列强大的工具,让用户可以方便地浏览、管理、编辑和导出照片。本文将从多个方面对GTKAM进行…

    编程 2025-04-27
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • 深入解析Vue3 defineExpose

    Vue 3在开发过程中引入了新的API `defineExpose`。在以前的版本中,我们经常使用 `$attrs` 和` $listeners` 实现父组件与子组件之间的通信,但…

    编程 2025-04-25
  • 深入理解byte转int

    一、字节与比特 在讨论byte转int之前,我们需要了解字节和比特的概念。字节是计算机存储单位的一种,通常表示8个比特(bit),即1字节=8比特。比特是计算机中最小的数据单位,是…

    编程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什么是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一个内置小部件,它可以监测数据流(Stream)中数据的变…

    编程 2025-04-25
  • 深入探讨OpenCV版本

    OpenCV是一个用于计算机视觉应用程序的开源库。它是由英特尔公司创建的,现已由Willow Garage管理。OpenCV旨在提供一个易于使用的计算机视觉和机器学习基础架构,以实…

    编程 2025-04-25

发表回复

登录后才能评论