stdout/stderr
stdout/stderr有啥区别呢??
1和2对应的都是显示器文件,但是他们两个是不同的,如同认为,同一个显示器文件,被打开了两次!
以下面这段代码为例。
#include <iostream> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> void myperror(const char *msg) { fprintf(stderr, "%s: %s\n", msg, strerror(errno)); } int main() { //stdout -> 1 printf("hello printf 1\n"); fprintf(stdout,"hello fprintf 1\n"); // stderr -> 2 errno = 1; perror("hello perror 2"); //stderr const char *s1 = "hello write 1\n"; write(1, s1, strlen(s1)); const char *s2 = "hello write 2\n"; write(2, s2, strlen(s2)); // cout -> 1 std::cout << "hello cout 1" << std::endl; // cerr -> 2 std::cerr << "hello cerr 2" << std::endl; return 0; }
运行结果
[hang@VM-4-12-centos day11]$ make g++ -o myfile myfile.cc [hang@VM-4-12-centos day11]$ ./myfile hello printf 1 hello fprintf 1 hello perror 2: Operation not permitted hello write 1 hello write 2 hello cout 1 hello cerr 2 [hang@VM-4-12-centos day11]$ ./myfile >log.txt hello perror 2: Operation not permitted hello write 2 hello cerr 2
分开打印到两个文件中
[hang@VM-4-12-centos day11]$ ./myfile >ok.txt 2>err.txt [hang@VM-4-12-centos day11]$ cat ok.txt hello write 1 hello printf 1 hello fprintf 1 hello cout 1 [hang@VM-4-12-centos day11]$ cat err.txt hello perror 2: Operation not permitted hello write 2 hello cerr 2 [hang@VM-4-12-centos day11]$
合起来打印到一个文件中
[hang@VM-4-12-centos day11]$ ./myfile >ok.txt 2>&1 [hang@VM-4-12-centos day11]$ ls Makefile myfile myfile.cc ok.txt [hang@VM-4-12-centos day11]$ cat ok.txt hello perror 2: Operation not permitted hello write 1 hello write 2 hello printf 1 hello fprintf 1 hello cout 1 hello cerr 2 [hang@VM-4-12-centos day11]$ [hang@VM-4-12-centos day11]$ cat < ok.txt >err.txt [hang@VM-4-12-centos day11]$ ls err.txt Makefile myfile myfile.cc ok.txt [hang@VM-4-12-centos day11]$ cat err.txt hello perror 2: Operation not permitted hello write 1 hello write 2 hello printf 1 hello fprintf 1 hello cout 1 hello cerr 2
perror
errno = 1; perror("hello perror 2"); //stderr
#include <iostream> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> void myperror(const char *msg) { fprintf(stderr, "%s: %s\n", msg, strerror(errno)); } int main() { int fd = open("log.txt", O_RDONLY); if(fd < 0) { myperror("open"); return 1; } return 0; }
电脑上的文件可以分为两类:被进程打开的,未被打开的。
前者被进程加载到内存中去,后者则存在于磁盘(磁盘级文件)
文件
站在单个文件的角度:这个文件在哪里?有多大?其他属性是什么?.........
站在系统的角度:一共有多少文件?各自的属性存储在哪里?如何快速找到?还可以存储多少文件?..........
文件系统的目的:如何对磁盘文件进行分类的存储,用来支持更好的存取!!
磁盘–永久性存储介质-SSD,U盘,flash卡,光盘,磁带
内存--掉电易失介质
磁盘是一个外设,是我们计算机唯一一个机械设备!这样注定了它的速度很慢,OS会有一些提速方式。
浅浅了解一下磁盘。
磁盘盘片,磁头,伺服系统,音圈马达...........
磁盘盘面会存储数据,由于计算机只认识二进制。联想到磁铁的正极和负极,就可以明白了;
向磁盘写入,本质就是改变磁盘上的正负极。
磁盘的基本结构
注意一个扇面的大小是512字节(通常)(磁盘存储数据的基本单位)。
在物理上,如何把数据写入到指定的扇区里?
如何找到一个扇区(CHS寻址)
1.在哪一个面上~(对应的就是哪一个磁头)
2.在哪一个磁道(柱面)上
3.在哪一个扇区上
如果我们有了chs,就能找到任意一个扇区,那么所有扇区我们就都能找到了!
通过将磁盘的存储方式进行逻辑化推演成线性结构。访问一个扇区,其实就由一个块组成的数组。计算机通过LBA寻址方式进行定位,然后转换成CHS进行磁盘定位。
对磁盘的管理采用分而治之 的思想,将整体拆分进行规划。
最终对磁盘的管理就精确到了一个小分区的管理。
块组组成
Linux在磁盘上存储文件的时候,将内容和属性是分开存储的!
Super Block:简单来说,就是文件系统的属性信息。复杂一些:存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了。
说人话:是整个分区的文件系统信息,不是单个块组的(不长眼的磁头)
Data blocks:多个4KB(扇区*8)大小的集合﹐保存的都是特定文件的内容
inode Table: inode是一个大小为128字节的空间,保存的是对应文件的属性
该块组内,所有文件的inode空间的集合,需要标识唯一性,每一个inode块,都要有一个inode编号!一般而言一个文件,一个inode,一个inode编号
BlockBitmap:假设有10000+个blocks,10000+比特位:比特位和特定的block是一一对应的,其中比特位为1,代表该block被占用,否则表示可用!
inode Bitmap:假设有10000+个inode节点,就有10000+个比特位,比特位和特定的inode是一一对应的。其中bitmap中比特为为1,代表该inode,被占用,否则表示可用!
GDT:块组描述符,这个块 组多大,已经使用了多少了,有多少个inode,已经行用了多少个,还剩多少,一共有多少个block,使用了多少....
BootBlock:启动块
这些区域让一个文件的信息可追溯,可管理。
将块组分割成上面的内容,并且写入相关的管理数据。其他块组类似,整个分区就被写入了文件信息系统!
我们可以发现的是,Linux在磁盘上存储文件的时候,是将内容和属性分开存储的!!!
磁盘的基本的单位扇区(512字节),但是操作系统(文件系统)和磁盘进行IO的基本单位是4kb(block大小,这也是磁盘被称为块设备的原因)。
为什么不以512字节为基本单位?
1.太小了,有可能会导致多次I0,进而导致效率的降低!
2.如果操作系统使用和磁盘一样的大小,万一磁盘基本大小变了的话,OS的源代码要不要改呢﹖硬件和软件(OS)进行解耦!
我们讲块组分割成为上面的内容--->>并且写入相关的管理数据->每一个块组都这么干---->>整个分区就被写入了文件系统信息!(相当于格式化)
1.那些block属于同一个文件?
2.找到文件,只要找到文件对应的inode编号,就能找到改文件的inode属性集合,可是,文件的内容?
data block中,不是所有的data block只能存文件数据。也可以存其他块的块号!!
寻找文件,首先通过inode编号---->>> 找到分区特定的块组(block group)---->>inode---->属性---->内容
我们通过依托于目录结构来知道inode编号!!
linux中,inode属性里面,没有文件名这样的说法!
分区格式化------->>>>在磁盘写入文件系统!
inode是固定的,datablock是固定的!
那么就有可能出现还有内存空间,但是却无法新建文件的现象。
目录是文件吗﹖是->有自己的inode,有自己的data block。在data block中存储的是文件名 ------inode编号的映射关系(互为key值)。
文件名对应的是用户,inode对应的是文件系统。
那这里我们又要想到一个东西,
进入目录所需权限:x
创建文件所需权限:w
显示文件名与属性:r
新增的
我们需要在目录文件中找到我们的对应的映射关系,那么如何找到目录文件呢??是需要到目录文件的上级目录下去寻找的。我们操作系统在寻找文件时,会在操作系统内核中生成一个目录树。这就是我们第一次查找文件时比较慢的原因。