命令行中的重定向符号
介绍和使用
在Linux的命令行中,重定向符号用于将命令的输入或输出重定向到文件或设备。
常见的重定向符号:
1.“
>
“符号:将命令的标准输出重定向到指定文件中,并覆盖原有的内容。
2.”>>
“符号:将命令的标准输出重定向的指定文件中,并将输出结果追加到文件末尾。
3.”<
“符号:将指定文件的内容作为命令的标准输入。
4."<<
"符号:将命令的标准输入设置为指定的文本块。
在使用重定向符号时,应该确保文件或设备的权限设置正确,否则可能会出现无法访问或写入的错误。
模拟实现
下面通过自定义shell来进行模拟实现重定向,加深印象。
自定义Shell的链接入口
文件缓冲问题
描述
文件缓冲是指将数据暂时存储在内存中,而不是立即写入到文件中。这样可以提高文件操作的效率,因为将多次的写操作合并为一次,可以减少IO操作的效率。
文件缓冲主要为两种类型:
- 全缓冲:当填满缓冲区或遇到换行符时,才会执行写操作。例如,使用
fwrite()
函数写入数据时,默认是全缓冲。 - 行缓冲:当遇到换行符时,才会执行写操作。例如,使用
printf()
函数输出数据时,默认是行缓冲。
可以使用setbuf()
、setvbuf()
等函数来设置文件的缓冲方式。此外,使用fflush()
函数可以强制刷新缓冲区,将缓冲区中的数据立即写入到文件中。
需要注意的是,文件缓冲只适用于标准I/O库函数(如stdio.h
中的函数),对于直接使用系统调用进行文件操作的函数(如read()
和write()
),没有文件缓冲的概念,数据会立即写入文件。
例子
模拟实现
头文件:mystdio.h
#pragma once#include <stdio.h>#define SIZE 4096
#define NONE_FLUSH (1<<1)
#define LINE_FLUSH (1<<2)
#define FULL_FLUSH (1<<3) typedef struct _myFILE
{//char inbuffer[];char outbuffer[SIZE];int pos;int cap;int fileno;int flush_mode;
}myFILE;myFILE *my_fopen(const char *pathname, const char *mode);
int my_fwrite(myFILE *fp, const char *s, int size);
//int my_fread();
void my_fflush(myFILE *fp);
void my_fclose(myFILE *fp);
void DebugPrint(myFILE *fp);
源文件:mystdio.c
#include "mystdio.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>const char *toString(int flag)
{if(flag & NONE_FLUSH) return "None";else if(flag & LINE_FLUSH) return "Line";else if(flag & FULL_FLUSH) return "FULL";return "Unknow";
}void DebugPrint(myFILE *fp)
{printf("outbufer: %s\n", fp->outbuffer);printf("fd: %d\n", fp->fileno);printf("pos: %d\n", fp->pos);printf("cap: %d\n", fp->cap);printf("flush_mode: %s\n", toString(fp->flush_mode));
}myFILE *my_fopen(const char *pathname, const char *mode)
{int flag = 0;if(strcmp(mode, "r") == 0){flag |= O_RDONLY;}else if(strcmp(mode, "w") == 0){flag |= (O_CREAT|O_WRONLY|O_TRUNC);}else if(strcmp(mode, "a") == 0){flag |= (O_CREAT|O_WRONLY|O_APPEND);}else{return NULL;}int fd = 0;if(flag & O_WRONLY){umask(0);fd = open(pathname, flag, 0666);}else{fd = open(pathname, flag);}if(fd < 0) return NULL;myFILE *fp = (myFILE*)malloc(sizeof(myFILE));if(fp == NULL) return NULL;fp->fileno = fd;fp->cap = SIZE;fp->pos = 0;fp->flush_mode = LINE_FLUSH;return fp;
}void my_fflush(myFILE *fp)
{if(fp->pos == 0) return;write(fp->fileno, fp->outbuffer, fp->pos);fp->pos = 0;
}int my_fwrite(myFILE *fp, const char *s, int size)
{// 1. 写入memcpy(fp->outbuffer+fp->pos, s, size);fp->pos += size;// 2. 判断,是否要刷新if((fp->flush_mode & LINE_FLUSH) && fp->outbuffer[fp->pos-1] == '\n'){my_fflush(fp);}else if((fp->flush_mode & FULL_FLUSH) && fp->pos == fp->cap){my_fflush(fp);}return size;
}void my_fclose(myFILE *fp)
{my_fflush(fp);close(fp->fileno);free(fp);
}
测试: