外贸移动端网站模板,网站建设sem账户搭建,网络推广引流是做什么的,白山市网站建设简介#xff1a; CSDN博客专家#xff0c;专注Android/Linux系统#xff0c;分享多mic语音方案、音视频、编解码等技术#xff0c;与大家一起成长#xff01; 优质专栏#xff1a;Audio工程师进阶系列【原创干货持续更新中……】#x1f680; 人生格言#xff1a; 人生… 简介 CSDN博客专家专注Android/Linux系统分享多mic语音方案、音视频、编解码等技术与大家一起成长 优质专栏Audio工程师进阶系列【原创干货持续更新中……】 人生格言 人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注Android系统攻城狮 1.前言 本篇目的理解IPC通信消息队列、管道、socket两次内存拷贝与共享内存一次内存拷贝。 2.IPC通信消息队列、管道、socket、共享内存介绍 在Linux和Android中进程间通信IPC的方式有很多种包括管道Pipe、消息队列Message Queue、共享内存Shared Memory、信号量Semaphore、套接字Socket等。其中管道、消息队列、套接字都需要进行两次内存拷贝而共享内存只需要一次内存拷贝。
1. 两次内存拷贝的IPC方式 管道Pipe 当一个进程向管道中写入数据时数据首先会被拷贝到内核缓冲区然后当另一个进程从管道中读取数据时数据会从内核缓冲区拷贝到该进程的内存空间。这就是两次内存拷贝。 消息队列Message Queue 消息队列的工作方式与管道类似数据在发送和接收时都需要经过内核缓冲区因此也需要两次内存拷贝。 套接字Socket 套接字在发送和接收数据时数据也需要经过内核缓冥区因此也需要两次内存拷贝。
2. 一次内存拷贝的IPC方式
共享内存Shared Memory 共享内存是最快的IPC方式因为进程是直接对内存进行操作数据不需要在进程和内核之间进行拷贝。但是由于多个进程可以同时操作同一块内存因此需要使用信号量等同步机制来防止数据的不一致。
3.总结 一次内存拷贝 一次内存拷贝是指数据在用户空间和内核空间之间只进行了一次拷贝。在Linux和Android中使用共享内存shared memory实现IPC通信是一种一次内存拷贝的方式。共享内存允许多个进程共享同一块物理内存因此数据被写入内核空间后其他进程可以直接在内存中读取数据避免了多次拷贝的开销。 两次内存拷贝 两次内存拷贝指数据在用户空间和内核空间之间进行了两次拷贝。在Linux和Android中使用Socket、管道pipe和消息队列message queue进行IPC通信会涉及两次内存拷贝。
3.代码实例
1.共享内存进行一次内存拷贝
#include iostream
#include sys/shm.h
#include cstringint main() {key_t key ftok(/tmp, S);int shmid shmget(key, 1024, 0666 | IPC_CREAT);char *data (char*)shmat(shmid, nullptr, 0);std::string message Hello, IPC using shared memory!;std::memcpy(data, message.c_str(), message.size());shmdt(data);shmctl(shmid, IPC_RMID, nullptr);return 0;
}2.Socket进行两次内存拷贝
// 服务器端
#include iostream
#include sys/socket.h
#include cstringint main() {int server_sock socket(AF_INET, SOCK_STREAM, 0);// 绑定和监听int client_sock accept(server_sock, nullptr, nullptr);std::string message Hello, IPC using sockets!;send(client_sock, message.c_str(), message.size(), 0);close(client_sock);close(server_sock);return 0;
}// 客户端
#include iostream
#include sys/socket.h
#include cstringint main() {int client_sock socket(AF_INET, SOCK_STREAM, 0);// 连接服务器char buffer[1024];recv(client_sock, buffer, sizeof(buffer), 0);std::cout Message received from server: buffer std::endl;close(client_sock);return 0;
}3.管道进行两次内存拷贝
#include iostream
#include unistd.h
#include cstringint main() {int pipe_fds[2];if (pipe(pipe_fds) -1) {std::cerr Failed to create pipe std::endl;return 1;}const char* message Hello, IPC using pipes!;const size_t len strlen(message);if (write(pipe_fds[1], message, len) ! static_castssize_t(len)) {std::cerr Failed to write to pipe std::endl;return 1;}char buffer[64];ssize_t bytes_read read(pipe_fds[0], buffer, sizeof(buffer));if (bytes_read -1) {std::cerr Failed to read from pipe std::endl;return 1;}std::cout Message read from pipe: std::string(buffer, bytes_read) std::endl;close(pipe_fds[0]);close(pipe_fds[1]);return 0;
}4.消息队列进行两次内存拷贝
#include iostream
#include cstring
#include sys/msg.hstruct Message {long type;char text[100];
};int main() {key_t key ftok(/tmp, Q);int msgid msgget(key, 0666 | IPC_CREAT);Message message;message.type 1;std::strcpy(message.text, Hello, IPC using message queues!);msgsnd(msgid, message, sizeof(message.text), 0);msgrcv(msgid, message, sizeof(message.text), 1, 0);std::cout Message received from message queue: message.text std::endl;msgctl(msgid, IPC_RMID, nullptr);return 0;
}5.信号量进行两次内存拷贝
#include iostream
#include sys/sem.h
#include sys/ipc.h
#include sys/types.h
#include unistd.h
#include cstringint main() {key_t key ftok(/tmp, S);int semid semget(key, 1, IPC_CREAT | 0666);if (semid -1) {std::cerr Failed to create semaphore std::endl;return 1;}sembuf acquire {0, -1, SEM_UNDO};sembuf release {0, 1, SEM_UNDO};if (semop(semid, acquire, 1) -1) {std::cerr Failed to acquire semaphore std::endl;return 1;}// Critical section - perform operations that require exclusive accessstd::string message Hello, IPC using semaphores!;// Perform operations on the shared resourceif (semop(semid, release, 1) -1) {std::cerr Failed to release semaphore std::endl;return 1;}return 0;
}