实现进程间通信的几种方式

实现进程间通信的几种方式

一. 传统的进程间通信 - 管道文件

管道是 UNIX 系统中最古老的进程间通信技术。早期的管道是半双工通信,现有的系统管道是全双工通信。管道是一种特殊的文件,数据在文件中是流动的,读取之后自动消失,如果文件中没有数据则会阻塞。

1. 有名管道

有名管道基于有文件名的管道文件进行通信。

编程模型
  • 进程 A

    • 创建管道
    • 打开管道(写)
    • 写数据
    • 关闭管道
    • 删除管道
  • 进程 B

    • 打开管道(读)
    • 读数据
    • 关闭管道
创建有名管道文件
  1. 命令:mkfifo

  2. 函数:

    int mkfifo(const char *pathname, mode_t mode);
    
    • 功能:创建有名管道
    • pathname:管道文件路径
    • mode:管道文件权限(如 0664)

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ca7cc69bfb5942079df22f3c56310464.png

代码实现

进程 A

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, const char* argv[]) {
    if (mkfifo("fifo", 0644)) {
        perror("mkfifo");
        return -1;
    }
    int fd = open("fifo", O_WRONLY);
    if (fd < 0) {
        perror("open");
        unlink("fifo");
        return -1;
    }
    char buf[256] = {};
    for (;;) {
        printf(">>>>>>>>");
        fgets(buf, sizeof(buf), stdin);
        write(fd, buf, strlen(buf));
        if (0 == strncmp("quit", buf, 4)) {
            printf("quit\n");
            break;
        }
    }
    close(fd);
    usleep(1000);
    unlink("fifo");
    return 0;
}

进程 B

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, const char* argv[]) {
    int fd = open("fifo", O_RDONLY);
    if (fd < 0) {
        perror("open");
        return -1;
    }
    char buf[1024] = {};
    int n = read(fd, buf, sizeof(buf));
    while (n > 0) {
        write(1, buf, n);
        n = read(fd, buf, sizeof(buf));
    }
    close(fd);
    return 0;
}

2. 匿名管道

匿名管道只适合通过 fork 创建的父子进程之间通信。

函数
int pipe(int pipefd[2]);
  • pipefd[0] 用于读
  • pipefd[1] 用于写
编程模型
  • 父进程

    • 获取一对 fd
    • 创建子进程
    • 关闭读
    • 写数据
    • 关闭写
  • 子进程

    • 共享一对 fd
    • 关闭写
    • 读数据
    • 关闭读

在这里插入图片描述

代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int fd[2];
    if (pipe(fd) == -1) {
        perror("pipe");
        return 1;
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        return 1;
    }

    if (pid > 0) {
        // 父进程
        close(fd[0]);
        for (;;) {
            char buf[256];
            printf("请输入要发送的消息:");
            fgets(buf, sizeof(buf), stdin);
            buf[strcspn(buf, "\n")] = 0;
            write(fd[1], buf, strlen(buf) + 1);
            if (strcmp(buf, "quit") == 0) break;
        }
        close(fd[1]);
    } else {
        // 子进程
        close(fd[1]);
        for (;;) {
            char buf[256];
            ssize_t bytesRead = read(fd[0], buf, sizeof(buf));
            if (bytesRead > 0) {
                printf("收到消息:%s\n", buf);
                if (strcmp(buf, "quit") == 0) break;
            } else {
                break;
            }
        }
        close(fd[0]);
    }
    return 0;
}

二. XSI 进程间通信

XSI 是 X/Open 公司制定的用于进程间通信的系统接口。

共享内存

共享内存允许多个进程共享一块内存,由内核负责协调管理。

函数
  • 创建/获取共享内存:

    int shmget(key_t key, size_t size, int shmflg);
    
  • 映射共享内存:

    void *shmat(int shmid, const void *shmaddr, int shmflg);
    
  • 取消映射:

    int shmdt(const void *shmaddr);
    
  • 控制共享内存:

    int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    
