在Linux系统中,进程间通信(IPC)是实现不同进程之间数据交换的关键机制。以下是一些常用的Linux IPC方法,以及如何实现高效数据交换的建议:
管道是一种半双工的通信方式,通常用于父子进程之间的通信。
pipe()
系统调用创建,只能在具有亲缘关系的进程间使用。mkfifo()
系统调用创建,可以在任意进程间使用。#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
int fd[2];
char buffer[1024];
// 创建无名管道
if (pipe(fd) == -1) {
perror("pipe");
return 1;
}
// 写入数据
write(fd[1], "Hello, World!", 13);
// 读取数据
read(fd[0], buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
close(fd[0]);
close(fd[1]);
return 0;
}
消息队列允许进程以消息的形式交换数据,支持多对多的通信模式。
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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);
struct msg_buffer message;
message.msg_type = 1;
strcpy(message.msg_text, "Hello, Message Queue!");
// 发送消息
msgsnd(msgid, &message, sizeof(message.msg_text), 0);
// 接收消息
msgrcv(msgid, &message, sizeof(message.msg_text), 1, 0);
printf("Received: %s\n", message.msg_text);
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
共享内存是最快的IPC方法之一,因为它避免了内核态和用户态之间的数据复制。
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
key_t key = ftok("shmfile", 65);
int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
char *str = (char*) shmat(shmid, (void*)0, 0);
if (str == (char*)(-1)) {
perror("shmat");
exit(1);
}
strcpy(str, "Hello, Shared Memory!");
printf("String in shared memory: %s\n", str);
shmdt(str);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
信号量用于进程同步,确保多个进程对共享资源的互斥访问。
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
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);
// P操作(等待信号量)
struct sembuf sb = {0, -1, SEM_UNDO};
semop(semid, &sb, 1);
printf("Semaphore value: %d\n", semctl(semid, 0, GETVAL, arg));
// V操作(释放信号量)
sb.sem_op = 1;
semop(semid, &sb, 1);
semctl(semid, 0, IPC_RMID, arg);
return 0;
}
通过合理选择和使用这些IPC机制,并遵循上述建议,可以实现高效的进程间数据交换。