为什么公司网站打开很慢,网站的建设流程是什么,国外html5网站欣赏,python网站开发简单吗文章目录 fd-文件描述符如何深度理解一切皆文件**我们使用OS的本质:**FILEFILE是什么?谁提供的?和我们刚刚讲的内核的struct有关系吗FILE是一个结构体.该结构体内部一定要有以下字段:FILE是C语言标准库提供的.FILE和我们刚刚讲的内核的struct没有关系,最多就是上… 文章目录 fd-文件描述符如何深度理解一切皆文件**我们使用OS的本质:**FILEFILE是什么?谁提供的?和我们刚刚讲的内核的struct有关系吗FILE是一个结构体.该结构体内部一定要有以下字段:FILE是C语言标准库提供的.FILE和我们刚刚讲的内核的struct没有关系,最多就是上下层的关系 做实验-重定向的本质第一个实验-文件描述符的分配规则第二个实验-输出重定向重定向的原理 第三个实验-输入重定向第四个实验-追加重定向结论需求:把常规消息放一个文件,错误消息放在另一个文件更好的写法 让我们自己的程序支持重定向: fd-文件描述符
任何一个进程在启动的时候默认会打开当前进程的三个文件
标准输入标准输出标准错误本质都是文件stdinstdoutstderr文件在语言层的表现cincoutcerr同上但是他是一个类012-fd ,数组下标
文件描述符即open对应的返回值本质就是数组下标 标准输出和标准错误都会向显示器打印但是其实是不一样的
类型设备文件标准输入键盘文件标准输出显示器文件标准错误显示器文件
#includeiostream
#includecstdioint main()
{//因为linux一切皆文件所以向显示器打印本质就是向文件中写入printf(hello printf-stdout\n); fprintf(stdout,hello fprintf-stdout\n);fprintf(stderr,hello fprintf-stderr\n);std::cout hello cout - cout std::endl;std::cerr hello cerr - cerr std::endl;
}int fd1 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);//3
int fd2 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);//4
int fd3 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);//5
int fd4 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);//6
int fd5 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);//7
int fd6 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);//8如何深度理解一切皆文件
我们使用OS的本质:
都是通过进程的方式进行操作系统的访问,在进程的角度,只能看到文件对象,而看不到底层的设备的区别,所以我们才说Linux下一切皆文件.
FILE
操作系统层面,我们必须使用fd才能找到文件! 任何语言层面访问外设或者文件,都必须经历OS
FILE是什么?谁提供的?和我们刚刚讲的内核的struct有关系吗
#includestdio.h
FILE* fopen(const char *path,const char* mode);答案:
FILE是一个结构体.该结构体内部一定要有以下字段:
fd证明:
int main()
{printf(%d\n,stdin-_fileno);printf(%d\n,stdout-_fileno);printf(%d\n,stderr-_fileno);FILE* fp fopen(LOG,w);printf(%d\n,fp-_fileno);
}FILE是C语言标准库提供的. 我们平时安装VS2019,是在安装IDE环境以及对应语言的库和头文件 FILE和我们刚刚讲的内核的struct没有关系,最多就是上下层的关系
做实验-重定向的本质
第一个实验-文件描述符的分配规则
把fd为3的文件关闭以后,新的文件fd应该是什么
int main()
{close(0);//fclose(stdin)close(2);//fclose(stderr)int fd1 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);int fd2 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);int fd3 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);int fd4 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);int fd5 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);int fd6 open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);printf(%d\n,fd1);0printf(%d\n,fd2);2printf(%d\n,fd3);3printf(%d\n,fd4);4printf(%d\n,fd5);5return 0;
}进程中,文件描述符的分配规则: 最小的,没有被使用的数组元素,分配给新文件 第二个实验-输出重定向
int main()
{fclose(1);int fd open(LOG, O_WRONLY | O_CREAT | O_TRUC, 0666);//此时log.txt的fd是1//但是上层结构不知道这个变化,他只知道要写进fd1的文件中printf(you can see me!\n);//本来是指向stdout - 1的,但是stdout变成了log.txtprintf(you can see me!\n);printf(you can see me!\n);printf(you can see me!\n);printf(you can see me!\n);return 0;
}结果:打印不到屏幕,但是打印到了log.txt printf(,);不是认stdout,而是认fd1的文件描述符
重定向的原理
在上层无法感知的情况下,在OS内部,更改进程对应的文件描述符表中,特定下标的指向!!
第三个实验-输入重定向
现在log.txt中写入:
123 456int main()
{fclose(0);int fd open(LOG, O_RDONLY | O_CREAT | O_TRUC, 0666);//fd0int a,b;scanf(%d %d,a,b);printf(a%d , b%d\n,a,b);return 0;
}结果: cat log.txt: a123 , b456
第四个实验-追加重定向
int main()
{close(1);//标准输出int fd open(LOG, O_RDONLY | O_CREAT | O_APPEND, 0666);printf(you can see me!\n);//从屏幕(stdout)上追加到fd中printf(you can see me!\n);printf(you can see me!\n);printf(you can see me!\n);
}结果: cat log.txt:
a123 , b456
you can see me!
you can see me!
you can see me!
you can see me!结论
所以stdout cout-1,他们都是向1号文件描述符对应的文件打印 stderr cerr -2 ,他们都是向2号文件描述符对应的文件打印 输出重定向,只改的是1号对应的指向,对2号不影响
需求:把常规消息放一个文件,错误消息放在另一个文件
#includestdio.h
#includesys/types.h
#includesys/stat.h
#includefcntl.h
#includeunistd.h
#includeerrno.h
#includestring.h
#define LOG log.txt
#define LOG_NORMAL logNormal.txt
#define LOG_ERROR logError.txtint main()
{close(1);int fd open(LOG_NORMAL, O_WRONLY | O_CREAT | O_APPEND, 0666);close(2);int fd open(LOG_ERROR, O_WRONLY | O_CREAT | O_APPEND, 0666);printf(hello printf-stdout\n); fprintf(stdout,hello fprintf-stdout\n);fprintf(stderr,hello fprintf-stderr\n);}
所以为什么要默认把1和2打开: 就是为了把常规消息和错误消息分类开来,便于后面的调试!
bash中重定向操作
a.out log.txt 2 1
或者
a.out 1log.txt 2err.txt2 1 把1里面的内容,写到2下标的内容里
更好的写法
int dup2(int oldfd, int newfd) 是对数组对应下标的内容进行拷贝 new要成为old的拷贝 所以最终只有oldfd的内容了 而我们最后正确重定向肯定是剩下3啊 所以oldfd 是3 newfd 是1 所以代码 dup2(fd,1)
重定向写法:
int main ()
{int fd open(LOG_NORMAL, O_WRONLY | O_CREAT | O_APPEND, 0666);if(fd 0){perrer(open);return 1;}dup2(fd,1);printf(hello world,hello lx\n);close(fd);
}就是打开文件,之后使用dup2就行
让我们自己的程序支持重定向:
enum redir{REDIR_INPUT 0,REDIR_OUTPUT,REDIR_APPEND,REDIR_NONE
};char* checkdir(char commandstr[],redir redir_type);
{//1.监测是否有 //2.如果有,要根据 设置redir_type ?//3.将符号改成\0,分成两部分//保存文件名,并返回//如果不满足,直接返回
}int main()
{while(1){redir redir_type REDIR_NONE//...char* filename NULL;char* filename checkdir(commandstr,redir_type);if(*filename){//1.存在文件//2.获取redir_type}//遍历,看是否有 ,这三个字符//前半部分执行后续//把这三个字符变成\0,将后面的字符串打开文件//dup2(fd,1);//...if(id 0){if(redir_typr ! REDIR_NONE){dup2();}}}
}未完待续…