LinuxC中的重定向功能,必须依靠等位文件描述符函数dup,该函数的介绍如下:
dup用来复制oldfd所指的文件描述符。但复制成功时返回最小的尚未被使用的文件描述符。若有错误则返回-1,错误代码存入errno中。返回的新文件描述符和参数oldfd指向同一个文件,共享所有的锁定,读写指针,和各项权限或标志位。
可以用这样的C++代码来实现
这个指令的作用是,把ls的输出作为wc的输入,最后wc的结果输出到控制台上。
同样Ubuntu下测试通过,作用和Bash指令一样。
dup和dup2用来复制文件描述符。
函数介绍:
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd,int newfd);
dup用来复制oldfd所指的文件描述符。但复制成功时返回最小的尚未被使用的文件描述符。若有错误则返回-1,错误代码存入errno中。返回的新文件描述符和参数oldfd指向同一个文件,共享所有的锁定,读写指针,和各项权限或标志位。
dup2可以用参数newfd指定新文件描述符的数值。若newfd已经被程序使用,系统就会将其关闭以释放该文件描述符;若newfd与oldfd相等,dup2将返回newfd,而不关闭他。dup2调用成功返回新的文件描述符,出错则返回-1。
标准输入(stdin),标准输出(stdout),标准出错信息(stderr)的文件号分别为0,1,2。
例如,使用了dup(newfd, 1)后,控制台输出的信息会全部被输出到文件描述符newfd所对应的文件上,而控制台不再输出信息,因为控制台所对应的文件描述符已经被关闭了。
下面的这句Bash指令:
#ls -l >> /home/lin/桌面/test
可以用这样的C++代码来实现
//============================================================================
// Name : DupTest.cpp
// Author : Lin
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <string>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
int main()
{
string path = "/home/lin/桌面/test"; //把标准输出流重定向到这个文件中
int newFd = open(path.c_str(), O_RDWR|O_CREAT, S_IRWXU);//open和close并不在同一个头文件中,open()在<fcntl.h>
dup2(newFd, 1);//包含于<unistd.h>
close(newFd);//包含于<unistd.h>
execlp("ls", "ls", "-l", NULL);
//cout << "heiheihei" << endl;//假如加进了这句代码,这个字符串被直接写进path路径的文件立。这句代码和write(STDOUT, str, sizeof(str))是一样的,本质上都是把字符串写进标准输出流所对应的文件描述符STDOUT(即1)中
return 0;
}
在Ubuntu下测试通过,和Bash指令的作用一样。
再来看另一个例子,Linux下的管道重定向,例如下面的这句Bash指令:
# ls -l | wc
这个指令的作用是,把ls的输出作为wc的输入,最后wc的结果输出到控制台上。
这个指令,用C代码的实现思路是这样的,构造一个管道,把标准输出流挂到管道的写入端上,标准输入流挂到管道的读取端上,工作流程如下:
ls -l的结果 --> STDOUT(即管道的写入端)--> STDIN(即管道的读取端)--> 作为wc的输入 --> 最后的结果打印到控制台上。
这里直接贴代码了:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pfds[2];
char *path = "/home/lin";
chdir(path);
if ( pipe(pfds) == 0 ) {
if ( fork() == 0 ) {
close(1);
dup2( pfds[1], 1 );//标准输出流挂到管道写入端
close( pfds[0] );
execlp( "ls", "ls", "-l", NULL );
} else {
close(0);
dup2( pfds[0], 0 );//标准输入流挂到管道读取端
close( pfds[1] );
execlp( "wc", "wc", NULL );
}
return 0;
}
}
同样Ubuntu下测试通过,作用和Bash指令一样。