进程间通讯(Inter-Process Communication,简称IPC)是运行在一个系统中的进程之间共享信息和数据的一种机制。在C++中,可以使用多种方法实现进程间通讯,包括管道、信号、共享内存、消息队列、套接字等。
以下是一个使用消息队列进行进程间通讯的C++示例:
#include
#include <sys/ipc.h>
#include <sys/msg.h>
#include
// 定义消息队列的键值和权限
#define MSG_KEY 12345
#define MSG_PERMS 0666
// 定义消息结构体
struct my_msg_st {
long int my_msg_type;
char text[100];
};
int main() {
int running = 1;
int msgid;
struct my_msg_st some_data;
long int msg_to_receive = 0;
// 创建消息队列
msgid = msgget(MSG_KEY, MSG_PERMS | IPC_CREAT);
if (msgid == -1) {
std::cerr << "Error creating message queue" << std::endl;
return -1;
}
// 发送消息
std::cout << "Enter text to send: ";
std::cin.getline(some_data.text, sizeof(some_data.text));
some_data.my_msg_type = 1;
if (msgsnd(msgid, &some_data, sizeof(some_data), 0) == -1) {
std::cerr << "Error sending message" << std::endl;
return -1;
}
// 接收消息
while (running) {
if (msgrcv(msgid, &some_data, sizeof(some_data),
msg_to_receive, 0) == -1) {
std::cerr << "Error receiving message" << std::endl;
return -1;
}
std::cout << "You wrote: " << some_data.text << std::endl;
std::cout << "Enter text to send: ";
std::cin.getline(some_data.text, sizeof(some_data.text));
some_data.my_msg_type = 1;
if (msgsnd(msgid, &some_data, sizeof(some_data), 0) == -1) {
std::cerr << "Error sending message" << std::endl;
return -1;
}
}
// 删除消息队列
if (msgctl(msgid, IPC_RMID, 0) == -1) {
std::cerr << "Error deleting message queue" << std::endl;
return -1;
}
return 0;
}
在上述示例中,我们创建了一个消息队列,并使用 msgsnd 函数将消息发送到队列中。然后,我们使用 msgrcv 函数从队列中接收消息。每次接收消息后,我们都会打印出消息的内容,并提示用户输入新的消息。这个示例是一个简单的基于消息队列的进程间通讯例子。
下面我们来看一下如何使用信号进行进程间通步,还是使用两个进程,其中一个进程向另一个进程发送一个信号。在 Unix 或类 Unix 系统(如 Linux)中,信号是一种常见的进程间通讯方式。进程可以接收、发送和处理信号。
这里给出一个简单的例子,首先是创建两个进程的代码片段:
#include
#include
#include
// 定义一个信号处理函数
void signal_handler(int signal_num) {
std::cout << "Received signal: " << signal_num << std::endl;
}
int main() {
// 注册信号处理函数
signal(SIGUSR1, signal_handler);
while(1) {
std::cout << "Waiting for signal..." << std::endl;
pause(); // 让进程暂停,等待信号
}
return 0;
}
这个进程会一直等待信号。现在我们来创建第二个进程,它会向第一个进程发送一个 SIGUSR1 信号:
#include
#include
int main() {
// 找到第一个进程的 PID
pid_t pid = ...; // 需要知道第一个进程的 PID
// 向第一个进程发送 SIGUSR1 信号
kill(pid, SIGUSR1);
return 0;
}
注意,在实际应用中,进程间通讯通常涉及到更复杂的同步和错误处理。例如,当使用共享内存时,需要确保每个进程在使用共享内存时都不会发生竞争条件(race condition)。这可能需要使用某种同步机制,例如锁(locks)或者信号量(semaphores)。另外,当使用 IPC 时,需要处理可能的错误,例如 IPC 失败或者进程间通信中断等。