在Linux系统中,C++程序可以通过多种方式实现进程间通信(IPC)。以下是主要的IPC方法及其实现方式:
管道是最简单的IPC方式,适用于有亲缘关系的进程。
#include <unistd.h>
#include <iostream>
int main() {
int fd[2];
pipe(fd); // 创建管道
pid_t pid = fork();
if (pid == 0) { // 子进程
close(fd[1]); // 关闭写端
char buf[100];
read(fd[0], buf, sizeof(buf));
std::cout << "Child received: " << buf << std::endl;
close(fd[0]);
} else { // 父进程
close(fd[0]); // 关闭读端
const char* msg = "Hello from parent";
write(fd[1], msg, strlen(msg) + 1);
close(fd[1]);
}
return 0;
}
命名管道可用于无亲缘关系的进程间通信。
// 创建FIFO (在shell中或使用mkfifo函数)
// mkfifo myfifo
// 写入进程
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
int main() {
int fd = open("myfifo", O_WRONLY);
write(fd, "Hello FIFO", 10);
close(fd);
return 0;
}
// 读取进程
int main() {
int fd = open("myfifo", O_RDONLY);
char buf[100];
read(fd, buf, sizeof(buf));
std::cout << "Received: " << buf << std::endl;
close(fd);
return 0;
}
共享内存是最快的IPC方式,但需要同步机制。
#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>
int main() {
key_t key = ftok("shmfile", 65);
int shmid = shmget(key, 1024, 0666|IPC_CREAT);
char *str = (char*)shmat(shmid, (void*)0, 0);
std::cout << "Write data: ";
std::cin >> str;
std::cout << "Data written: " << str << std::endl;
shmdt(str);
// shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
return 0;
}
#include <sys/ipc.h>
#include <sys/msg.h>
#include <iostream>
struct msg_buffer {
long msg_type;
char msg_text[100];
};
int main() {
key_t key = ftok("progfile", 65);
int msgid = msgget(key, 0666 | IPC_CREAT);
msg_buffer message;
message.msg_type = 1;
std::cout << "Write data: ";
std::cin >> message.msg_text;
msgsnd(msgid, &message, sizeof(message), 0);
std::cout << "Data sent: " << message.msg_text << std::endl;
// 接收消息
msgrcv(msgid, &message, sizeof(message), 1, 0);
std::cout << "Data received: " << message.msg_text << std::endl;
msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
return 0;
}
用于进程同步。
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <iostream>
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);
semun sem_union;
sem_union.val = 1;
semctl(semid, 0, SETVAL, sem_union);
struct sembuf sb = {0, -1, 0}; // 锁定
semop(semid, &sb, 1);
std::cout << "Critical section" << std::endl;
sleep(5);
sb.sem_op = 1; // 解锁
semop(semid, &sb, 1);
semctl(semid, 0, IPC_RMID, sem_union); // 删除信号量
return 0;
}
可用于不同主机或同一主机上的进程通信。
// 服务器端
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
int main() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in address;
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);
int new_socket = accept(server_fd, NULL, NULL);
char buffer[1024] = {0};
read(new_socket, buffer, 1024);
std::cout << "Message: " << buffer << std::endl;
close(new_socket);
close(server_fd);
return 0;
}
// 客户端
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
send(sock, "Hello from client", 17, 0);
close(sock);
return 0;
}
每种方法都有其适用场景,选择时应考虑通信模式、性能需求、进程关系等因素。