还没有笔记
选中页面文字后点击「高亮」按钮添加
IPC 代表进程间通信。它是一组编程接口,允许进程之间进行协调活动。

图 15.1 UNIX 系统 IPC 摘要
管道是 UNIX 系统 IPC 最古老的形式,所有 UNIX 系统都提供。
管道有两个限制:
```
cat file.txt | sort | uniq > sorted_file.txt
```
cat 的输出成为 sort 的输入,sort 的输出成为 uniq 的输入。uniq 的输出被重定向到一个文件。
```
#include
int pipe(int fd[2]);
```
通过 fd 参数返回两个文件描述符:
fd[1] 的输出是 fd[0] 的输入。
\#include
通过 fd 参数返回两个文件描述符:
fd[1] 的输出是 fd[0] 的输入。

正如我们刚刚所见,单个进程中的管道几乎无用。
通常,调用 pipe() 的进程会接着调用 fork(),从而在父进程和子进程之间创建一个 IPC 通道,反之亦然。

图 15.3 fork 后的半双工管道
读取进程应关闭 fd[1] 并使用 fd[0] 进行读取。写入进程应关闭 fd[0] 并使用 fd[1] 进行写入。

图 15.3 fork 后的半双工管道

图 15.4 从父进程到子进程的管道
当管道的一端关闭时,适用两条规则。
```
#include "apue.h"
int main(void) {
int n;
int fd[2];
pid_t pid;
char line[MAXLINE];
if (pipe(fd) < 0)
err_sys("pipe error");
if ((pid = fork()) < O) {
err_sys("fork error");
} else if (pid > 0) { / parent /
close(fd[0]);
write(fd[1], "hello world\n", 12);
} else { / child /
close(fd[1]);
n = read(fd[O], line, MAXLINE);
write(STDOUT_FILENO, line, n);
}
exit(O);
}
```
为了将管道与已执行的进程一起使用,我们无法直接访问 pipe() 创建的文件描述符,我们必须使用 dup2() 函数,如下所示:
```
#include
int dup(int oldfd);
int dup2(int oldfd, int newfd);
```
dup() 系统调用创建一个文件描述符的副本。它使用最低编号的未使用描述符作为新描述符。
dup2() 系统调用与 dup() 类似,但它们之间的基本区别在于,dup2() 不使用最低编号的未使用文件描述符,而是使用用户指定的描述符编号。
假设您想计算系统上运行的名为“kworker”的进程有多少。
在 shell 中,您可以设置以下命令管道:
ps -A | grep -i kworker | wc -l
要在 C 中实现这一点,会复杂得多。
声明 3 个 int[] 数组并在父进程中调用 pipe() 3 次。
调用 fork() 3 次。对于每个子进程:
在父进程中,从最后一个进程和父进程之间的管道的开放端读取。在屏幕上打印输出。
等待所有 3 个子进程执行完毕。

现在研究 Canvas 中的 countprocess.c。
```
FILE popen(const char command, const
char *type);
```
```
int pclose(FILE *stream);
```