TCP/IP网络编程 第十一章:进程间通信
发布人:shili8
发布时间:2024-12-29 10:35
阅读次数:0
**TCP/IP网络编程**
**第十一章:进程间通信**
在前面的章节中,我们已经学习了如何使用TCP/IP协议进行网络通信。然而,在实际的应用场景中,往往需要多个进程或线程之间进行通信,以实现更复杂的功能。在本章中,我们将讨论如何在Linux系统上实现进程间通信。
**1.管道**
管道是一种最简单的进程间通信方式。它通过创建一个特殊类型的文件来实现通信,两个进程可以通过读写这个文件来交换信息。
c#include <stdio.h> #include <stdlib.h> int main() { int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid ==0) { // 子进程 close(pipefd[0]); // 关闭读管道 char buffer[10]; read(pipefd[1], buffer,10); // 从父进程读取信息 printf("子进程收到信息:%s ", buffer); close(pipefd[1]); // 关闭写管道 } else { // 父进程 close(pipefd[1]); // 关闭写管道 char buffer[] = "Hello, world!"; write(pipefd[0], buffer,10); // 向子进程写入信息 printf("父进程发送信息:%s ", buffer); close(pipefd[0]); // 关闭读管道 } return0; }
在上面的例子中,我们使用`pipe()`函数创建一个管道,两个进程通过`fork()`函数创建后,可以通过读写这个管道来交换信息。
**2.命名管道**
命名管道是一种特殊类型的文件,它可以被多个进程共享。每个进程都可以打开这个文件,并使用它来进行通信。
c#include <stdio.h> #include <stdlib.h> int main() { int fd; char *pathname = "/tmp/named_pipe"; if ((fd = open(pathname, O_RDWR | O_CREAT,0666)) == -1) { perror("open"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid ==0) { // 子进程 char buffer[10]; read(fd, buffer,10); // 从父进程读取信息 printf("子进程收到信息:%s ", buffer); close(fd); // 关闭文件描述符 } else { // 父进程 char buffer[] = "Hello, world!"; write(fd, buffer,10); // 向子进程写入信息 printf("父进程发送信息:%s ", buffer); close(fd); // 关闭文件描述符 } return0; }
在上面的例子中,我们使用`open()`函数创建一个命名管道,每个进程都可以打开这个文件,并使用它来进行通信。
**3.信号**
信号是一种特殊类型的事件,它可以被多个进程共享。每个进程都可以注册一个信号处理函数,以便在接收到该信号时执行特定的操作。
c#include <stdio.h> #include <stdlib.h> #include <signal.h> void sigint_handler(int signum) { printf("子进程收到SIGINT信号 "); } int main() { pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid ==0) { // 子进程 signal(SIGINT, sigint_handler); // 注册SIGINT信号处理函数 while (1) { sleep(1); } } else { // 父进程 printf("父进程发送SIGINT信号 "); kill(pid, SIGINT); // 向子进程发送SIGINT信号 } return0; }
在上面的例子中,我们使用`signal()`函数注册一个信号处理函数,以便在接收到SIGINT信号时执行特定的操作。
**4.共享内存**
共享内存是一种特殊类型的文件,它可以被多个进程共享。每个进程都可以打开这个文件,并使用它来进行通信。
c#include <stdio.h> #include <stdlib.h> int main() { int *shared_memory; shared_memory = (int *)malloc(sizeof(int)); if (!shared_memory) { perror("malloc"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid ==0) { // 子进程 *shared_memory =10; printf("子进程写入共享内存:%d ", *shared_memory); } else { // 父进程 printf("父进程读取共享内存:%d ", *shared_memory); } free(shared_memory); //释放共享内存 return0; }
在上面的例子中,我们使用`malloc()`函数创建一个共享内存,每个进程都可以打开这个文件,并使用它来进行通信。
**5.消息队列**
消息队列是一种特殊类型的文件,它可以被多个进程共享。每个进程都可以打开这个文件,并使用它来进行通信。
c#include <stdio.h> #include <stdlib.h> int main() { int queue_id; char *pathname = "/tmp/msg_queue"; if ((queue_id = msgget(pathname,0666 | IPC_CREAT)) == -1) { perror("msgget"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid ==0) { // 子进程 struct msgbuf message; message.mtype =10; strcpy(message.mtext, "Hello, world!"); if (msgsnd(queue_id, &message, strlen(message.mtext), IPC_NOWAIT) == -1) { perror("msgsnd"); exit(EXIT_FAILURE); } } else { // 父进程 struct msgbuf message; if (msgrcv(queue_id, &message,10,0, IPC_NOWAIT) == -1) { perror("msgrcv"); exit(EXIT_FAILURE); } printf("父进程收到消息:%s ", message.mtext); } return0; }
在上面的例子中,我们使用`msgget()`函数创建一个消息队列,每个进程都可以打开这个文件,并使用它来进行通信。
**6.信号量**
信号量是一种特殊类型的变量,它可以被多个进程共享。每个进程都可以对该变量进行操作,以便在满足特定条件时执行特定的操作。
c#include <stdio.h> #include <stdlib.h> int main() { int sem_id; if ((sem_id = semget(0,1, IPC_CREAT |0666)) == -1) { perror("semget"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid ==0) { // 子进程 struct sembuf semaphore; semaphore.sem_num =0; semaphore.sem_op =0; // P操作 semaphore.sem_flg = IPC_NOWAIT; if (semop(sem_id, &semaphore,1) == -1) { perror("semop"); exit(EXIT_FAILURE); } } else { // 父进程 struct sembuf semaphore; semaphore.sem_num =0; semaphore.sem_op =1; // V操作 semaphore.sem_flg = IPC_NOWAIT; if (semop(sem_id, &semaphore,1) == -1) { perror("semop"); exit(EXIT_FAILURE); } } return0; }
在上面的例子中,我们使用`semget()`函数创建一个信号量,每个进程都可以对该变量进行操作,以便在满足特定条件时执行特定的操作。
**7.共享内存**
共享内存是一种特殊类型的文件,它可以被多个进程共享。每个进程都可以打开这个文件,并使用它来进行通信。
c#include <stdio.h> #include <stdlib.h> int main() { int *shared