一、进程间通信概述
进程间通信,即Inter-Process Communication(IPC),是指不同进程之间进行信息交换和共享的机制。在Linux系统下,IPC有多种方法,包括管道、套接字、消息队列、共享内存等。
管道:是一种单向通信机制,只能在父子进程之间共享数据,并且只能用于有亲缘关系的进程间通信。使用C语言实现的例子:
#include <stdio.h> #include <unistd.h> #define BUFFER_SIZE 25 #define READ_END 0 #define WRITE_END 1 int main(void) { char write_msg[BUFFER_SIZE] = "Hello, world!"; char read_msg[BUFFER_SIZE]; int fd[2]; pid_t pid; if (pipe(fd) == -1) { fprintf(stderr, "Pipe failed"); return 1; } pid = fork(); if (pid < 0) { fprintf(stderr, "Fork failed"); return 1; } if (pid > 0) { close(fd[READ_END]); write(fd[WRITE_END], write_msg, strlen(write_msg)+1); close(fd[WRITE_END]); } else { close(fd[WRITE_END]); read(fd[READ_END], read_msg, BUFFER_SIZE); printf("Received message: %s\n", read_msg); close(fd[READ_END]); } return 0; }
套接字:是一种双向通信机制,可以在不同的进程之间进行信息交换。可以分为面向连接(TCP)和无连接(UDP)套接字。使用Python实现的例子:
import socket HOST = '127.0.0.1' PORT = 12345 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() with conn: print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(data)
消息队列:是内核维护的一种队列,进程可以在队列中发送和接收消息。使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/msg.h> #define MSGSZ 128 typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; int main() { int msqid; key_t key; message_buf rbuf; size_t buflen; key = ftok("msgq.txt", 'A'); msqid = msgget(key, 0666 | IPC_CREAT); rbuf.mtype = 1; sprintf(rbuf.mtext, "Hello, world!"); buflen = strlen(rbuf.mtext) + 1; msgsnd(msqid, &rbuf, buflen, IPC_NOWAIT); msgrcv(msqid, &rbuf, MSGSZ, 1, 0); printf("Received message: %s\n", rbuf.mtext); msgctl(msqid, IPC_RMID, NULL); return 0; }
共享内存:是多个进程共享同一块物理内存的机制。使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #define SHMSZ 27 int main() { int shmid; key_t key; char *shm, *s; key = ftok("shmfile", 'A'); shmid = shmget(key, SHMSZ, 0666 | IPC_CREAT); shm = shmat(shmid, NULL, 0); s = shm; for (char c = 'a'; c <= 'z'; c++) { *s++ = c; } *s = '\0'; while (*shm != '*') { sleep(1); } shmdt(shm); shmctl(shmid, IPC_RMID, NULL); return 0; }
二、信号量机制
信号量(Semaphore)是一种保证多个进程之间互斥访问共享资源的机制。多个进程可以在信号量上进行等待和唤醒操作,并互相通知。在Linux系统下,信号量可以使用System V IPC 或 POSIX IPC实现。
System V IPC实现信号量,使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/sem.h> union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; }; int main() { int sem_id; key_t key; struct sembuf sembuf; union semun arg; key = ftok("semfile", 'A'); sem_id = semget(key, 1, 0666 | IPC_CREAT); arg.val = 1; semctl(sem_id, 0, SETVAL, arg); sembuf.sem_num = 0; sembuf.sem_op = -1; sembuf.sem_flg = SEM_UNDO; semop(sem_id, &sembuf, 1); printf("Semaphore locked!\n"); sembuf.sem_op = 1; semop(sem_id, &sembuf, 1); printf("Semaphore unlocked!\n"); semctl(sem_id, 0, IPC_RMID); return 0; }
POSIX IPC也可以实现信号量机制,使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <semaphore.h> #define SEM_NAME "/mysem" int main() { sem_t *sem; sem = sem_open(SEM_NAME, O_CREAT, 0666, 1); sem_wait(sem); printf("Semaphore locked!\n"); sem_post(sem); printf("Semaphore unlocked!\n"); sem_unlink(SEM_NAME); sem_close(sem); return 0; }
三、共享内存机制
共享内存是一种高效的进程间通信机制,多个进程可以将同一块物理内存映射到自己的地址空间中,实现共享。在Linux系统下,共享内存可以使用System V IPC或 POSIX IPC实现。
System V IPC实现共享内存,使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #define SHMSZ 27 int main() { int shmid; key_t key; char *shm, *s; key = ftok("shmfile", 'A'); shmid = shmget(key, SHMSZ, 0666 | IPC_CREAT); shm = shmat(shmid, NULL, 0); s = shm; for (char c = 'a'; c <= 'z'; c++) { *s++ = c; } *s = '\0'; while (*shm != '*') { sleep(1); } shmdt(shm); shmctl(shmid, IPC_RMID, NULL); return 0; }
POSIX IPC也可以实现共享内存机制,使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/mman.h> #define SHMSZ 27 int main() { int fd; char *shm, *s; fd = shm_open("shmfile", O_CREAT | O_RDWR, 0666); ftruncate(fd, SHMSZ); shm = mmap(NULL, SHMSZ, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); s = shm; for (char c = 'a'; c <= 'z'; c++) { *s++ = c; } *s = '\0'; while (*shm != '*') { sleep(1); } munmap(shm, SHMSZ); shm_unlink("shmfile"); return 0; }
四、消息队列机制
消息队列是一种专门用于进程间通信的机制,多个进程可以通过消息队列发送和接收消息。在Linux系统下,消息队列可以使用System V IPC或 POSIX IPC实现。
System V IPC实现消息队列,使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/msg.h> #define MSGSZ 128 typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; int main() { int msqid; key_t key; message_buf rbuf; size_t buflen; key = ftok("msgq.txt", 'A'); msqid = msgget(key, 0666 | IPC_CREAT); rbuf.mtype = 1; sprintf(rbuf.mtext, "Hello, world!"); buflen = strlen(rbuf.mtext) + 1; msgsnd(msqid, &rbuf, buflen, IPC_NOWAIT); msgrcv(msqid, &rbuf, MSGSZ, 1, 0); printf("Received message: %s\n", rbuf.mtext); msgctl(msqid, IPC_RMID, NULL); return 0; }
POSIX IPC也可以实现消息队列机制,使用C语言实现的例子:
#include <stdio.h> #include <stdlib.h> #include <mqueue.h> #define QUEUE_NAME "/test_queue" #define MSGSZ 128 int main() { mqd_t qd; char msgbuf[MSGSZ]; struct mq_attr attr; attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = MSGSZ; attr.mq_curmsgs = 0; qd = mq_open(QUEUE_NAME, O_CREAT | O_RDWR, 0666, &attr); mq_send(qd, "Hello, world!", 13, 0); mq_receive(qd, msgbuf, MSGSZ, NULL); printf("Received message: %s\n", msgbuf); mq_close(qd); mq_unlink(QUEUE_NAME); return 0; }
五、总结
Linux IPC提供了多种机制用于进程间通信,包括管道、套接字、消息队列、共享内存和信号量。任何一种IPC机制都可以被应用于相应的场景中。