通信方法 | 优点 | 缺点 |
---|
管道(Pipes) | 实现简单,适用于父子进程通信 | 单向通信,不适合双向通信;不适合大数据量传输;通信效率较低 |
信号(Signals) | 异步通信,可以在任何时刻通知进程 | 通信内容受限,主要用于进程间的同步和控制 |
消息队列 | 支持异步处理,可以进行数据存储 | 通信不及时,数据大小有限制 |
共享内存 | 通信效率高,适合大量数据传输 | 需要同步机制以防数据冲突,可能导致地址冲突 |
信号量 | 用于进程间同步和互斥控制 | 不当使用易造成死锁 |
套接字(Sockets) | 适用于网络通信,支持不同主机间的进程通信 | 通信开销较大 |
内存映射文件 | 可以实现高效的共享内存通信,减少数据拷贝开销 | 需要同步机制,管理复杂 |
1.管道(Pipes)
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int fd[2]; // 文件描述符数组
pid_t pid;
if (pipe(fd) == -1) {
perror("Pipe");
return 1;
}
pid = fork();
if (pid < 0) {
perror("Fork");
return 1;
}
if (pid == 0) { // 子进程
close(fd); // 关闭读端
write(fd[1], "Hello, World!", 13);
close(fd[1]);
} else { // 父进程
close(fd[1]); // 关闭写端
char msg[100];
read(fd, msg, sizeof(msg) - 1);
msg[sizeof(msg) - 1] = '\0'; // 确保字符串以null结束
printf("Parent received: %s\n", msg);
close(fd);
}
wait(NULL); // 等待子进程结束
return 0;
}
2. 信号(Signals)
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler(int sig) {
printf("Caught signal %d\n", sig);
}
int main() {
signal(SIGINT, handler); // 注册信号处理器
while(1);
return 0;
}
3. 消息队列
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
struct my_msgbuf {
long mtype;
char mtext[100];
};
int main() {
key_t key = ftok(".", 'M');
int msqid = msgget(key, 0666 | IPC_CREAT);
if (msqid == -1) {
perror("msgget");
return 1;
}
struct my_msgbuf msg;
msg.mtype = 1;
strcpy(msg.mtext, "Hello, Message queue!");
if (msgsnd(msqid, &msg, strlen(msg.mtext) + 1, 0) == -1) {
perror("msgsnd");
return 1;
}
if (msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0) == -1) {
perror("msgrcv");
return 1;
}
printf("Received message: %s\n", msg.mtext);
msgctl(msqid, IPC_RMID, NULL); // 清除消息队列
return 0;
}
4. 共享内存
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
int main() {
key_t key = ftok(".", 'S');
int shmid = shmget(key, 100, 0666 | IPC_CREAT);
char *data = shmat(shmid, NULL, 0);
strcpy(data, "Hello, Shared Memory!");
printf("Data in shared memory: %s\n", data);
shmdt(data);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
5. 信号量
#include <iostream>
#include <semaphore.h>
#include <thread>
#include <chrono>
sem_t sem; // POSIX semaphore
void increment() {
sem_wait(&sem); // 等待信号量
std::cout << "Resource accessed by thread " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
sem_post(&sem); // 释放信号量
}
int main() {
if (sem_init(&sem, 0, 1) == -1) {
std::cerr << "Semaphore initialization failed" << std::endl;
return 1;
}
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
sem_destroy(&sem); // 销毁信号量
return 0;
}
6.套接字(Sockets)
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
void handle_client(int client_socket) {
char buffer[1024];
memset(buffer, '\0', sizeof(buffer));
int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
std::cout << "Received: " << buffer << std::endl;
send(client_socket, "Hello, Client!", 15, 0);
}
close(client_socket);
}
int main() {
int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == -1) {
std::cerr << "Socket creation failed" << std::endl;
return 1;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
std::cerr << "Binding failed" << std::endl;
return 1;
}
if (listen(listen_socket, 5) == -1) {
std::cerr << "Listening failed" << std::endl;
return 1;
}
while (true) {
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
int client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &addr_len);
if (client_socket != -1) {
std::cout << "New client connected" << std::endl;
std::thread(handle_client, client_socket).detach();
}
}
close(listen_socket);
return 0;
}
7.内存映射文件
#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int file_desc = open("testfile", O_RDWR|O_CREAT, 0644);
if (file_desc == -1) {
std::cerr << "File opening failed" << std::endl;
return 1;
}
if (ftruncate(file_desc, 100) == -1) {
std::cerr << "File truncation failed" << std::endl;
return 1;
}
char *data = (char *)mmap(NULL, 100, PROT_READ|PROT_WRITE, MAP_SHARED, file_desc, 0);
if (data == MAP_FAILED) {
std::cerr << "Memory mapping failed" << std::endl;
return 1;
}
strcpy(data, "Hello, Memory Mapped File!");
munmap(data, 100);
close(file_desc);
return 0;
}