Linux文件操作(一)
使用文件
在这一部分当中,我们将会讨论Linux的文件以及目录以及如何来管理他们.我们将会学习创建文件,打开文件,读取文件,写入文件以及关闭文件.我们也将会学习程序如何来管理目录(例如创建,扫描,删除).在上一部分当中我们使用Shell进行编程,而现在我们要开始使用C编程.
在讨论Linux处理文件I/O之前,我们将会看一些与文件,目录以及设备相关的概念.要处理文件与目录,我们需要使用系统调用(与Windows API相类似的Unix/Linux调用),但是也存在着一系列的库函数,标准I/O库(stdio),来使得我们的文件处理更为有效.
在这里我们要将讨论处理文件和目录的各种调用,所以我们将会谈到下面的一些内容:
1 文件与设备
2 系统调用
3 库函数
4 低层文件访问
5 文件管理
6 标准I/O库
7 格式化输入与输出
8 文件与目录维护
9 目录扫描
10 错误
11 /proc文件系统
12 高级主题:fcntl与mmap
Linux文件
也许有人会问:为什么?我们要来讨论文件结构吗?我们已经知道这些了.不错,与Unix中相类似,文件在Linux环境中是相当重要的,因为他们提供了简单并一致的接口来处理系统服务与设备.在Linux中,一切都是文件.这就意味着,在Linux中,程序可以像处理普通文件一样来使用磁盘文件,串口,打印机以及其他的设备.而目录,也是一类特殊的文件.在现代的Unix版本中,包括Linux,甚至是超级用户也不可以对他们直接进行写入操作.所有的普通用户使用高层的opendir/readdir接口来读取目录,而不需要知道目录实现的系统细节.我们稍后将会讨论特殊的目录函数.确实,在Linux下,所有的内容都被看成文件,或者是通过特殊的文件可以访问.即便这样,也存在着一些主要的原则,而这与我们平常所了解和喜爱的文件是不同的.现在我们来看一下我们谈到的特殊情况.
目录
与他的内容一样,一个文件有文件名和一些属性,或者是管理信息;也就是说是这些文件的创建/修改日期与访问权限.这些属性存放在文件的I节点(inode)中,所谓的I节点是文件系统中一个特殊数据块,包含着文件的长度以及在磁盘上的存放位置等信息.系统使用文件的I节点数目,目录结构只是为我们的方便进行文件的命名.
一个目录就是一个包含I节点数目以及其他文件名的文件.每一个目录实体都是指向一个文件I节点的链接,删除了这个文件名,我们也就删除了这个链接(我们可以使用ls -i命令来查看一个文件的I节点数).使用ln命令,我们可以创建在不同的目录中指向同一个文件的链接.如果指向一个文件的链接数(也就是ls -l命令输出中权限后的数字)为零,那么他所指向的I节点和数据就不再使用并标记为空闲.
文件排列在目录,而其中一些也许还会有子目录.这样就形成了我们所熟悉的文件系统结构.一个名为neil用户,通常将他的文件存放在home目录中,也许是/home/neil,而在其中也许会存在一些e-mail等一些子目录.在这里我们要注意就是在Unix和Linux Shell中都有一个直接到达我们的用户主目录的命令,也就是~.如果要进入其他用户的目录,我们可以输入~user.正如我们所知道的,每一个用户的home目录都是因为这个特殊的原因而创建的高层目录的子目录,在这里是/home.
在这里我们要注意的就是在标准的库函数中并不支持文件名参数的~符号.
/home目录只是根目录/的一个子目录,根目录是文件系统层次的最高层并且在其子目录中包含所有的系统文件.root目录通常包含有系统程序的/bin目录,系统配置文件的/etc目录,系统库的/l
linux怎么读取windows文件ib目录.代表物理设备并提供处理这些设备的接口的文件位于/dev目录中.我们可以在Linux File System Stander上查到更为详细的内容,或者是我们可以使用man hier命令来得到更为详细的描述.
文件与设备
甚至是硬件设备也会表示成为文件.例如,作为超级用户,我们可以将CD-ROM挂载作为一个文件:
# mount -t iso9660 /dev/hdc /mnt/cdrom
# cd /mnt/cdrom
这样就会启动CD-ROM设备,并将其当将的内容作为/mnt/cdrom文件结构分枝.我们可以像平常的文件一样进入CD-ROM目录,当然,此时这些内容都是只读的.
在Unix和Linux中常见了的三个最重要的设备为/dev/console,/dev/tty和/dev/null.
/dev/console
这个设备代表系统控制台.错误以及论断信息常会发到这个设备.每一个Unix系统都会有一个指定的终端或是屏幕来接收控制台信息.曾经,这是一个复杂的打印终端.在现代的工作站或是Linux中,他通常是一个活动的虚拟控制台,而在X下,则会是在屏幕上的一个特殊的控制窗口.
/dev/tty
/dev/tty是一个进程控制终端的别名,如果有这样的一个进程.例如,由cron运行的进程并不会有一个控制终端,所以他不会打开/dev/tty.
在他可以使用的地方,/dev/tty允许程序将信息直接写给用户,而不需要考虑用户正在使用何种终端.他在标准输出重定向时相当有用.一个例子就是ls -R | more命令,在这里more可以用输出的每一个新页来提示给用户.
在这里我们要注意的是,虽然只有一个/dev/console设备,但是却可以通过/dev/tty来访问多个不同的物理设备.
/dev/null
这是一个空设备.所有写入这个设备的信息都会被丢弃.当读取这个文件时将会立刻到达文件的结尾处,这样他就可以作为使用cp命令的一个空的文件源.所有不希望看到的输出都可以重定向到这个设备.
另一个创建新文件的方法就是使用touch <filename>命令,他将修改一个文件的修改日期,而如果这个文件不存在则会创建这个文件.然而他并不会清空他的内容.
$ echo do not want to see this >/dev/null
$ cp /dev/null empty_file
其他可以在/dev目录中到的设备有硬盘,软盘,通信口,磁带,CD-ROM,声卡以及一些代表系统内部状态的设备.还有一个设备/dev/zero,他可以作为一个空字节的源来创建一个文件大小为零的文件.我们需要超级用户的权限来访问其中的一些设置.普通的用户不可以使用程序来直接访问类似于硬盘这样的低层设备.设备名也许会由系统的不同而不同.在Linux发行版本中通常会有一个需要超级用户来运行的程序来管理这些设备文件,例如mount命令.
设备可以分为字符设备与块设备.区别就在于一些设备需要一次访问一个块.块设备通常是指
那些支持随机存取的文件系统,如硬盘.
系统调用与设备驱动
我们可以使用一些函数来访问和控制设备文件.这些函数就是所谓的系统调用,是由Unix/Linux直接提供的到操作系统的接口.
在操作系统的核心,内核,是大量的设备驱动.这是控制系统硬件的低层接口的集合.例如会有一个磁带驱动,他可以知道如何来启动磁带,向前或是向后,读或是写.他同时知道磁带每次要写入一定大小的数据块.因为磁带是顺序存取的,驱动器不可以直接访问磁带块,而是必须要转到的指定的位置.
与此相类似,低层硬盘设备也会每一次写入一个指定的磁盘块,但是可以直接访问所需的磁盘块,因为磁盘是随机存取的设备.为了提供一个相似的接口,硬盘驱动器封装了所有依赖于硬件的特征.硬件的材质特征我们可以通过ioctl得到.
/dev中的设备文件可以用同样的方法来使用,他们可以打开,读取,写入和关闭.例如用来打开一个常规文件的open调用可以用来访问一个用户终端,一个打印机或是磁带.
用来访问设备驱动器的代层系统调用包括:
1 open:打开一个文件或是设备
2 read:从一个打开的文件或是设备读
3 write:写入一个文件或是设备
4 close:关闭文件或是设备
5 ioctl:向设备驱动器传递控制信息
ioctl系统调用用来提供必须的硬件控制,所以他会因设备的不同而不同.例如,ioctl调用可以用来重定位磁带或是设置串口的字符流.正是由于这个原因,ioctl从一个机器到另一个机器并不是必须移植的.另外每一个驱动器定义了自己的ioctl命令集.
库函数
直接使用低层的系统来进行输入与输出所存在的问题就是这样的方式并不是十分的有效.为什么呢?
1 使用系统调用会有一个不好的结果.与函数调用比较起来系统调用要浪费大量的资源,因为这时Linux要在执行我们的程序代码与执行他的内核代码之间进行切换.一个好的方法是尽量使得在一个程序中所用到的系统最少,同时要使得每一个系统调用做尽可能多的工作,例如,每一次要读出或是写入大量的数据,而不是第一次只读写一个字符.
2 由于硬件的限制会在每一次使用低层系统调用来读写的数据尺寸上有许多的限制.例如,对于磁带驱动器来说,他们每一次可以写入的数据块的大小为10k.所以如果我们每一次要写入的数据块大小并不是10k的整倍数,那么磁带就会向前到下一个10k处,这时就会在磁带上留下一段空白.
为了提供一个到设备或是硬盘文件的高层接口,与Unix相类似,Linux发行版本提供了大量的标准库.这是一些我们可以包含在我们的程序中用来处理这些问题的函数的集合.一个很好的例子就是提供了缓冲区输出的标准I/O库.我们可以高效的书写变尺寸的数据块,从而可以使用那些为了提供完整的数据块而安排的低层系统调用.这样就会大大的减少了系统调用的开销.
库函数通常位于手册页的第三部分,而且通常会有一个标准的头文件与之相对,如对于标准输入输出的stdio.h
低层的文件访问
每一个正在运行的程序,被称之为一个进程,他们都有一系列的文件描述符与之相对.这是一些我们可以用来访问打开的文件或是设备的小整数.我们可以使用这些迫切描述符中的多少内容是依赖于我们的系统配置的.当启动一个程序时,他通常会有三个已打开的描述符.他们是:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。