C++进程链接工具之通信器详解
什么是C++进程链接工具之通信器
C++进程链接工具之通信器(又称共享内存通信器)是一种实现进程间通信的方式。它使用共享内存的方式,允许多个进程共享同一块内存区域,并利用操作系统提供的信号量等机制,实现对共享内存的并发访问。
通信器主要由以下三个部分组成:
- 共享内存区域:即多个进程共享的内存区域,用于存储需要交换的数据。
- 读写锁:用于多个进程对共享内存的读写操作的互斥控制。
- 信号量:用于某些情况下的进程同步,如通知对方进程数据已经准备好等。
通信器的使用方法
通信器的使用主要包括以下几个步骤:
- 创建或链接共享内存区域:第一个进程需要创建共享内存区域,而后续的进程需要链接已经创建好的共享内存区域。共享内存区域的大小应该由所有进程协商确定,通常在创建时指定,并且应该足够容纳所有需要共享的数据。
- 获取读写锁:所有需要对共享内存进行读写操作的进程都需要获取读写锁。
- 进行数据交换:各进程直接进行数据交换,可以把共享内存视为一个全局变量。
- 释放读写锁:读写操作完成后,需要释放读写锁。
- 删除共享内存:通信完成后,第一个进程需要删除共享内存区域。
下面将通过两个示例说明如何使用通信器。
示例一:简单的进程间通信
假设有两个进程A和B,我们通过通信器实现它们之间的数据交换。
进程A的代码示例
#include <iostream>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
using namespace std;
int main() {
key_t key = ftok("/tmp/comm", 'a');
int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
char* data = (char*)shmat(shmid, (void*)0, 0);
sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);
while (true) {
sem_wait(full);
sem_wait(mutex);
cout << "Process A read: " << data << endl;
strcpy(data, "Hello B!");
sem_post(mutex);
sem_post(empty);
}
shmctl(shmid, IPC_RMID, 0);
sem_unlink("/tmp/comm_mutex");
sem_unlink("/tmp/comm_empty");
sem_unlink("/tmp/comm_full");
return 0;
}
进程B的代码示例
#include <iostream>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
using namespace std;
int main() {
key_t key = ftok("/tmp/comm", 'a');
int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
char* data = (char*)shmat(shmid, (void*)0, 0);
sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);
while (true) {
sem_wait(empty);
sem_wait(mutex);
strcpy(data, "Hello A!");
cout << "Process B read: " << data << endl;
sem_post(mutex);
sem_post(full);
}
shmctl(shmid, IPC_RMID, 0);
sem_unlink("/tmp/comm_mutex");
sem_unlink("/tmp/comm_empty");
sem_unlink("/tmp/comm_full");
return 0;
}
上述代码演示了进程A和进程B之间的简单通信过程。两个进程共享一个大小为1024字节的共享内存区域,其中单元格0用于进程A存储数据,单元格1用于进程B存储数据。读写锁和信号量使用了POSIX信号量库提供的相关函数。
如何运行示例代码
为了运行这个示例代码,需要在终端中执行以下命令:
$ g++ process_a.cpp -o process_a -lpthread
$ g++ process_b.cpp -o process_b -lpthread
$ ./process_a & ./process_b
代码运行后,将持续输出“Hello A!”和“Hello B!”。
示例二:使用通信器发送结构化数据
假设还是有两个进程A和B,我们需要把一个结构化的数据传送给B进程。
通信结构体定义
struct Data {
int a;
float b;
char c[20];
};
进程A的代码示例
#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include "data.h"
using namespace std;
int main() {
key_t key = ftok("/tmp/comm", 'a');
int shmid = shmget(key, sizeof(Data), 0666 | IPC_CREAT);
Data* data = (Data*)shmat(shmid, (void*)0, 0);
sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);
while (true) {
sem_wait(full);
sem_wait(mutex);
data->a++;
data->b += 0.123;
strncpy(data->c, "Hello B!", sizeof(data->c));
sem_post(mutex);
sem_post(empty);
}
shmctl(shmid, IPC_RMID, 0);
sem_unlink("/tmp/comm_mutex");
sem_unlink("/tmp/comm_empty");
sem_unlink("/tmp/comm_full");
return 0;
}
进程B的代码示例
#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include "data.h"
using namespace std;
int main() {
key_t key = ftok("/tmp/comm", 'a');
int shmid = shmget(key, sizeof(Data), 0666 | IPC_CREAT);
Data* data = (Data*)shmat(shmid, (void*)0, 0);
sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);
while (true) {
sem_wait(empty);
sem_wait(mutex);
cout << "Process B read " << data->a << ", " << data->b << ", " << data->c << endl;
sem_post(mutex);
sem_post(full);
}
shmctl(shmid, IPC_RMID, 0);
sem_unlink("/tmp/comm_mutex");
sem_unlink("/tmp/comm_empty");
sem_unlink("/tmp/comm_full");
return 0;
}
示例二演示了进程A向进程B发送结构化数据的过程。这里使用了一个自定义的Data结构体来存储数据。进程A在共享内存中修改结构体的数据,而进程B从共享内存中读取数据,然后在控制台输出。注意到这里并没有使用strcpy函数,而是直接使用了strncpy函数,为了避免溢出。
如何运行示例代码
还是运行以下命令:
$ g++ process_a.cpp -o process_a -lpthread
$ g++ process_b.cpp -o process_b -lpthread
$ ./process_a & ./process_b
在运行时请注意,如果两个进程同时输出,会产生混乱的控制台输出。可以尝试将输出重定向到文件中以便观察。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++进程链接工具之通信器详解 - Python技术站