在Linux环境下,C++程序可以使用多种方法进行进程间通信(IPC)。以下是一些常用的IPC机制:
-
管道(Pipes):
- 匿名管道(Anonymous Pipes):通常用于父子进程之间的通信。
- 命名管道(Named Pipes,FIFOs):允许无亲缘关系的进程之间进行通信。
-
信号(Signals):
- 用于通知接收进程某个事件已经发生。
-
消息队列(Message Queues):
- 允许进程发送和接收消息。
-
共享内存(Shared Memory):
- 允许多个进程访问同一块内存区域。
-
信号量(Semaphores):
- 用于进程同步,控制多个进程对共享资源的访问。
-
套接字(Sockets):
- 可以用于本地进程间通信(如Unix Domain Sockets)或网络通信。
下面是一些简单的示例代码,展示了如何在C++中使用这些IPC机制:
匿名管道
#include#include int main() { int pipefd[2]; char buffer[10]; // 创建匿名管道 if (pipe(pipefd) == -1) { perror("pipe"); return EXIT_FAILURE; } // 父进程关闭写端,子进程关闭读端 if (fork() == 0) { close(pipefd[1]); // 子进程关闭写端 read(pipefd[0], buffer, sizeof(buffer)); // 读取数据 std::cout << "Child received: " << buffer << std::endl; close(pipefd[0]); } else { close(pipefd[0]); // 父进程关闭读端 write(pipefd[1], "Hello from parent", 20); // 写入数据 close(pipefd[1]); } return EXIT_SUCCESS; }
命名管道(FIFO)
#include#include #include #include int main() { const char* fifo = "/tmp/myfifo"; mkfifo(fifo, 0666); int fd = open(fifo, O_RDWR); if (fd == -1) { perror("open"); return EXIT_FAILURE; } write(fd, "Hello FIFO", 11); char buffer[12]; read(fd, buffer, sizeof(buffer)); std::cout << "Read from FIFO: " << buffer << std::endl; close(fd); unlink(fifo); // 删除FIFO return EXIT_SUCCESS; }
共享内存
#include#include #include #include int main() { key_t key = ftok("shmfile", 65); int shmid = shmget(key, 1024, 0666|IPC_CREAT); char *str = (char*) shmat(shmid, (void*)0, 0); strcpy(str, "Hello World"); std::cout << "String in shared memory: " << str << std::endl; shmdt(str); shmctl(shmid, IPC_RMID, NULL); return EXIT_SUCCESS; }
信号量
#include#include #include 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); union semun arg; arg.val = 1; // 初始化信号量为1 semctl(semid, 0, SETVAL, arg); // 使用semop进行P操作(等待信号量) struct sembuf sb = {0, -1, SEM_UNDO}; semop(semid, &sb, 1); std::cout << "Semaphore value decreased to 0" << std::endl; // 使用semop进行V操作(释放信号量) sb.sem_op = 1; semop(semid, &sb, 1); semctl(semid, 0, IPC_RMID, arg); return EXIT_SUCCESS; }
套接字(Unix Domain Sockets)
// 服务器端 #include#include #include #include int main() { int server_fd, new_socket; struct sockaddr_un address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } address.sun_family = AF_UNIX; strncpy(address.sun_path, "/tmp/uds.sock", sizeof(address.sun_path)-1); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } read(new_socket, buffer, 1024); std::cout << "Message from client: " << buffer << std::endl; close(new_socket); close(server_fd); return EXIT_SUCCESS; } // 客户端 #include #include #include #include int main() { struct sockaddr_un serv_addr; int sock = 0; char *hello = "Hello from client"; char buffer[1024] = {0}; if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { std::cout << "\n Socket creation error \n"; return -1; } serv_addr.sun_family = AF_UNIX; strncpy(serv_addr.sun_path, "/tmp/uds.sock", sizeof(serv_addr.sun_path)-1); if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { std::cout << "\nConnection Failed \n"; return -1; } send(sock, hello, strlen(hello), 0); std::cout << "Hello message sent\n"; read(sock, buffer, 1024); std::cout << "Message from server: " << buffer << std::endl; close(sock); return 0; }
在使用这些IPC机制时,需要注意同步问题,特别是在共享内存和信号量的使用中。此外,错误处理在实际应用中也非常重要。以上代码仅为示例,实际使用时需要根据具体情况进行调整。