Linux进程间通信是操作系统中多进程协同工作的基础能力,不同的进程需要在隔离的内存空间中完成数据交换、状态通知等操作,就需要依赖系统提供的各类通信机制。这些机制各有特点,适配不同的业务场景,开发者可以根据通信的实时性、数据量、进程关系等需求选择对应的实现方式。
常见Linux进程间通信方式
1. 管道(Pipe)
管道是最基础的进程间通信方式,分为匿名管道和命名管道两种。匿名管道只能用于有亲缘关系的进程之间通信,比如父子进程;命名管道可以用于无亲缘关系的进程之间通信,在文件系统中存在对应的管道文件。
匿名管道的使用示例:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
int main() {
int pipe_fd[2];
pid_t pid;
char write_buf[] = "Hello from parent process";
char read_buf[1024];
// 创建匿名管道
if (pipe(pipe_fd) == -1) {
perror("pipe create failed");
return 1;
}
pid = fork();
if (pid < 0) {
perror("fork failed");
return 1;
} else if (pid == 0) {
// 子进程:关闭写端,从读端读取数据
close(pipe_fd[1]);
int len = read(pipe_fd[0], read_buf, sizeof(read_buf) - 1);
if (len > 0) {
read_buf[len] = ' ';
printf("Child process read: %sn", read_buf);
}
close(pipe_fd[0]);
} else {
// 父进程:关闭读端,向写端写入数据
close(pipe_fd[0]);
write(pipe_fd[1], write_buf, strlen(write_buf));
close(pipe_fd[1]);
wait(NULL); // 等待子进程结束
}
return 0;
}
2. 消息队列(Message Queue)
消息队列是内核维护的消息链表,进程可以向队列中发送指定类型的消息,也可以按类型读取消息,支持无亲缘关系的进程之间通信,消息读取后不会自动删除,需要显式操作。
消息队列简单使用示例:
#include <stdio.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
// 定义消息结构体
struct msg_buffer {
long msg_type;
char msg_text[100];
};
int main() {
key_t key = ftok("msgqueue", 65); // 生成唯一key
int msgid = msgget(key, 0666 | IPC_CREAT); // 创建消息队列
struct msg_buffer message;
message.msg_type = 1;
strcpy(message.msg_text, "Test message from process");
// 发送消息
msgsnd(msgid, &message, sizeof(message.msg_text), 0);
printf("Message sent to queuen");
// 读取消息
msgrcv(msgid, &message, sizeof(message.msg_text), 1, 0);
printf("Message received: %sn", message.msg_text);
// 删除消息队列
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
3. 共享内存(Shared Memory)
共享内存是效率最高的进程间通信方式,内核将同一块物理内存映射到多个进程的虚拟地址空间,进程可以直接读写这块内存,不需要内核做数据拷贝。通常需要配合信号量等机制实现同步,避免读写冲突。
共享内存使用示例:
#include <stdio.h>
#include <sys/shm.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, NULL, 0);
// 写入数据到共享内存
strcpy(str, "Hello shared memory");
printf("Data written to shared memory: %sn", str);
// 分离共享内存
shmdt(str);
// 读取端可以重新附加共享内存读取数据,最后删除共享内存段
// shmctl(shmid, IPC_RMID, NULL);
return 0;
}
4. 信号量(Semaphore)
信号量主要用于进程间的同步和互斥,本身不传输数据,而是通过计数器控制多个进程对共享资源的访问。常见的信号量有System V信号量和POSIX信号量,下面以System V信号量为例。
#include <stdio.h>
#include <sys/sem.h>
#include <unistd.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); // 创建1个信号量
union semun arg;
arg.val = 1; // 初始化信号量值为1
semctl(semid, 0, SETVAL, arg);
struct sembuf sb;
sb.sem_num = 0;
sb.sem_flg = 0;
// P操作:申请资源,信号量减1
sb.sem_op = -1;
semop(semid, &sb, 1);
printf("Process get resourcen");
sleep(2); // 模拟资源使用
// V操作:释放资源,信号量加1
sb.sem_op = 1;
semop(semid, &sb, 1);
printf("Process release resourcen");
// 删除信号量
semctl(semid, 0, IPC_RMID);
return 0;
}
5. 套接字(Socket)
套接字不仅可以用于网络通信,也可以用于本地进程间通信,分为网络套接字和Unix域套接字。Unix域套接字用于同一台机器上的进程通信,效率比网络套接字更高,支持无亲缘关系的进程之间通信。
Unix域套接字服务端示例:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>
int main() {
int server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/unix_socket_test");
bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
listen(server_fd, 5);
int client_fd = accept(server_fd, NULL, NULL);
char buf[1024];
int len = read(client_fd, buf, sizeof(buf) - 1);
if (len > 0) {
buf[len] = ' ';
printf("Server received: %sn", buf);
}
close(client_fd);
close(server_fd);
unlink("/tmp/unix_socket_test");
return 0;
}
不同通信方式的选择建议
可以根据实际需求选择合适的进程间通信方式:
- 如果是父子进程之间简单的单向数据传输,优先选择匿名管道
- 如果需要无亲缘关系进程之间传输结构化消息,可选择消息队列
- 如果需要传输大量数据,追求最高效率,选择共享内存配合信号量同步
- 如果需要跨机器或者本地进程之间通用通信,选择套接字
- 如果只需要进程同步,不需要传输数据,选择信号量
| 通信方式 | 适用场景 | 效率 | 是否支持无亲缘关系进程 |
|---|---|---|---|
| 匿名管道 | 父子进程单向数据传输 | 中等 | 否 |
| 命名管道 | 无亲缘关系进程简单数据传输 | 中等 | 是 |
| 消息队列 | 结构化消息传输 | 中等 | 是 |
| 共享内存 | 大量数据高速传输 | 最高 | 是 |
| 信号量 | 进程同步互斥 | 高 | 是 |
| Unix域套接字 | 本地通用进程通信 | 较高 | 是 |
Linux进程间通信pipeshared_memorysocket修改时间:2026-07-03 12:37:05