← 返回首页
🔗

Linux进程间通信

📂 devops ⏱ 2 min 291 words

Linux进程间通信

进程间通信概述

进程间通信(IPC)是指不同进程之间交换数据的机制。

主要IPC方式

管道(Pipe)

管道是最简单的IPC方式,用于父子进程之间通信。

#include <unistd.h>

int pipefd[2];
pipe(pipefd);

// 父进程写入
write(pipefd[1], "hello", 5);

// 子进程读取
char buf[10];
read(pipefd[0], buf, 5);

命名管道(FIFO)

命名管道可以在不相关的进程之间通信。

# 创建命名管道
mkfifo /tmp/mypipe

# 进程1写入
echo "hello" > /tmp/mypipe

# 进程2读取
cat /tmp/mypipe

消息队列

// System V消息队列
#include <sys/msg.h>

int msqid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);

struct msgbuf {
    long mtype;
    char mtext[100];
};

// 发送消息
struct msgbuf msg = {1, "hello"};
msgsnd(msqid, &msg, sizeof(msg.mtext), 0);

// 接收消息
msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0);

共享内存

共享内存是最快的IPC方式,多个进程可以访问同一块内存。

#include <sys/shm.h>

// 创建共享内存
int shmid = shmget(IPC_PRIVATE, 4096, 0666 | IPC_CREAT);

// 映射到进程地址空间
void *ptr = shmat(shmid, NULL, 0);

// 写入数据
strcpy(ptr, "hello");

// 从另一个进程读取
char *data = (char *)shmat(shmid, NULL, 0);
printf("%s\n", data);

// 分离共享内存
shmdt(ptr);

信号量

信号量用于进程同步,控制对共享资源的访问。

#include <sys/sem.h>

// 创建信号量集
int semid = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);

// 初始化信号量值
semctl(semid, 0, SETVAL, 1);

// P操作(等待)
struct sembuf op = {0, -1, 0};
semop(semid, &op, 1);

// V操作(释放)
struct sembuf op = {0, 1, 0};
semop(semid, &op, 1);

信号

信号是异步通信方式。

#include <signal.h>

// 注册信号处理函数
void handler(int sig) {
    printf("Received signal %d\n", sig);
}
signal(SIGUSR1, handler);

// 发送信号
kill(pid, SIGUSR1);

Socket

Socket是最通用的IPC方式,支持网络通信。

#include <sys/socket.h>

// 创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);

// 绑定地址
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));

// 监听
listen(sockfd, 5);

// 接受连接
int clientfd = accept(sockfd, NULL, NULL);

实践:管道通信示例

#!/bin/bash
# 使用命名管道实现进程通信

# 创建命名管道
mkfifo /tmp/pipe_example 2>/dev/null

# 启动接收进程(后台)
(
    while true; do
        read message < /tmp/pipe_example
        echo "收到: $message"
    done
) &
RECEIVER_PID=$!

# 发送消息
echo "Hello from sender" > /tmp/pipe_example
echo "Hello again" > /tmp/pipe_example

# 清理
sleep 1
kill $RECEIVER_PID
rm /tmp/pipe_example

IPC方式比较

方式 速度 复杂度 适用场景
管道 父子进程
消息队列 结构化消息
共享内存 最快 大量数据
信号量 - 同步控制
Socket 网络通信

总结

IPC是多进程编程的基础。根据应用场景选择合适的IPC方式,能够提高程序的性能和可维护性。