在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機制取決于具體的應用需求,例如數據量大小、實時性要求、安全性等。