你需要pipe(2):
pipe() 创建一个管道,一个单向的数据通道,可以
用于进程间通信。数组pipefd 用于
返回两个引用管道末端的文件描述符。
pipefd[0] 指管道的读取端。 pipefd[1] 指
到管道的写端。数据写入写入端
管道由内核缓冲,直到从读取中读取
管道的末端。详情请见pipe(7)。
你需要dup2(2):
int dup2(int oldfd, int newfd);
dup2() 系统调用执行与dup() 相同的任务,但
而不是使用编号最小的未使用文件描述符,它
使用newfd 中指定的文件描述符编号。其他
换句话说,文件描述符newfd 已调整为现在
指与oldfd相同的打开文件描述。
如果文件描述符newfd之前打开过,则关闭
在被重复使用之前;关闭是静默执行的(即,任何
dup2() 不会报告关闭期间的错误。
所以,您需要的是 两个 管道。由于一根管道只能做一个方向,而你想要全双工,你需要两个。下面是两个非常简单的例子。 cap.c 是一个读取一个字符并将其回显为大写的程序。它会无限期地这样做。
pipe.c 是生成cap.c 的程序,创建两个管道,写入它,读回孩子的响应,并通过stderr 给我们响应(因为我们将有dup2(2)ed 另一个、stdin 和 stdout)。代码已注释。
/* cap.c */
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
int main(void)
{
char buf;
while(1) {
read(0, &buf, 1);
buf = toupper(buf);
write(1, &buf, 1);
}
}
还有一个……
/* pipe.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
int main(void)
{
int parent_write[2], child_write[2], ws;
char *cap[2] = {"./cap", NULL}, buf;
pid_t cpid;
pipe(parent_write);
pipe(child_write);
/* pipe[0] -> read (you read from it)
* pipe[1] -> write (you write to it)
*
* parent_write[0] -> the child will read this
* parent_write[1] -> the parent writes here
*
* child_write[0] -> the parent reads here
* child_write[1] -> the child writes here
*/
if(!(cpid = fork())) {
/* child process, the "add" */
/* close the read end of child_write
* close the write end of parent_write
*/
close(child_write[0]);
close(parent_write[1]);
/* dup2 will swap our stdin(0) and stdout(1)
* for the pipe
*
* parent_write[0] -> our new stdin(0)
* child_write[1] -> our new stdout(1)
*/
dup2(parent_write[0], 0);
dup2(child_write[1], 1);
execv(*cap, cap);
} else {
/* close the read end parent_write
* close the write end of child_write
*/
close(parent_write[0]);
close(child_write[1]);
/* dup2 will swap...
*
* parent_write[1] -> new stdout
* child_write[0] -> new stdin
*/
dup2(parent_write[1], 1);
dup2(child_write[0], 0);
for(int i = 0; i < 10; i++) {
buf = 'a' + i;
write(1, &buf, 1);
fprintf(stderr, "sent: %c\n", buf);
read(0, &buf, 1);
fprintf(stderr, "got : %c\n", buf);
}
kill(cpid, 1);
wait(&ws);
}
return 0;
}
然后……
$ gcc cap.c -o cap
$ gcc pipe.c -o pipe
$ ./pipe
sent: a
got : A
sent: b
got : B
sent: c
got : C
sent: d
got : D
sent: e
got : E
sent: f
got : F
sent: g
got : G
sent: h
got : H
sent: i
got : I
sent: j
got : J