huanayun
hengtianyun
vps567
莱卡云

[Linux操作系统]探索Linux IPC进程间通信的奥秘|,Linux IPC进程间通信,揭秘Linux IPC,深入探索进程间通信的精髓

PikPak

推荐阅读:

[AI-人工智能]免翻墙的AI利器:樱桃茶·智域GPT,让你轻松使用ChatGPT和Midjourney - 免费AIGC工具 - 拼车/合租账号 八折优惠码: AIGCJOEDISCOUNT2024

[AI-人工智能]银河录像局: 国内可靠的AI工具与流媒体的合租平台 高效省钱、现号秒发、翻车赔偿、无限续费|95折优惠码: AIGCJOE

[AI-人工智能]免梯免翻墙-ChatGPT拼车站月卡 | 可用GPT4/GPT4o/o1-preview | 会话隔离 | 全网最低价独享体验ChatGPT/Claude会员服务

[AI-人工智能]边界AICHAT - 超级永久终身会员激活 史诗级神器,口碑炸裂!300万人都在用的AI平台

本文深入探讨Linux操作系统进程间通信(IPC)机制。介绍了多种IPC方式,包括管道、消息队列、共享内存、信号量及套接字等,解析了它们的工作原理和应用场景。通过实例演示了如何在不同进程间高效传输数据,强调了IPC在多进程编程中的重要性。文章旨在帮助开发者理解并掌握Linux IPC技术,提升系统开发和维护能力。

本文目录导读:

  1. Linux IPC概述
  2. 管道(Pipe)
  3. 命名管道(Named Pipe)
  4. 消息队列(Message Queue)
  5. 信号量(Semaphore)
  6. 共享内存(Shared Memory)
  7. 套接字(Socket)
  8. 信号(Signal)

在多任务操作系统中,进程间通信(Inter-Process Communication,IPC)是确保不同进程能够高效协作和数据交换的关键技术,Linux作为广泛使用的开源操作系统,提供了多种IPC机制,以满足不同场景下的通信需求,本文将深入探讨Linux IPC的各种方式及其应用场景,帮助读者全面理解这一重要技术。

Linux IPC概述

进程间通信是指在不同进程之间传递数据和信号的过程,在Linux系统中,IPC机制不仅支持同一主机上的进程通信,还支持跨网络的进程通信,Linux提供的IPC方式主要包括:

1、管道(Pipe)

2、命名管道(Named Pipe)

3、消息队列(Message Queue)

4、信号量(Semaphore)

5、共享内存(Shared Memory)

6、套接字(Socket)

7、信号(Signal)

管道(Pipe)

管道是Linux中最简单的IPC机制,适用于父子进程或兄弟进程间的单向数据传输,管道通过系统调用pipe()创建,返回两个文件描述符,一个用于读操作,另一个用于写操作。

int pipe(int pipefd[2]);

示例代码:

#include <stdio.h>
#include <unistd.h>
int main() {
    int pipefd[2];
    pid_t cpid;
    char buf;
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) { // 子进程
        close(pipefd[0]); // 关闭读端
        write(pipefd[1], "Hello, world!
", 14);
        close(pipefd[1]); // 关闭写端
    } else { // 父进程
        close(pipefd[1]); // 关闭写端
        while (read(pipefd[0], &buf, 1) > 0)
            write(STDOUT_FILENO, &buf, 1);
        write(STDOUT_FILENO, "
", 1);
        close(pipefd[0]); // 关闭读端
    }
    return 0;
}

命名管道(Named Pipe)

命名管道克服了管道只能在亲缘进程间通信的局限,可以在任意进程间进行通信,通过mkfifo()系统调用创建命名管道。

int mkfifo(const char *pathname, mode_t mode);

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main() {
    const char *fifo_path = "/tmp/my_fifo";
    mkfifo(fifo_path, 0666);
    int fd = open(fifo_path, O_WRONLY);
    write(fd, "Hello, named pipe!
", 19);
    close(fd);
    return 0;
}

消息队列(Message Queue)

消息队列允许进程以消息为单位进行数据交换,支持多种消息类型,通过msgget()msgsnd()msgrcv()等系统调用进行操作。

int msgget(key_t key, int msgflg);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

示例代码:

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct message {
    long msg_type;
    char msg_text[100];
};
int main() {
    key_t key = ftok("queuefile", 65);
    int msgid = msgget(key, 0666 | IPC_CREAT);
    struct message msg;
    msg.msg_type = 1;
    strcpy(msg.msg_text, "Hello, message queue!");
    msgsnd(msgid, &msg, sizeof(msg.msg_text), 0);
    msgrcv(msgid, &msg, sizeof(msg.msg_text), 1, 0);
    printf("Received message: %s
", msg.msg_text);
    msgctl(msgid, IPC_RMID, NULL);
    return 0;
}

信号量(Semaphore)

信号量用于控制多个进程对共享资源的访问,防止资源竞争,通过semget()semop()semctl()等系统调用进行操作。

int semget(key_t key, int nsems, int semflg);
int semop(int semid, struct sembuf *sops, size_t nsops);
int semctl(int semid, int semnum, int cmd, ...);

示例代码:

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.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 u;
    u.val = 1;
    semctl(semid, 0, SETVAL, u);
    struct sembuf sops;
    sops.sem_num = 0;
    sops.sem_op = -1; // P操作
    sops.sem_flg = 0;
    semop(semid, &sops, 1);
    printf("Critical section
");
    sops.sem_op = 1; // V操作
    semop(semid, &sops, 1);
    semctl(semid, 0, IPC_RMID);
    return 0;
}

共享内存(Shared Memory)

共享内存允许多个进程共享同一块内存区域,实现高效数据交换,通过shmget()shmat()shmdt()等系统调用进行操作。

int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);

示例代码:

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main() {
    key_t key = ftok("shmfile", 65);
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    char *str = (char *) shmat(shmid, (void *) 0, 0);
    strcpy(str, "Hello, shared memory!");
    printf("Data written in memory: %s
", str);
    shmdt(str);
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}

套接字(Socket)

套接字支持跨网络进程间通信,适用于客户端-服务器模型,通过socket()bind()listen()accept()connect()等系统调用进行操作。

int socket(int domain, int type, int protocol);
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

示例代码(服务器端):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    const char *hello = "Hello from server";
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8080);
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));
    listen(server_fd, 3);
    new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
    read(new_socket, buffer, 1024);
    printf("Message from client: %s
", buffer);
    send(new_socket, hello, strlen(hello), 0);
    return 0;
}

信号(Signal)

信号是一种简单的IPC机制,用于通知接收进程某个事件已经发生,通过signal()sigaction()系统调用进行操作。

void (*signal(int signum, void (*handler)(int)))(int);
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

示例代码:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int signum) {
    printf("Received signal %d
", signum);
}
int main() {
    signal(SIGINT, signal_handler);
    while (1) {
        printf("Waiting for signal...
");
        sleep(
bwg Vultr justhost.asia racknerd hostkvm pesyun Pawns

原文链接:,转发请注明来源!