Linux 文件描述符、重定向和管道
1.文件描述符
- 文件描述符就是一个 数组 的 索引号
- 每个进程都有其打开的一组文件,它们保存在一个数组中,文件描述符即为某文件在此数组中的索引
- 当打开文件时,为此文件安排的描述符总是此数组中最小可用位置的索引
- 0 :标准输入; 1 :标准输出; 2 :标准错误
- Unix 中这三个文件描述符默认情况下为每个进程都打开,进程可以直接对其读写操作
2. 重定向
-
通过重定向符号告诉
shell
而不是程序将文件描述定位到文件. -
shell 并不将重定向符号及文件名传递给程序
-
重定向可以出现在命令行中的任何地方,重定向符号并不能终止命令和参数
-
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null
-
重定向的三种方法:
- close(0) + open(filename, O_RDONLY).
- fd = open(file) + close(0) + dup(fd) + close(fd)
- fd = open(file) + dup2(fd, 0) + close(fd)
目标 复制一个文件描述符 头文件 #include <unistd.h>
函数原型 newfd= dup(oldfd)
newfd= dup2(oldfd,newfd)
参数 oldfd
需要复制的文件描述符newfd
复制oldfd
后得到的文件描述符返回值 -1 出错;newfd 新的文件描述符
3. 管道
- 管道的特点:
- 单工且单向通信
- 字节流传送(FIFO)
- 命名管道可以在任意进程间通信
- 无名管道只能在父子进程之间通信
目标 | 创建管道 |
---|---|
头文件 | #include <unistd.h> |
函数原型 | int pipe(int pipe[2]) |
参数 | 创建成功后,pipe[0]是读端的文件描述符; pipe[1]是写端的文件描述符 |
返回值 | -1 出错;0 成功 |
- 例子:编写一个程序,实现如下功能:创建父子进程,父进程向子进程通过管道发送一个字符串,子进程读取该字符串显示并倒序后发送给父进程,父进程读取该倒序后的字符串并打印出来。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
char sendbuf[] = "I am Linux";
char recbuf[20];
char parrecbuf[20];
void reverse(char *str){
if (str == NULL) return;
char *p = str;
char *q = str;
while(*q) ++q;
q--;
while(q > p) {
char t = *p;
*p++ = *q;
*q-- = t;
}
}
int main() {
int mypipe[2], fd;
if ( pipe(mypipe) < 0) {
perror("pipe failed");
exit(0);
}
if ((fd = fork()) < 0) {
perror("pipe failed");
exit(0);
}
if (fd == 0) {
read(mypipe[0], recbuf, strlen(sendbuf));
printf("The child process get %s\n", recbuf);
reverse(recbuf);
write(mypipe[1], recbuf, strlen(recbuf));
}
if (fd > 0) {
write(mypipe[1], sendbuf, strlen(sendbuf));
sleep(10);
read(mypipe[0], parrecbuf, strlen(sendbuf));
printf("The parent process get %s\n", parrecbuf);
wait();
}
}
- 例子:实现类似于“ps –aux | grep init”的功能
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
int pid, mypipe[2];
pipe(mypipe);
pid = fork();
if ( pid < 0 ) {
perror("create process failed.\n");
exit(0);
}
if (pid == 0) {
close(mypipe[1]);
dup2(mypipe[0], 0);
close(mypipe[0]);
sleep(1);
execlp("grep", "grep", "init", NULL);
}
if (pid > 0) {
close(mypipe[0]);
dup2(mypipe[1], 1);
close(mypipe[1]);
execlp("ps", "ps", "aux", NULL);
}
}