深入了解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/zh-tw/n/368220.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
SDTSW的頭像SDTSW
上一篇 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

發表回復

登錄後才能評論