在Linux系统中,进程间通信(IPC)是指在不同进程之间传递和共享数据的方法。有多种IPC机制可供选择,每种机制都有其优缺点。以下是一些常见的Linux IPC机制及其实现数据交换的方法:
管道是一种半双工的通信方式,通常用于父子进程之间的通信。
匿名管道通过pipe()
系统调用创建,返回两个文件描述符,一个用于读,一个用于写。
#include <stdio.h>
#include <unistd.h>
int main() {
int pipefd[2];
char buffer[10];
if (pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return 1;
}
if (pid == 0) { // 子进程
close(pipefd[1]); // 关闭写端
read(pipefd[0], buffer, sizeof(buffer));
printf("Child received: %s\n", buffer);
close(pipefd[0]);
} else { // 父进程
close(pipefd[0]); // 关闭读端
write(pipefd[1], "Hello from parent", 20);
close(pipefd[1]);
}
return 0;
}
命名管道通过mkfifo()
系统调用创建,可以在不相关的进程之间进行通信。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
const char *fifo_name = "/tmp/myfifo";
mkfifo(fifo_name, 0666);
int fd = open(fifo_name, O_RDWR);
if (fd == -1) {
perror("open");
return 1;
}
char buffer[10];
read(fd, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
char *message = "Hello from FIFO";
write(fd, message, strlen(message) + 1);
close(fd);
unlink(fifo_name);
return 0;
}
消息队列允许进程以消息的形式发送和接收数据。
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msg_buffer {
long msg_type;
char msg_text[100];
};
int main() {
key_t key = ftok("msgqueue.c", 65);
int msgid = msgget(key, 0666 | IPC_CREAT);
struct msg_buffer message;
message.msg_type = 1;
strcpy(message.msg_text, "Hello from 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 <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main() {
key_t key = ftok("shmfile.c", 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 from shared memory");
printf("String written to shared memory is: %s\n", str);
shmdt(str);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
信号用于通知接收进程某个事件已经发生。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int signum) {
printf("Interrupt received, signal number: %d\n", signum);
}
int main() {
signal(SIGINT, signal_handler);
printf("Waiting for a signal...\n");
while (1) {
sleep(1);
}
return 0;
}
套接字是一种通用的IPC机制,不仅限于本地进程间通信,还可以用于网络通信。
Unix域套接字用于本地进程间通信。
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>
int main() {
int sockfd;
struct sockaddr_un addr;
char buffer[1024];
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
return 1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/tmp/uds.sock", sizeof(addr.sun_path) - 1);
unlink("/tmp/uds.sock");
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
listen(sockfd, 5);
int newsockfd = accept(sockfd, NULL, NULL);
if (newsockfd == -1) {
perror("accept");
return 1;
}
read(newsockfd, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
close(newsockfd);
close(sockfd);
return 0;
}
每种IPC机制都有其适用的场景和优缺点。选择合适的IPC机制取决于具体的应用需求,例如数据量大小、实时性要求、安全性等。