重定向的实现原理

重定向
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{
close(1);
int fd = open("myfile", O_WRONLY|O_CREAT, 00644);
if(fd < 0){
perror("open");
return 1;
}
printf("fd: %d\n", fd);
fflush(stdout);
close(fd);
exit(0);
}
此时,我们发现,本来应该输出到显示器上的内容,输出到了文件 myfile 当中,其中, fd 1 。这种现象叫做输出
重定向。常见的重定向有 :>, >>, <
那重定向的本质是什么呢?
使用 dup2 系统调用
函数原型如下 :
#include <unistd.h>
int dup2(int oldfd, int newfd);
示例代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd = open("./log", O_CREAT | O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
close(1);
dup2(fd, 1);
for (;;) {
char buf[1024] = {0};
ssize_t read_size = read(0, buf, sizeof(buf) - 1);
if (read_size < 0) {
perror("read");
break;
}
printf("%s", buf);
fflush(stdout);
}
return 0;
}
例子 1. minishell 中添加重定向功能
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <fcntl.h>
# define MAX_CMD 1024
char command[MAX_CMD];
int do_face()
{
memset(command, 0x00, MAX_CMD);
printf("minishell$ ");
fflush(stdout);
if (scanf("%[^\n]%*c", command) == 0) {
getchar();
return -1;
}
return 0;
}
char **do_parse(char *buff)
{
int argc = 0;
static char *argv[32];
char *ptr = buff;
while(*ptr != '\0') {
if (!isspace(*ptr)) {
argv[argc++] = ptr;
while((!isspace(*ptr)) && (*ptr) != '\0') {
ptr++;
}
}else {
while(isspace(*ptr)) {
*ptr = '\0';
ptr++;
}
}
}
argv[argc] = NULL;
return argv;
}
int do_redirect(char *buff)
{
char *ptr = buff, *file = NULL;
int type = 0, fd, redirect_type = -1;
while(*ptr != '\0') {
if (*ptr == '>') {
*ptr++ = '\0';
redirect_type++;
if (*ptr == '>') {
*ptr++ = '\0';
redirect_type++;
}
while(isspace(*ptr)) {
ptr++;
}
file = ptr;
while((!isspace(*ptr)) && *ptr != '\0') {
ptr++;
}
*ptr = '\0';
if (redirect_type == 0) {
fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0664);
}else {
fd = open(file, O_CREAT|O_APPEND|O_WRONLY, 0664);
}
dup2(fd, 1);
}
ptr++;
}
return 0;
}
int do_exec(char *buff)
{
char **argv = {NULL};
int pid = fork();
if (pid == 0) {
do_redirect(buff);
argv = do_parse(buff);
if (argv[0] == NULL) {
exit(-1);
}
execvp(argv[0], argv);
}else {
waitpid(pid, NULL, 0);
}
return 0;
}
int main(int argc, char *argv[])
{
while(1) {
if (do_face() < 0)
continue;
do_exec(command);
}
return 0;
}
printf C 库当中的 IO 函数,一般往 stdout 中输出,但是 stdout 底层访问文件的时候,找的还是 fd:1, 但此时, fd:1
下标所表示内容,已经变成了 myfifile 的地址,不再是显示器文件的地址,所以,输出的任何消息都会往文件中写
入,进而完成输出重定向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值