编程模型
  • 进程 A

    • 创建共享内存
    • 映射共享内存
    • 写数据并通知其他进程
    • 收到通知并读数据
    • 取消映射
    • 删除共享内存
  • 进程 B

    • 获取共享内存
    • 映射共享内存
    • 收到通知并读数据
    • 写数据并通知其他进程
    • 取消映射

在这里插入图片描述

代码实现

进程 A

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

char* shm;

void sigint(int num) {
    printf("已收到信号\n");
    printf("%s\n", shm);
}

int main(int argc, const char* argv[]) {
    printf("进程ID为:%u\n", getpid());

    // 创建共享内存
    int shmid = shmget(ftok(".", 110), 4096, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    // 映射共享内存
    shm = (char*)shmat(shmid, NULL, 0);
    if (shm == (void*)-1) {
        perror("shmat");
        shmctl(shmid, IPC_RMID, NULL);
        return 1;
    }

    signal(SIGRTMIN, sigint);

    // 写入数据并通知其他进程
    pid_t pid = 0;
    printf("请输入与我通信的进程号:");
    scanf("%d", &pid);
    for (;;) {
        printf(">>>>>>");
        scanf("%s", shm);
        kill(pid, SIGRTMIN);
        if (0 == strcmp(shm, "quit")) {
            printf("通信结束\n");
            break;
        }
    }

    // 取消映射
    shmdt(shm);
    // 删除共享内存
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

进程 B

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <string.h>

char *shm;

void sigint(int num) {
    printf("已收到信号\n");
    printf("%s\n", shm);
}

int main(int argc, const char* argv[]) {
    // 打印出进程号
    pid_t pid = getpid();
    printf("进程ID为:%u\n", pid);

    // 获取共享内存
    int shmid = shmget(ftok(".", 110), 4096, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    // 映射共享内存
    shm = (char*)shmat(shmid, NULL, 0);
    if (shm == (void*)-1) {
        perror("shmat");
        shmctl(shmid, IPC_RMID, NULL);
        return 1;
    }

    // 收到通知并读取数据
    signal(SIGRTMIN, sigint);

    // 写入数据并通知其他进程
    pid_t pids = 0;
    printf("请输入与我通信的进程号:");
    scanf("%u", &pids);
    for (;;) {
        printf(">>>>>>");
        scanf("%s", shm);
        kill(pids, SIGRTMIN);
        if (0 == strcmp(shm, "quit")) {
            printf("通信结束\n");
            break;
        }
    }

    // 取消映射
    shmdt(shm);
    return 0;
}
  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android进程间通信(Inter-process Communication, IPC)是指在不同进程之间进行数据交互和通信的方法。Android提供了多种方式实现进程间通信,以下是常用的几种方式: 1. Binder机制:Binder是一种跨进程通信技术,它基于Linux内核提供的Binder驱动。通过Binder,我们可以将一个Service注册为Binder服务,其他进程可以通过Binder进行远程调用,实现进程间的通信。 2. 文件共享:进程可以通过共享文件的方式实现通信。一个进程将数据写入文件,其他进程读取该文件数据,从而实现进程间的信息传递。 3. Socket通信:可以使用Socket套接字进行进程间通信。一个进程作为服务器,另一个进程作为客户端,通过Socket建立连接进行数据交互。 4. ContentProvider:ContentProvider是Android中用于实现进程间共享数据的一种组件。通过ContentProvider,一个进程可以提供数据给其他进程进行读写操作。 5. BroadcastReceiver:广播是一种常见的进程间通信方式。一个进程发送广播消息,其他进程通过注册相应的广播接收器来接收并处理广播消息。 6. Messenger:Messenger是一种轻量级的进程间通信方式。通过Messenger,一个进程可以发送消息给另一个进程,实现进程间的通信。 以上是常用的几种Android进程间通信方式,开发者可以根据具体需求选择合适的方式实现进程间通信
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值