【Linux】我的Linux系统级I/O及相关指令的操作文档

Linux中,较高级的I/O函数(如printf(),scanf()等)都是通过使用内核提供的系统级Unix I/O函数来实现的。虽然我们用起这些较高级的I/O函数都觉得非常顺手,但是学习系统级I/O函数仍存在许多意义,正如《深入理解计算机系统》一书中写道:

1.了解Unix I/O会帮助我们理解其他的系统概念。系统I/O与其他系统概念经常会形成循环依赖,比如I/O函数在系统进程创建和执行中非常重要,而进程的创建又在不同进程的文件共享中扮演着关键角色;
2.有时除了Unix系统级I/O以外别无选择。在某些重要的情况中,使用高级的I/O函数不太可能,比如:标准I/O库中没有提供读取文件元数据的方式,例如文件大小或文件创建时间。

了解完系统级I/O的重要性,接下来介绍一下本篇博客的主体目录:

  1. 基本的系统级I/O函数及其相应的参数
  2. 系统级I/O操作中运用的指令
  3. 《CSAPP》中推荐的I/O函数
  4. 总结

下面来进入我们的第一个部分:

1.基本的系统级I/O函数及其相应的参数

“Linux中,一切皆文件”,我的《深入了解计算机系统》的老师如是说道。一个功能完整的机器,所有的设备/文件等等是海量的,那么应当如何单独地描述标记一个文件呢?这时我们就需要引入一个文件描述符(fd,一个非负数)的概念。一个应用程序通过要求内核打开相应的文件时,内核会返回一个非负数,这个非负数就是这个相应的文件的文件标识符fd。

解释完fd是什么,进入正题。Unix I/O中,所有的I/O都由一种“统一而且一致的方式”来执行,各种Unix I/O函数如下:

  1. 打开文件:每个对文件的I/O操作必须要进行的操作,一个文件的fd也是在这个时候生成,并作为open()的返回值。
  2. Linux shell中创建时就有的文件:Linux shell作为用户访问内核的界面,创建的每一个进程都要有三个打开的文件:标准输入(fd=0)、标准输出(fd=1)、标准错误(fd=2)。头文件中定义了三个可以代替三个上述文件描述符的常量:STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO。由上述可知,每个自定义文件的fd都只能从3开始。
  3. 改变当前文件位置:对于每个打开后的文件,内核会保存其文件位置k,初始化为0。应用程序能通过seek操作,设置文件的位置。
  4. 读写文件:读操作就是从文件复制n>0个字节到内存,从当前文件位置k开始,然后改变文件的位置,从k变成k+n;特殊地,对一个字节大小为m<=k的文件,读操作会触发EOF,应用程序可以检测到。写操作类似。
  5. 关闭文件:内核会释放该文件所创建的各种数据结构(堆栈、等等),并将fd恢复到可用的描述符中(释放两件东西:数据结构+fd)。

(1).打开文件

open()的函数原型如下:

#include
#include
#include

int open(char *filename, int flags, mode_t mode);
/*返回值:若成功则返回文件fd,不成功则为-1。*/
/*函数参数:filename:文件名;flags:进程访问文件的方式对应的参数;mode:访问权限位*/

接下来对flags及mode进行进一步的解析:

i).flags参数


了解完各种flags,我们可以知道它与open()的多种联用:

fd=open("foo.txt",O_WRONLY|O_APPEND,0);
/*打开一个文件,并在后面追加一些数据。*/
fd=open("foo.txt",O_CREAT|O_TRUNC|O_WRONLY,DEF_MODE);
/*若文件名对应的文件不存在,则创建;*/
/*若文件名对应的文件存在,则截断(清空)文件内的原内容,并将权限设置为可写。*/

ii).访问权限位

各种访问权限位在头文件sys/stat.h中定义,以掩码的形式表现出来,如下:
【Linux】我的Linux系统级I/O及相关指令的操作文档_第1张图片

(2).关闭文件

代码如下,理解起来简单,故不作赘述:

#include

int close(int fd);
/*成功返回0,不成功返回-1.,,x'x*/

(3).读和写文件

系统级的读写主要是通过调用read()和write()实现的,他们的代码如下:;

include<unistd.h>

ssize_t read(int fd, void *buf, size_t n);
/*若成功则返回读的字节数,若EOF则返回0,若失败则返回-1。*/

ssize_t write(int fd, const void *buf, size_t n);
/*若成功则返回写入的字节数,若出错则为-1。*/
/*变量名解释:fd;文件描述符;buf:read()时读入字节的存储位置,write()时被写入字节的来源;n:读写操作字节数数量。*/

了解了这么多系统级的I/O函数,接下来看看在Linux命令符提示窗口下可能会帮助到我们使用系统级I/O的指令。

2.系统级I/O操作中运用的指令/参数

(1).ls指令

ls指令可以查看指定文件的目录结构(包括目录和文件夹),但只限于文件和文件夹的名称。比如接下来我们来用ls指令来查看根目录下的子目录(“/”代表根目录):
ls指令查看根目录

(2).cat指令

cat指令用于显示文件中的内容,语法为cat+(选项)+(文件列表参数/路径);
其选项有以下几种:cat参数
各自的运行截图如下:
【Linux】我的Linux系统级I/O及相关指令的操作文档_第2张图片
【Linux】我的Linux系统级I/O及相关指令的操作文档_第3张图片

(3).chmod指令

chmod指令用于改变文件的属性(即改变文件的访问权限位),语法为chmod+mode+file;其中mode代表权限设定字串,格式为:[ugoa][±=][rwxX];其中:

  1. [ugoa]:代表文件的各类操作对象,u:user,用户本身;g:group of user,用户所在的群体;o:前两者之外的人;a:all。
  2. [±=]:+:代表增加权限;-:代表减少权限;=:代表唯一设定权限;
  3. [rwxX]:r:可读;w:可写;x:可执行;X:该档案是个子目录,或者该档案已经被设置为可执行。

下面使用上述指令给出例子:

  • 将file.txt设置为所有人皆可读取:chmod ugo+r file.txt
  • 将file.txt设置为仅使用者可以执行:chmod u+x file.txt

(4).cp指令

cp指令用于复制文件或者文件夹,它有两种用法:

  1. 用法一:一对一(此处目标为文件)复制:$ cp src-file target-file
  2. 用法二:多对一(此处目标为文件夹)复制:$ cp src1 src2 src3 ... target-directory

了解完系统级I/O和相关的Linux指令,我们来看《CSAPP》一书中推荐的I/O函数:

3.《CSAPP》推荐的I/O函数

《CSAPP》中有如下几条关于I/O函数使用的原则:

  1. 只要有可能就一定使用系统I/O;
  2. 不要用scanf()或者rio_readlineb()来读取二进制文件:scanf()这样的函数是专门用来读取文本文件的,而二进制文件中经常会散布着许多无意义的0xa,读取时必会产生“诡异莫测”的错误;
  3. 对网络套接字的I/O使用RIO(健壮的I/O)函数。

4.总结

以上便是我个人对于Linux系统级I/O及相关指令操作文档的汇总,其中包含了系统级I/O函数的汇总,一些十分有用且有趣的Linux指令,以及《CSAPP》一书中对于I/O函数使用的建议。希望这能对大家有所帮助。

你可能感兴趣的:(【Linux】我的Linux系统级I/O及相关指令的操作文档)