Linux第八次学习笔记
2015-11-08 20:48
585 查看
#系统级I/O
输入/输出(I/O)是在主存和外部设备之间拷贝数据的过程。
输入操作是从I/O设备拷贝数据到主存。
I/O→主存
输出操作是从主存拷贝数据到I/O设备。
主存→I/O
##Unix I/O
所有的I/O设备都被模型化为文件。
所有的输入和输出都被当作对相应文件的读和写来执行。
打开文件
应用程序通过要求内核打开相应的文件,来宣告它想要访问一个I/O设备。
内核返回一个小的非负整数,称为描述符。
内核记录有关这个打开文件的所有信息。
应用程序只需要记住操作符即可。
创建每个进程开始时三个打开的文件
标准输入(描述符为0)|STDIN_FILENO
标准输出(描述符为1)|STDOUT_FILENO
标准错误(描述符为2)|STDERR_FILENO
改变当前的文件位置
对于打开的文件,内核保存着该文件的位置k,初始值为0
k为从文件开头起始的字节偏移量
应用程序通过执行seek操作,显式地设置文件的当前位置为k
读写文件
读操作:
从文件拷贝n>0个字节到存储器
从当前文件位置k开始
将k增加到k+n
给定一个大小为m字节的文件,当k≥m时(即当前文件位置已到文件尾),此时执行读操作会触发end-of-file(EOF)条件。
在文件的结尾并未明确的EOF符号
写操作:
从存储器拷贝n>0个字节到一个文件
从当前文件位置k开始
更新k
关闭文件
应用完成对文件的访问后,会通知内核关闭该文件。
内核释放文件打开时创建的数据结构,并恢复描述池。
无论一个进程因为何种原因终止,内核都会关闭所有打开的文件并释放它们的存储器资源。
##打开和关闭文件
sys/types.h 基本系统数据类型,其中包括核心地址、系统时间、设备号、文件描述集、文件位置等类型。
sys/stat.h 用于获取一个文件的所有信息,包括文件对应的模式、设备号码、文件所有者、最后被访问的时间、最后被修改的时间等。ls -l命令就用到了该头文件中所包含的类型。
fcntl.h 文件信息控制类型(file control),定义了很多宏和open.fcntl函数原型。
####open函数
char *filename 参数filename指向欲打开的文件路径字符串。
int flags 旗标
O_RDONLY 以只读方式打开文件
#define O_RDONLY 00
O_WRONLY 以只写方式打开文件
#define O_WRONLY 01
O_RDWR 以可读写方式打开文件。
#define O_RDWR 02
上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。
O_CREAT 若欲打开的文件不存在则自动建立该文件。
#define O_CREAT 00000100
O_TRUNC 若文件存在并且以可写的方式打开时,此旗标会令文件长度清为0,而原来存于该文件的资料也会消失。
#define O_TRUNC 00001000
O_APPEND 当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面。
#define O_APPEND 00002000
mode_t mode 文件权限标志
文件权限标志也可以用加权数字表示,这组数字被成为umask变量,它的类型是mode_t,是一个无符号八进制数。
umask变量由3位数字组成,数字的每一位代表一类权限,用户所获得的权限是加权数值的总和。
例如764表示所有者拥有读、写和执行权限,群组拥有读和写权限,其他用户拥有读权限。
0表示没有任何权限。
每个程序都有一个umask的值,并且默认为022。可以通过umask()函数调用设置。
umask()会将系统umask值设成参数mask&0777后的值,然后将先前的umask值返回。在使用open()建立新文件时,该参数 mode并非真正建立文件的权限,而是(mode& ~umask)的权限值。
例如,在建立文件时指定文件权限为0666,通常umask值默认为 022,则该文件的真正权限则为0666&~022=0644
书上例子解析:
返回值 若成功则为新文件描述符,若出错为-1。返回的描述符总是在进程中当前没有打开的最小描述符。
示例:fd = open("foo.txt",O_WRONLY|O_APPEND,0)
表示打开一个已存在的文件,并在后面添加一些数据。
###close函数
unistd.h 提供了close()函数。
返回值:成功返回0,出错返回-1并设置errno
参数fd是要关闭的文件描述符。
需要说明的是,当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close关闭,所以即使用户程序不调用close,在终止时内核也会自动关闭它打开的所有文件。
若省略fd,则将关闭Open语句打开的所有活动文件。
##读和写文件
###读文件
fd 文件描述符
*buf 缓冲区指针,用于保存读出来的数据。
n 所需要读取的字节数
返回值类型为ssize_t 表示有符号的size_t。
size_t(size type),表示一种整型类型,包含int、long等。
返回所读取的字节数;0(读到EOF);-1(出错)。
以下几种情况会导致读取到的字节数小于 n :
读取普通文件时,读到文件末尾还不够 n 字节。例如:如果文件只有 30 字节,而我们想读取 100 字节,那么实际读到的只有 30 字节,read 函数返回 30 。此时再使用 read 函数作用于这个文件会导致 read 返回 0 。
从终端设备(terminal device)读取时,一般情况下每次只能读取一行。
从网络读取时,网络缓存可能导致读取的字节数小于 n字节。
读取 pipe 或者 FIFO 时,pipe 或 FIFO 里的字节数可能小于 n 。
从面向记录(record-oriented)的设备读取时,某些面向记录的设备(如磁带)每次最多只能返回一个记录。
在读取了部分数据时被信号中断。
###写文件
fd 文件描述符
const void *buf 数据来源buf,const所描述的对象具有不变性,不可更新。
n 从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。
返回值 一般等于n,否则就是出错。
常见出错的原因:
磁盘空间满了
超过文件大小限制
###书上cpstdin.c代码测试
书上的源代码仅为理论上讲述的程序,说明了一次一个字节地从标准输入拷贝到标准输出的功能,但是并未有明显的表示。所以我将代码修改了,通过两个文件foo.txt与foo1.txt来体现该功能。
foo.txt文档中存放着123456的文本
foo1.txt为空文档。
代码功能将foo.txt中的文本一次一个地写入foo1.txt文档中。
代码如下:
运行结果如下:
##用RIO包健壮地读写
RIO(Robust I/O,健壮地I/O)包:它会自动为你处理不足值。
不足值:read和write传送的字节比应用程序要求地要少。
RIO提供了两类不同的函数:
无缓冲的输入输出函数。 没有应用级缓冲,它们对将二进制数据读写到网络和从网络读写二进制数据尤其有用。
带缓冲的输入函数。 高效地从文件中读取文件行和二进制数据,这些文件的内容缓存在应用级缓存区内。
###RIO的无缓冲的输入输出函数
通过调用rio_readn和rio_writen函数,应用程序可以在存储器和文件之间直接传送数据。
void *usrbuf 存储器位置
size_t n 传送的字节数
返回值 若成功则为传送的字节数,若EOF则为0,若出错则为-1
功能 从描述符fd的当前文件位置最多传送n个字节到存储器位置usrbuf。
void *usrbuf 存储器位置
size_t n 传送的字节数
返回值 若成功则为传送的字节数,若出错则为-1
功能 从位置usrbuf传送n个字节道描述符fd。
###RIO带缓冲地输入函数
一个文本行就是一个由换行符结尾的ASCII码字符序列。
在Unix系统中,换行符的数值未0x0a。
每打开一个描述符都会调用一次rio_readinitb,它将描述符fd和地址rp处的一个类型为rio_t的读缓冲区练习起来。
rio_t 设置一个地址
void *usrbuf 缓存区地址
size_t maxlen 读取的最大长度
返回值 若成功则为传送的字节数,若EOF则为0,若出错则为-1
功能 从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时,会自动地调用read重新填满缓冲区。
rio_readlineb函数最多读maxlen-1个字节,余下的一个字符留给结尾的空字符。
超过maxlen-1字节的文本行被截断,并用一个空字符结束。
ssize_t rio_readnb(rio_t *rp,void *usrbuf,size_t n);
rio_t 设置一个地址
void *usrbuf 缓存区地址
size_t maxlen 读取的最大长度
返回值 若成功则为传送的字节数,若EOF则为0,若出错则为-1
功能 对于既包含文本行也包含二进制数据的文本,进行拷贝文本行操作。
从文件rp最多读n个字节道存储器位置usrbuf。
####对同一描述符,对rio_readlineb和rio_readnb的调用可以任意交叉进行,但不应该和无缓冲的rio_readn函数交叉使用。
##读取文件元数据
应用程序能够通过调用stat和fstat函数,检索到关于文件的信息(也称为文件的元数据)。
filename 文件名
struct stat *buf 结构体stat中各个成员,如下:
int fd 文件描述符
不同的文件类型
普通文件
目录文件
网络套接字
宏指令根据st_mode成员来确定文件的类型
S_ISREG() —— 这是一个普通文件吗?
S_ISDIR() —— 这是一个目录文件吗?
S_ISSOCK() —— 这是一个网络套接字吗?
##共享文件
内核用三个数据结构来表示打开的文件:
描述符表
每个进程都有它独立的描述符表
文件表
打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。
每个文件表的表项组成:
当前的文件位置
引用计数
指向v-node表中对应表项的指针
v-node表
所有的进程共享这张v-node表。
##I/O重定向
利用dup2函数进行I/O重定向工作
dup2函数拷贝描述符表表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前的内容。
如果newfd已经打开了,dup2会在拷贝oldfd之前关闭newfd。
##标准I/O
ANSI C定义了一组高级输入输出函数,成为标准I/O库。
提供了打开和关闭文件的函数(fopen/fclose)
读和写字节的函数(fread/fwrite)
读和写字符串的函数(fgets/fputs)
复杂的格式化的I/O函数(scanf/printf)
标准I/O库将一个打开的文件模型化为一个流。
每个ANSI C程序开始时都有三个打开的流stdin、stdout和stderr。
类型为FILE的流是对文件描述符和流缓冲区的抽象。
##参考资料
1.《Computer.Systems.A.Programmer's.Perspective.2nd.CN》教材
2.《打开文件、新建文件和关闭文件操作》http://book.51cto.com/art/200912/169537.htm
3.《linux下的文件操作函数》http://jingyan.baidu.com/article/6dad5075c33056a123e36ecf.html
4.《linux下的umask()函数》http://www.360doc.com/content/12/0605/16/9305922_216186419.shtml
输入/输出(I/O)是在主存和外部设备之间拷贝数据的过程。
输入操作是从I/O设备拷贝数据到主存。
I/O→主存
输出操作是从主存拷贝数据到I/O设备。
主存→I/O
##Unix I/O
所有的I/O设备都被模型化为文件。
所有的输入和输出都被当作对相应文件的读和写来执行。
打开文件
应用程序通过要求内核打开相应的文件,来宣告它想要访问一个I/O设备。
内核返回一个小的非负整数,称为描述符。
内核记录有关这个打开文件的所有信息。
应用程序只需要记住操作符即可。
创建每个进程开始时三个打开的文件
标准输入(描述符为0)|STDIN_FILENO
标准输出(描述符为1)|STDOUT_FILENO
标准错误(描述符为2)|STDERR_FILENO
改变当前的文件位置
对于打开的文件,内核保存着该文件的位置k,初始值为0
k为从文件开头起始的字节偏移量
应用程序通过执行seek操作,显式地设置文件的当前位置为k
读写文件
读操作:
从文件拷贝n>0个字节到存储器
从当前文件位置k开始
将k增加到k+n
给定一个大小为m字节的文件,当k≥m时(即当前文件位置已到文件尾),此时执行读操作会触发end-of-file(EOF)条件。
在文件的结尾并未明确的EOF符号
写操作:
从存储器拷贝n>0个字节到一个文件
从当前文件位置k开始
更新k
关闭文件
应用完成对文件的访问后,会通知内核关闭该文件。
内核释放文件打开时创建的数据结构,并恢复描述池。
无论一个进程因为何种原因终止,内核都会关闭所有打开的文件并释放它们的存储器资源。
##打开和关闭文件
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(char *filename,int flags,mode_t mode)
sys/types.h 基本系统数据类型,其中包括核心地址、系统时间、设备号、文件描述集、文件位置等类型。
sys/stat.h 用于获取一个文件的所有信息,包括文件对应的模式、设备号码、文件所有者、最后被访问的时间、最后被修改的时间等。ls -l命令就用到了该头文件中所包含的类型。
fcntl.h 文件信息控制类型(file control),定义了很多宏和open.fcntl函数原型。
####open函数
char *filename 参数filename指向欲打开的文件路径字符串。
int flags 旗标
O_RDONLY 以只读方式打开文件
#define O_RDONLY 00
O_WRONLY 以只写方式打开文件
#define O_WRONLY 01
O_RDWR 以可读写方式打开文件。
#define O_RDWR 02
上述三种旗标是互斥的,也就是不可同时使用,但可与下列的旗标利用OR(|)运算符组合。
O_CREAT 若欲打开的文件不存在则自动建立该文件。
#define O_CREAT 00000100
O_TRUNC 若文件存在并且以可写的方式打开时,此旗标会令文件长度清为0,而原来存于该文件的资料也会消失。
#define O_TRUNC 00001000
O_APPEND 当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面。
#define O_APPEND 00002000
mode_t mode 文件权限标志
1. S_IRUSR 所有者拥有读权限 2. S_IWUSR 所有者拥有写权限 3. S_IXUSR 所有者拥有执行权限 4. S_IRGRP 群组拥有读权限 5. S_IWGRP 群组拥有写权限 6. S_IXGRP 群组拥有执行权限 7. S_IROTH 其他用户拥有读权限 8. S_IWOTH 其他用户拥有写权限 9. S_IXOTH 其他用户拥有执行权限
文件权限标志也可以用加权数字表示,这组数字被成为umask变量,它的类型是mode_t,是一个无符号八进制数。
umask变量由3位数字组成,数字的每一位代表一类权限,用户所获得的权限是加权数值的总和。
例如764表示所有者拥有读、写和执行权限,群组拥有读和写权限,其他用户拥有读权限。
0表示没有任何权限。
每个程序都有一个umask的值,并且默认为022。可以通过umask()函数调用设置。
umask()会将系统umask值设成参数mask&0777后的值,然后将先前的umask值返回。在使用open()建立新文件时,该参数 mode并非真正建立文件的权限,而是(mode& ~umask)的权限值。
例如,在建立文件时指定文件权限为0666,通常umask值默认为 022,则该文件的真正权限则为0666&~022=0644
书上例子解析:
#define DEF_MODE S_IRUSER|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH //拥用者、群组、其他人都拥有读写权限,相当于666 #define DEF_MASK S_IWGRP|S_IWOTH //用户组、其他人拥有写权限,相当于022 umask(DEF_UMASK); //将当前的umask值设置成022 fd = open("foo.txt",O_CREAT|O_TRUNC|O_WRONLY,DEF_MODE); //DEF_MODE此时的值应该为DEF_MODE &~DEF_UMASK,即666&~022=644,则文件的拥有者有读写权利,所有其他的用户只有读权利。
返回值 若成功则为新文件描述符,若出错为-1。返回的描述符总是在进程中当前没有打开的最小描述符。
示例:fd = open("foo.txt",O_WRONLY|O_APPEND,0)
表示打开一个已存在的文件,并在后面添加一些数据。
###close函数
#include <unistd.h> int close(int fd);
unistd.h 提供了close()函数。
返回值:成功返回0,出错返回-1并设置errno
参数fd是要关闭的文件描述符。
需要说明的是,当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close关闭,所以即使用户程序不调用close,在终止时内核也会自动关闭它打开的所有文件。
若省略fd,则将关闭Open语句打开的所有活动文件。
##读和写文件
###读文件
#include <unist.h> ssize_t read(int fd,void *buf,size_t n);
fd 文件描述符
*buf 缓冲区指针,用于保存读出来的数据。
n 所需要读取的字节数
返回值类型为ssize_t 表示有符号的size_t。
size_t(size type),表示一种整型类型,包含int、long等。
返回所读取的字节数;0(读到EOF);-1(出错)。
以下几种情况会导致读取到的字节数小于 n :
读取普通文件时,读到文件末尾还不够 n 字节。例如:如果文件只有 30 字节,而我们想读取 100 字节,那么实际读到的只有 30 字节,read 函数返回 30 。此时再使用 read 函数作用于这个文件会导致 read 返回 0 。
从终端设备(terminal device)读取时,一般情况下每次只能读取一行。
从网络读取时,网络缓存可能导致读取的字节数小于 n字节。
读取 pipe 或者 FIFO 时,pipe 或 FIFO 里的字节数可能小于 n 。
从面向记录(record-oriented)的设备读取时,某些面向记录的设备(如磁带)每次最多只能返回一个记录。
在读取了部分数据时被信号中断。
###写文件
#include <unist.h> sszize_t write(int fd,const void *buf,size_t n);
fd 文件描述符
const void *buf 数据来源buf,const所描述的对象具有不变性,不可更新。
n 从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。
返回值 一般等于n,否则就是出错。
常见出错的原因:
磁盘空间满了
超过文件大小限制
###书上cpstdin.c代码测试
书上的源代码仅为理论上讲述的程序,说明了一次一个字节地从标准输入拷贝到标准输出的功能,但是并未有明显的表示。所以我将代码修改了,通过两个文件foo.txt与foo1.txt来体现该功能。
foo.txt文档中存放着123456的文本
foo1.txt为空文档。
代码功能将foo.txt中的文本一次一个地写入foo1.txt文档中。
代码如下:
/* $begin cpstdin */ #include "csapp.h" #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(void) { char c = 1; int fd1,fd2; fd1 = open("foo.txt",O_RDWR);//打开foo.txt,并将文件描述符保存至fd1 fd2 = open("foo1.txt",O_RDWR);//打开 foo1.txt,并将文件描述符保存至fd2 while(read(fd1,&c, 1) != 0)//当未读到EOF,则循环进行 write(fd2, &c, 1);//将一个字符写入foo1.txt中 exit(0); } /* $end cpstdin */
运行结果如下:
##用RIO包健壮地读写
RIO(Robust I/O,健壮地I/O)包:它会自动为你处理不足值。
不足值:read和write传送的字节比应用程序要求地要少。
RIO提供了两类不同的函数:
无缓冲的输入输出函数。 没有应用级缓冲,它们对将二进制数据读写到网络和从网络读写二进制数据尤其有用。
带缓冲的输入函数。 高效地从文件中读取文件行和二进制数据,这些文件的内容缓存在应用级缓存区内。
###RIO的无缓冲的输入输出函数
通过调用rio_readn和rio_writen函数,应用程序可以在存储器和文件之间直接传送数据。
#include "csapp.h" ssize_t rio_readn(int fd,void *usrbuf,size_t n);
void *usrbuf 存储器位置
size_t n 传送的字节数
返回值 若成功则为传送的字节数,若EOF则为0,若出错则为-1
功能 从描述符fd的当前文件位置最多传送n个字节到存储器位置usrbuf。
#include "csapp.h" ssize_t rio_writen(int fd,viod *usrbuf,size_t n);
void *usrbuf 存储器位置
size_t n 传送的字节数
返回值 若成功则为传送的字节数,若出错则为-1
功能 从位置usrbuf传送n个字节道描述符fd。
###RIO带缓冲地输入函数
一个文本行就是一个由换行符结尾的ASCII码字符序列。
在Unix系统中,换行符的数值未0x0a。
#include "csapp.h" void rio_readinitb(rio_t *rp,int fd);
每打开一个描述符都会调用一次rio_readinitb,它将描述符fd和地址rp处的一个类型为rio_t的读缓冲区练习起来。
ssize_t rio_readlineb(rio_t *rp,void *usrbuf,size_t maxlen);
rio_t 设置一个地址
void *usrbuf 缓存区地址
size_t maxlen 读取的最大长度
返回值 若成功则为传送的字节数,若EOF则为0,若出错则为-1
功能 从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时,会自动地调用read重新填满缓冲区。
rio_readlineb函数最多读maxlen-1个字节,余下的一个字符留给结尾的空字符。
超过maxlen-1字节的文本行被截断,并用一个空字符结束。
ssize_t rio_readnb(rio_t *rp,void *usrbuf,size_t n);
rio_t 设置一个地址
void *usrbuf 缓存区地址
size_t maxlen 读取的最大长度
返回值 若成功则为传送的字节数,若EOF则为0,若出错则为-1
功能 对于既包含文本行也包含二进制数据的文本,进行拷贝文本行操作。
从文件rp最多读n个字节道存储器位置usrbuf。
####对同一描述符,对rio_readlineb和rio_readnb的调用可以任意交叉进行,但不应该和无缓冲的rio_readn函数交叉使用。
##读取文件元数据
应用程序能够通过调用stat和fstat函数,检索到关于文件的信息(也称为文件的元数据)。
#include <unistd.h> #include <sys/stat.h> int stat(const char *filename,struct stat *buf);
filename 文件名
struct stat *buf 结构体stat中各个成员,如下:
struct stat { mode_t st_mode; //文件对应的模式,文件,目录等 ino_t st_ino; //inode节点号 dev_t st_dev; //设备号码 dev_t st_rdev; //特殊设备号码 nlink_t st_nlink; //文件的连接数 uid_t st_uid; //文件所有者 gid_t st_gid; //文件所有者对应的组 off_t st_size; //普通文件,对应的文件字节数 time_t st_atime; //文件最后被访问的时间 time_t st_mtime; //文件内容最后被修改的时间 time_t st_ctime; //文件状态改变时间 blksize_t st_blksize; //文件内容对应的块大小 blkcnt_t st_blocks; //伟建内容对应的块数量 }; int fstat(int fd,struct stat *buf);
int fd 文件描述符
不同的文件类型
普通文件
目录文件
网络套接字
宏指令根据st_mode成员来确定文件的类型
S_ISREG() —— 这是一个普通文件吗?
S_ISDIR() —— 这是一个目录文件吗?
S_ISSOCK() —— 这是一个网络套接字吗?
##共享文件
内核用三个数据结构来表示打开的文件:
描述符表
每个进程都有它独立的描述符表
文件表
打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。
每个文件表的表项组成:
当前的文件位置
引用计数
指向v-node表中对应表项的指针
v-node表
所有的进程共享这张v-node表。
##I/O重定向
利用dup2函数进行I/O重定向工作
#include <unistd.h> int dup2(int oldfd,int newfd);
dup2函数拷贝描述符表表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前的内容。
如果newfd已经打开了,dup2会在拷贝oldfd之前关闭newfd。
##标准I/O
ANSI C定义了一组高级输入输出函数,成为标准I/O库。
提供了打开和关闭文件的函数(fopen/fclose)
读和写字节的函数(fread/fwrite)
读和写字符串的函数(fgets/fputs)
复杂的格式化的I/O函数(scanf/printf)
标准I/O库将一个打开的文件模型化为一个流。
每个ANSI C程序开始时都有三个打开的流stdin、stdout和stderr。
类型为FILE的流是对文件描述符和流缓冲区的抽象。
##参考资料
1.《Computer.Systems.A.Programmer's.Perspective.2nd.CN》教材
2.《打开文件、新建文件和关闭文件操作》http://book.51cto.com/art/200912/169537.htm
3.《linux下的文件操作函数》http://jingyan.baidu.com/article/6dad5075c33056a123e36ecf.html
4.《linux下的umask()函数》http://www.360doc.com/content/12/0605/16/9305922_216186419.shtml
相关文章推荐
- Linux下进行SVN迁移
- Linux命令之cut
- Linux文件/文件夹操作命令
- linux计划任务
- 【未完待补充】linux 设置So动态库链接路径
- Linux下搭LNMP
- 多系统(window下安装linux)
- 虚拟机安装centos
- LINUX 系统运维转向运维开发
- Linux下JAVA串口通信
- Linux环境下C程序启动、终止分析
- Linux 压缩与解压缩文件
- linux给用户添加sudo权限:
- 老王学linux-ftp
- centos中Read-only file system
- u-boot加载Linux过程
- Linux设置FQDN
- 【鸟哥的linux私房菜-学习笔记】磁盘配额 (Quota)、磁盘阵列 (RAID)、逻辑卷轴管理员 (LVM) 初步了解
- Centos7的相关问题
- Linux-chown and chmod 命令的使用