Linux系统编程:进程间通信之管道详解

需积分: 17 2 下载量 16 浏览量 更新于2024-07-23 收藏 331KB DOC 举报
"Linux系统编程中的进程间通信是一个重要的主题,特别是管道(Pipe)作为一种常见的通信机制,被广泛用于父子进程或兄弟进程之间的数据传递。管道是半双工的,即数据只能单向流动,需要双向通信时需要两个独立的管道。它们不是普通文件,而是存在于内存中的特殊文件系统。每个管道包含两个文件描述符,一个用于读取,另一个用于写入。创建管道通常伴随着`fork()`操作,用于父子进程间的通信。 在创建管道时,`pipe()`函数会生成两个文件描述符,`fd[0]`用于读,`fd[1]`用于写。管道的容量有限,当写入管道的数据达到其缓冲区的上限时,进一步的写操作将阻塞,直到读端读取部分或全部数据。同样,如果读端在写端之前关闭,那么写端会立即收到错误指示,表明管道已空。 无名管道的读写规则如下: - 当尝试从管道读取数据但写端已关闭时,读操作将返回0,表示管道为空。 - 写端如果尝试写入已满的管道,将被阻塞,直到读端消费掉部分或全部数据。 - 管道中的数据一旦被读取,就会从缓冲区中移除,不会持久存储。 以下是一个简单的示例代码,展示了如何使用管道进行父子进程间的通信: ```c #include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() { int n; int fd[2]; int count = 0; char buf[100] = {0}; if (pipe(fd) == -1) { perror("Pipe failed"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid < 0) { perror("Fork failed"); exit(EXIT_FAILURE); } else if (pid > 0) { // 父进程 close(fd[0]); // 关闭读端,避免干扰 write(fd[1], "Hello, child!\n", strlen("Hello, child!\n") + 1); close(fd[1]); // 写完后关闭写端 } else { // 子进程 close(fd[1]); // 关闭写端,避免干扰 read(fd[0], buf, sizeof(buf)); printf("Received from parent: %s\n", buf); close(fd[0]); } exit(EXIT_SUCCESS); } ``` 在这个例子中,父进程创建管道后,`fork()`一个子进程。父进程关闭读端,向管道写入字符串,然后关闭写端。子进程关闭写端,从管道读取数据,然后关闭读端。这样就实现了父子进程间的一次简单通信。 除了无名管道,还有有名管道(FIFO)、信号量、共享内存、消息队列等其他的System V IPC对象,以及BSD套接字等通信方式。每种方式都有其适用场景和特点,选择哪种方式取决于具体的应用需求和性能考虑。例如,有名管道允许非亲缘关系的进程间通信,而信号量则用于同步多个进程对共享资源的访问。