命令行中的重定向符号
介绍和使用
在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);
}
测试: