📜  进程间通信-概述(1)

📅  最后修改于: 2023-12-03 15:41:55.665000             🧑  作者: Mango

进程间通信-概述

在多进程编程中,进程之间需要相互通信,以完成数据共享、协同工作等目的。即便是在单一计算机中,进程间通信也是必要的。在操作系统层面,进程间通信主要通过管道、消息队列、共享内存、信号量、套接字等方式实现。以下是介绍这些方式的详细内容。

管道

管道是一种最基本的进程间通信方式。它可以实现两个进程之间的单向通信。在Linux系统中,管道可以用pipe函数进行创建。

例如:

int fd[2];
if (pipe(fd) == -1) {
    // 失败处理
}

创建成功后,fd[0]用于从管道读取数据,fd[1]用于向管道写入数据。这种方式的局限性在于,只能在具有亲缘关系的进程之间使用。

消息队列

消息队列是一种进程间通信的方式,它利用链表数据结构实现。消息队列通常用于相互独立的进程之间通信,可以完全避免由于进程间资源争夺而导致的协调问题。

例如,在Linux系统中,我们可以用msgget函数创建消息队列:

key_t key;
int msgid;
struct msgbuf {
    long mtype;
    char mtext[256];
} msg;

if ((key = ftok(".", 'a')) < 0) {
    // 失败处理
}
if ((msgid = msgget(key, IPC_CREAT|0666)) < 0) {
    // 失败处理
}

在创建消息队列之后,可以使用msgsnd函数向消息队列添加消息,msgrcv函数从消息队列中取出消息。

共享内存

共享内存是指在两个进程之间共享内存区域的一种进程间通信方式。使用共享内存通信的优点主要在于它可以提供非常快速的数据传输,但同时也增加了设计进程同步的复杂性。

例如,在使用Linux系统中,我们可以使用shmat函数在进程中创建共享内存:

key_t key;
int shmid;
char *shm = NULL;

if ((key = ftok(".", 'a')) < 0) {
    // 失败处理
}
if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT|0666)) == -1) {
    // 失败处理
}
if ((shm = shmat(shmid, NULL, 0)) == (void *)-1) {
    // 失败处理
}

创建成功之后,我们可以使用shmaddr来访问共享内存中的数据。

信号量

信号量是一种用于进程间同步的一种机制。它被用于协调两个进程之间的操作顺序或是共享数据,或者用于预防两个或多个进程同时修改某个共享资源所带来的问题。

例如,在Linux系统中,我们可以使用semget函数创建信号量:

key_t ipc_key;
int semid;
if ((ipc_key = ftok(".", 'a')) < 0) {
    // 失败处理
}
if ((semid = semget(ipc_key, 1, IPC_CREAT|0666)) == -1) {
    // 失败处理
}

在创建成功之后,我们可以使用semop函数来对信号量进行操作。

套接字

套接字是Linux提供的一种进程间基于网络的通信方式。它对进程间通信的方式进行了进一步的封装。使用套接字可以实现在不同计算机中的进程间通信。

例如,在C++中,我们可以使用socket创建一个套接字:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

返回一个套接字描述符用于访问该套接字。之后可以使用bind函数将套接字与主机和端口绑定。

以上五种进程间通信方式中,每种方式都有着其自身的优缺点。根据不同的使用场景,我们需要选择合适的通信方式以完成更加高效的进程间通信。