进程间通信的方式
管道
概述:
用于在父子进程之间传递数据,管道在操作系统内部提供了一个缓冲区,进程可以通过该缓冲区交换数据
形式:
- 匿名管道:用于父子进程之间的通信
- 命名管道(FIFO):允许无关的进程之间进行通信
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <stdio.h> #include <unistd.h>
int main() { int pipefd[2]; char buffer[100];
pipe(pipefd);
if (fork() == 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", 18); close(pipefd[1]); }
return 0; }
|
消息队列
概述:
允许不同的进程之间通过发送和接收消息进行通信,消息队列支持异步通信,发送者和接收者可以不在同一时刻,通过FIFO的方式排列消息
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include <stdio.h> #include <stdlib.h> #include <mqueue.h> #include <string.h>
#define QUEUE_NAME "/example_queue"
int main() { mqd_t mq; struct mq_attr attr; char buffer[256];
attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = 256; attr.mq_curmsgs = 0;
mq = mq_open(QUEUE_NAME, O_CREAT | O_RDWR, 0644, &attr); if (mq == (mqd_t)-1) { perror("mq_open"); exit(1); }
char* message = "Hello, message queue!"; if (mq_send(mq, message, strlen(message) + 1, 0) == -1) { perror("me_send"); exit(1); }
if (mq_receive(mq, buffer, 256, NULL) == -1) { perror("mq_receive"); exit(1); }
printf("Received: %s\n", buffer);
mq_close(mq); mq_unlink(QUEUE_NAME);
return 0; }
|
共享内存
概述:
允许多个进程直接访问同一块内存区域,通过共享内存,不同进程可以以读写的方式直接修改共享区域的数据
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <stdio.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <string.h>
#define SHM_NAME "/shm_example"
int main() { int shm_fd; char* shm_ptr;
shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666); ftruncate(shm_fd, 256);
shm_ptr = mmap(0, 256, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (shm_ptr == MAP_FAILED) { perror("mmap"); return -1; }
sprintf(shm_ptr, "Hello, shared memory!");
printf("Shared memory content: %s\n", shm_ptr);
munmap(shm_ptr, 256); close(shm_fd); shm_unlink(SHM_NAME);
return 0; }
|
信号量
概述:
用于控制对共享资源的访问呢,解决进程之间的互斥问题,防止多个进程同时访问同一资源
- 二进制信号量:只能取值0或1,常用于互斥锁
- 计数信号量:信号量的值大于1,常用于管理多个共享资源
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <stdio.h> #include <semaphore.h> #include <pthread.h>
sem_t sem;
void* worker(void* arg) { sem_wait(&sem); printf("Worker started\n"); sleep(1); sem_post(&sem); return NULL; }
int main() { pthread_t t1, t2; sem_init(&sem, 0, 1);
pthread_create(&t1, NULL, worker, NULL); pthread_create(&t2, NULL, worker, NULL);
pthread_join(t1, NULL); pthread_join(t2, NULL);
sem_destroy(&sem);
return 0; }
|
socket
概述:
可用于本地进程间通信(Unix域套接字)或跨机器通信(基于TCP/IP协议)
服务端示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h>
int main() { int sock; struct sockaddr_in server_addr; char* message = "Hello from client";
sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("socket"); exit(1); }
server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
send(sock, message, strlen(message), 0);
close(sock); return 0; }
|
客户端示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h>
int main() { int sock; struct sockaddr_in server_addr; char* message = "Hello from client";
sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("socket"); exit(1); }
server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
send(sock, message, strlen(message), 0);
close(sock); return 0; }
|