(47)LINUX应用编程和网络编程之二Linux文件属性

 

Linux下的文件系统为树形结构,入口为/ 树形结构下的文件目录: 不管哪一个版本的Linux系统,都有这些目录,这些目录应该是标准的。各个Linux发行版本会存在一些小小的差别,但整体来讲,仍是大致差很少。 1. / 文件系统的入口,最高一级目录; 2. /bin 基础系统所须要的命令位于此目录,是最小系统所须要的命令,如:ls, cp, mkdir等。这个目录中的文件都是可执行的,通常的用户均可以使用。 3. /boot 包含Linux内核及系统引导程序所须要的文件,好比 vmlinuz initrd.img 文件都位于这个目录中。在通常状况下,GRUB或LILO系统引导管理器也位于这个目录; 4. /dev 设备文件存储目录,好比声卡、磁盘... ... 这是一个很是有趣的目录,是Linux文件系统的一个闪亮的特性 - 全部对象都是文件或目录。仔细观察这个目录你会发现hda1, hda2等, 它们表明系统主硬盘的不一样分区。/dev/cdrom和/dev/fd0表明你的CDROM驱动器和floppy驱动器。看上去可能有些奇怪,但比较文件和硬件的特性这倒是十分合理的。它们均可以读出和写入。例如/dev/dsp,这个文件表明你的扬声器。那么写入这个文件的数据都回传送到喇叭。试一试 'cat /etc/lilo.conf > /dev/dsp' 你会听到一些声音。这是你的 lilo.conf 文件的声音!一样,向 /dev/ttyS0 ( COM 1 ) 读出或写入数据你能够和接到上面的设备进行通信。 5. /etc 存放系统程序或者通常工具的配置文件。如安装了apache2以后,配置文件在/etc/apache2/目录下。/etc/init.d 这个目录是用来存放系统或服务器以System V模式启动的脚本,这在以System V模式启动或初始化的系统中常见。如apache2的/etc/init.d apache2 start|stop|restart MySQL为/etc/init.d mysql start|stop|restart 6. /home 普通用户默认存放目录 Linux 是多用户环境,因此每个用户都有一个只有本身能够访问的目录(固然管理员也能够访问)。它们以 /home/username 的方式存在。这个目录也保存一些应用对于这个用户的配置,好比 IRC, X 等。 7. /lib 库文件存放目录这里包含了系统程序所须要的全部共享库文件,相似于 Windows 的共享库 DLL 文件。 8. /lost+found 在ext2或ext3文件系统中,当系统意外崩溃或机器意外关机,而产生一些文件碎片放在这里。当系统启动的过程当中fsck工具会检查这里,并修复已经损坏的文件系统。 有时系统发生问题,有不少的文件被移到这个目录中,可能会用手工的方式来修复,或移到文件到原来的位置上。Linux 应该正确的关机。但有时你的系统也可能崩溃掉或忽然断电使系统意外关机。那么启动的时候 fsck 将会进行长时间的文件系统检查。Fsck 会检测并试图恢复所发现的不正确的文件。被恢复的文件会放置在这个目录中。所恢复的文件也许并不完整或并不合理,但毕竟提供了一些恢复数据的机会。 9. /media 即插即用型存储设备的挂载点自动在这个目录下建立,好比USB盘系统自动挂载后,会在这个目录下产生一个目录 ;CDROM/DVD自动挂载后,也会在这个目录中建立一个目录,相似cdrom 的目录。这个只有在最新的发行套件上才有. 10. /mnt /mnt 这个目录通常是用于存放挂载储存设备的挂载目录的,好比有cdrom 等目录。有时咱们能够把让系统开机自动挂载文件系统,把挂载点放在这里也是能够的。好比光驱能够挂载到/mnt/cdrom 。 这是一个普通的加载目录,在这里你能够加载你的文件系统或设备。加载是使一个文件系统对于系统可用的过程。在加载后你的文件能够在加载目录下访问。这个目录一般包含加载目录或用于加载软驱和光驱的子目录。若是须要,你也能够在这里创建其它的加载目录。对于加载目录的位置并无强制性的要求,你能够在系统的任意位置创建加载目录。创建 /mnt 只是为了使系统更工整的惯例。 11. /opt 表示的是可选择的意思,有些软件包也会被安装在这里,也就是自定义软件包,好比在Fedora Core 5.0中,OpenOffice就是安装在这里。有些咱们本身编译的软件包,就能够安装在这个目录中;经过源码包安装的软件,能够经过 ./configure --prefix=/opt/,将软件安装到opt目录。 这个目录包含全部默认系统安装以外的软件和添加的包。 12. /proc 操做系统运行时,进程(正在运行中的程序)信息及内核信息(好比cpu、硬盘分区、内存信息等)存放在这里。/proc目录是假装的文件系统proc的挂载目录,proc并非真正的文件系统。这是系统中极为特殊的一个目录,实际上任何分区上都不存在这个目录。它实际是个实时的、驻留在内存中的文件系统。 13. /root Linux超级权限用户root的家目录; 14. /sbin 大可能是涉及系统管理的命令的存放,是超级权限用户root的可执行命令存放地,普通用户无权限执行这个目录下的命令;这个目录和/usr/sbin; /usr/X11R6/sbin或/usr/local/sbin 目录是类似的; 咱们记住就好了,凡是目录sbin中包含的都是root权限才能执行的。 15. /tmp 临时文件目录,有时用户运行程序的时候,会产生临时文件。 /tmp就用来存放临时文件的。/var/tmp目录和这个目录类似。许多程序在这里创建lock文件和存储临时数据。有些系统会在启动或关机时清空此目录。 16. /usr 这个是系统存放程序的目录,好比命令、帮助文件等。这个目录下有不少的文件和目录。当咱们安装一个Linux发行版官方提供的软件包时,大多安装在这里。若是有涉及服务器配置文件的,会把配置文件安装在/etc目录中。 /usr目录下包括:涉及字体目录/usr/share/fonts ,帮助目录 /usr/share/man或/usr/share/doc,普通用户可执行文件目录/usr/bin 或/usr/local/bin 或/usr/X11R6/bin ,超级权限用户root的可执行命令存放目录,好比 /usr/sbin 或/usr/X11R6/sbin 或/usr/local/sbin 等;还有程序的头文件存放目录/usr/include。 /usr/bin 这个目录是可执行程序的目录,普通用户就有权限执行; 当咱们从系统自带的软件包安装一个程序时,他的可执行文件大多会放在这个目录。/usr/sbin 这个目录也是可执行程序的目录,但大多存放涉及系统管理的命令。只有root权限才能执行;类似目录是/sbin 或/usr/local/sbin或/usr/X11R6/sbin等; /usr/local 这个目录通常是用来存放用户自编译安装软件的存放目录;通常是经过源码包安装的软件,若是没有特别指定安装目录的话,通常是安装在这个目录中。这个目录下面有子目录。/usr/lib 和/lib 目录类似,是库文件的存储目录;/usr/share 系统共用的东西存放地,好比 /usr/share/fonts 是字体目录,是用户都共用的吧。/usr/share/doc和/usr/share/man帮助文件,也是共用的吧; /usr/src 是内核源码存放的目录,好比下面有内核源码目录,好比 linux 、linux-2.xxx.xx 目录等。有的系统也会把源码软件包安装在这里。好比Fedora/Redhat,当咱们安装file.src.rpm的时候,这些软件包会安装在 /usr/src/redhat相应的目录中。请参考: 《file.src.rpm 使用方法的简单介绍》 。另外Fedhat 4.0 5.0,他的内核源码包的目录位于/usr/src/kernels目录下的某个目录中(只有安装后才会生成相应目录); 17. /var 这个目录的内容是常常变更的,看名字就知道,咱们能够理解为vary的缩写,/var下有/var/log 这是用来存放系统日志的目录。/var/www目录是定义Apache服务器站点存放目录;/var/lib 用来存放一些库文件,好比MySQL的,以及MySQL数据库的的存放地;/var/log 系统日志存放,分析日志要看这个目录的东西;/var/spool 打印机、邮件、代理服务器等假脱机目录; Windows和Linux文件系统的区别 Linux文件系统与Windows文件系统有很大的差异。Linux文件系统做为开端,只有一个单独的顶级目录结构。全部一切都从 '根' 开始,用 '/' 表明, 而且延伸到子目录。DOS/Windows有不一样的分区,同时目录都存于分区上。linux则经过 '加载' 的方式把全部分区都放置在 '根' 下制定的目录里。一句话总结:Windows下,目录结构属于分区;Linux下,分区 '加载' 于目录结构。 在Windows下, 启动时检测不一样的分区并被赋予一个分区字母。在Linux下除非你加载一个分区或设备,不然系统不会知道那个分区的存在。这看上去也许不是访问分区或设备的最方便的方式,可是这种方式提供了伟大的机动性。这种构建的方式被称为统一的文件系统,超越了Windows所使用的方式。举个使用 /usr 的例子。这个目录包含了大多数的系统可执行文件。在Linux文件系统下,你能够选择把它加载为其余分区甚至网络上的其余计算机。系统不会感知其中的不一样,由于它表现出的只是本地目录结构下众多的目录中的一个而已。你是否有妄图在Windows下移动可执行文件和数据,而获得的是不得不去修改注册表或干脆蓝屏?你可曾奢望过移动 C: 到其余分区上?
存储设备进行格式化(即创建文件系统)html

1。关于文件系统node

对存储设备分区仍是不够的,咱们还要对新增分区进行格式化;一个分区只有创建了某种文件系统后,这个分区才能使用;创建文件系统过程,就是用相应格式化工具格式化分区的过程,这个过程和咱们在Windows中格式化某个分区为NTFS分区相似;没有什么高深的内容,只是所用的工具不同罢了;mysql

Linux操做系统中,几乎支持目前主流的文件系统,好比NTFS(只读)、FAT(可读可写)、ext二、ext三、reiserfs、hfs (MAC 操做系统的文件系统)、swap 交换分区... ... 还有一些我们不熟悉的操做系统的文件系统等;linux

在Linux中,咱们经常使用的文件系统无非是上面例出的这些;若是您新增了一个硬盘,可能想格 式化成 Linux的文件系统,最佳选择是 reiserfs 或ext3;目前ext2已被 ext3取代;咱们不推荐用ext2文件系统,ext2的使用风险比较大;速度最快的文件系统,当属reiserfs;reiserfs 还有不少优势,好比更安全;ext3是Redhat认为最好的文件系统。sql

相对来讲reiserfs仍是比ext3要优秀。shell

 

 

 

文件系统概念数据库

1。*nix系统中:一切皆文件;apache

2。文件编程

a. )文件的成分: 不管文件是一个程序、一个文档、一个数据库,或者是一个目录,操做系统都会赋予它以下所示的一样的结构:
◆索引节点又称I节点,在文件系统结构中,包含有关相应文件的信息的一个记录,这些信息包括文件权限、文件主、文件大小、存放位置、创建日期等。
◆数据文件的实际内容,它能够是空的,也能够很是大,而且有本身的结构。ubuntu

b.) Linux系统区分文件名的大小写

以圆点“.”开头的文件名是隐含文件(dot files),默认方式下使用ls命令并不能把它们在屏幕上显示出来。一样,在默认状况下,Shell通配符并不匹配这类文件名。

c.) 文件名通配符

星号(*): 与0个或多个任意的字符相匹配

问号(?): 问号只与一个任意的字符匹配,可使用多个问号

方括号([ ]) : 与问号类似,只与一个字符匹配。它们的区别在于,问号与任意一个字符匹配,而方括号只与括号中列出的字符之一匹配。例如letter [123]只与文件letter一、letter2或letter3匹配,但不与文件 letter12匹配。能够用短横线表明一个范围内的字符,而不用将它们一一列出。例如,letter[1-3]是letter[123]的简写形式。可是,要注意范围内的字符都按升序排列,即[A-Z]是有效的,而[Z-A]是无效的。方括号中能够列出多个范围,如[A-Za-z]能够和任意大写或小写 的字符相匹配。方括号中若是以惊叹号“!”开始,表示不与惊叹号后的字符匹配。

 


文件类型

Linux操做系统支持普通文件、目录文件、特别文件及符号连接文件等文件类型。

 


1. 普通文件

普通文件也称做常规文件,包含各类长度的字节串。核心对这些数据没有进行结构化,只是做为有序的字节序列把它提交给应用程序。应用程序本身组织和解释这些数据,一般把它们归并为下述类型之一:
◆文本文件,由ASCII字符构成。例如,信件、报告和称做脚本(Script)的命令文本文件,后者由shell解释执行。
◆数据文件,由来自应用程序的数字型和文本型数据构成。例如,电子表格、数据库,以及字处理文档。
◆可执行的二进制程序,由机器指令和数据构成。例如,上面所说的系统提供的命令。

使用file命令能够肯定指定文件的类型。该命令能够将任意多个文件名当作参数,其通常使用格式是:file 文件名 [文件名...]

2. 目录

目录是一类特殊的文件,利用它能够构成文件系统的分层树型结构。如同普通文件那样,目录文件也包含数据;但目录文件与普通文件的差异是,核心对这些数据加以结构化,它是由成对的“I节点号/文件名”构成的列表。
◆I节点号是检索I节点表的下标,I节点中存放有文件的状态信息。
◆文件名是给一个文件分配的文本形式的字符串,用来标识该文件。在一个指定的目录中,任何两项都不能有一样的名字。

每一个目录的第一项都表示目录自己,并以“.”做为它的文件名。每一个目录的第二项的名字是“..”,表示该目录的父目录。

应注意:以“.”开头的文件名表示隐含文件,使用带-a选项的ls命令能够列出它们。

当把文件添加到一个目录中的时候,该目录的大小会增加,以便容纳新文件名。当删除文件时,目录的尺寸并不减小,而是核心对该目录项作上特殊标记,以便下次添加一个文件时从新使用它。ls命令不会列出这些未被使用的项。

Linux系统的目录结构

Linux文件系统采用带连接的树形目录结构,即只有一个根目录(一般用“/”表示),其中含有下级子目录或文件的信息;子目录中又可含有更下级的子目录或者文件的信息。这样一层一层地延伸下去,构成一棵倒置的树,如图1所示。


图1 Linux树型目录结构

在目录树中,根节点和中间节点(用圆圈表示)都必须是目录,而普通文件和特别文件只能做为“叶子”出现。固然,目录也能够做为叶子。

(1)用户主目录
当注册进入系统时,主目录就是当前工做目录。主目录每每位于/home目录之下,而且与注册名相同,例如,/home/mengqc。一般主目录包含子目录、数据文件,以及用于注册环境的配置文件。

绝对路径和相对路径

什么状况下使用绝对路径名,什么状况下使用相对路径名,取决于哪一种方式涉及到的目录更少。路径短,不只键盘输入少,并且节省系统搜索路径的时间,提升执行效率。例如,当前的工做目录是 /etc/conf/cf.d,若是须要访问系统口令文件/etc/passwd,那么使用绝对路径名是/etc/passwd,使用相对路径名是.. /../passwd。绝对路径名/etc/passwd涉及的目录有2个,而相对路径名../../passwd涉及的目录倒是3个。此时,使用绝对路 径名更有效。

可是,若是当前工做目录是/home/mengqc/lib,要访问在 func目录之下的file1文件,那么使用绝对路径名是/home/mengqc/lib/func/file1,使用相对路径名是 func/file1。绝对路径名/home/mengqc/lib/func/file1涉及的目录有5个,而相对路径名涉及的目录只有2个。此时,使用相对路径名更有效。

若是不清楚当前工做目录与其它目录之间的关系,那么最好使用绝对路径名。

 


3. 设备文件
在Linux系统中,全部设备都做为一类特别文件对待,用户像使用普通文件那样对设备进行操做,从而实现设备无关性。可是,设备文件除了存放在文件I节点中的信息外,它们不包含任何数据。系统利用它们来标识各个设备驱动器,核心使用它们与硬件设备通讯。

有两类特别设备文件,它们对应不一样类型的设备驱动器:
◆字符设备 最经常使用的设备类型,容许I/O传送任意大小的数据,取决于设备自己的容量。使用这种接口的设备包括终端、打印机及鼠标。
◆块设备 这类设备利用核心缓冲区的自动缓存机制,缓冲区进行I/O传送老是以1KB为单位。使用这种接口的设备包括硬盘、软盘和RAM盘。

 

 

 

Linux系统的文件系统路径
1。路径分为绝对路径和相对路径。

绝对路径是从/(也被称为根目录)开始的,好比/usr、/etc/X11。若是一个路径是从/开始的,它必定是绝对路径。

相对路径是以 . 或 .. 开始的,.表示用户当前操做所处的位置,而.. 表示上级目录;在路径中,.表示用户当前所处的目录,而..上级目录,要把.和..当作目录来看。

2。[root@localhost ~]# pwd 注:判断用户当前所处的位置,也就是说他到底位于哪?

use when you are lost.

3。

[root@localhost ~]# cd . 注:咱们进入。

[root@localhost ~]# cd .. 注:咱们切入/root的上级目录。

注意,cd以后有个空格。

 


4。~ 表示当前用户本身的家目录;

~USER 表示用户名为USER的家目录

如:

cd ~ 回到当前用户的家目录;

cd ~USERNAME 回到USERNAME用户的家目录;

 

 

 

 


文件系统及其安装

一个硬盘上能够同时存在多个文件系统,每一个文件系统占据硬盘的一个独立分区。Linux文件系统能够根据须要随时装卸,从而实现文件存储空间的动态扩充和信息安全。在系统初启时,每每只有一个文件系统被安装上,即根文件系统,其上的文件主要是保证系统正常运行的操做系统的代码文件,以及若干语言编译程序、命令解释程序和相应的命令处理程序等构成的文件,此外,还有大量的用户文件空间。根文件系统一旦安装上,则在整个系统运行过程当中是不能卸下的,它是系统的基本部分。

其它的文件系统(例如,由软盘构成的文件系统)能够根据须要(如从硬盘向软盘复制文件),做为子系统动态地安装到主系统中,如图5所示。其中,mnt是为安装子文件系统而特设的安装节点。


图5 文件系统安装

通过安装以后,主文件系统与子文件系统就构成一个有完整目录层次结构的、容量更大的文件系统。这种安装能够高达几级。就是说,若干子文件系统能够并列安装到主文件系统上,也能够一个接一个地串连安装到主文件系统上。

已安装的子文件系统也可从整个文件系统上卸下来,恢复安装前的独立状态。

1.创建文件系统
当硬盘完成分区后,应该在该分区上创建文件系统。这一步工做是经过mkfs工具来完成的。例如,若是须要在分区/dev/hda1上创建ext2文件系统,并检查坏块,应该使用如下命令:
# mkfs -c /dev/hda1

注意,只有root用户才能创建或安装/卸下文件系统。

2.安装文件系统
建立文件系统后,须要使用命令mount将该文件系统安装到主文件系统中。命令mount有三个主要参数:
◆须要安装的文件系统类型,用“-t fstype”选项来指定,这与mkfs中的-t选项是同样的。
◆所需访问的文件系统所在分区名,一般是位于目录/dev中的特别设备文件;若是须要安装网络文件系统时,就使用该服务器上输出的目录名。
◆ 安装新文件系统的路径名,也就是放置新文件系统的安装点(Mount Point)。一般这是一个空目录名,而且是专门为安装新文件系统而准备的。在Linux系统下,目录/mnt是经常使用的文件系统安装目录,缺省状况下, CDROM和软盘驱动器都分别安装在其子目录下。固然,文件系统也能够被安装到其它空目录中。例如,须要将MSDOS文件系统分区/dev/hda1安装 到系统的空目录/dos中,应该使用如下命令:
# mount -t msdos /dev/hda1 /dos

3.卸载文件系统
在关闭系统以前,为了保证文件系统的完整性,全部安装的文件系统都必须被卸载。一般在/etc/fstab文件中定义的文件系统都可以自动卸载。可是,对于手工mount的文件系统,在关闭系统以前必须手工卸载。有时候也须要在系统工做过程当中手工卸载某个文件系统。手工卸载文件系统必须使用umount命令,umount命令将分区名或分区的安装点做为参数,格式以下:

umount <</font>分区名或分区的安装点>

例如,须要将已经安装到/mnt/floppy目录下的软盘卸载,可使用如下命令:
# umount /mnt/floppy

要注意,对于正在使用的文件系统,不能使用umount命令卸载。

本讲咱们介绍了有关Linux系统中经常使用命令格式、文件和目录的概念、文件类型、目录结构、文件的存取权限、文件系统的概念及其安装命令等。有关文件操做的命令不少,读者能够经过上机学习各类命令的使用方法,掌握其基本功能。(T111)

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

文件权限通常可认为是0 123 456 789,一共十位:
0:表示该文件的文件类型。Windows里面是使用了一种文件关联的技术,经过扩展名来关联相应的应用程序,使得双击某个文件,就能达到调用相应的应用程序来打开它的目的,这样简单快捷。然而对于用户来讲,好处是方便,坏处是隐藏了一个实质性的东西:文件的真正的类型,与其扩展名其实是毫无关联的。
举例来讲:一个纯粹的文本文件,我能够给它命名“个人歌声里.mp3”,而后在win下双击,会调用相应的音乐播放器来打开,结果显而易见,确定是错误的。那反过来,一个真正的MP3文件我也能够给它命名“花名册.txt”,在win下双击,通常会调用相应的文本编辑器来打开,不过我说你也知道,显示的必定是乱码。
上面两个例子是为了说明一个观点,某个文件真正的类型与其扩展名没一毛钱关系。
那么在不知道文件扩展名的状况下,如何知道文件的类型呢?在Linux是这样的。
Linux中文件类型只有如下这几种:
1.-,普通文件。
2.d,目录文件,d是directory的简写。
3.l,软链接文件,亦称符号连接文件,s是soft或者symbolic的简写。
4.b,块文件,是设备文件的一种(还有另外一种),b是block的简写。
5.c,字符文件,也是设备文件的一种(这就是第二种),c是character的文件。
Linux系统最原始的也只有这五种,因此第0位,只能是以上五者之一。
那么你会有疑问,
1.MP3文件是是哪一种?答案:普通文件。
2.二进制文件是哪一种?答案:普通文件。
3.文本文件是哪一种?答案:普通文件。
4.为何硬链接没有类型表示?答案:硬链接和软链接,名字上虽然只差一个字,本质彻底不一样,硬链接也是文件。其类型是普通文件。


为何上面要说这么多呢?目的是为下文作知识铺垫。


那么 123-456-789 都好说,了解这块儿的人都知道,他们只是 【用户-属组-其余 】这三组之间的区别,咱们拿其中任意一组做为例子来说解rwx皆可。
r:read,w:write,x:execute。

 


咱们应该如何去记忆这二者之间的区别呢??难道死记硬背?NO。
咱们应该知其然还得知其因此然,下面我试图从这查询文件以及内容的本质出发,来阐述rwx权限在这二者身上为什么有不一样的意义!


理解下面的所说的,须要关于Linux的文件系统的知识作铺垫。若是不知道inode这个概念,基本上就会很吃亏了。


再次强调,文件的内容和该文件当时所用的文件名毫无关联;该文件的类型,也与该文件当时的文件名,毫无关系。


查看一个文件的内容,其实是这样的一个过程:


举例来讲,你用了这个命令:cat /tmp/abc.txt


1.你只传递了一个绝对路径,/tmp/abc.txt,系统首先要知道/tmp/abc.txt文件的inode是多少才行,如何得知呢?
2.记住一个规律,某文件的父目录会(记录)知道该文件的inode号!(此刻我想你是否是悟出一点什么了,不用急,接着往下看)
3.那么我获得“/tmp/abc.txt”这个文件名,我得先知道/tmp目录的状况,要知道/tmp目录的状况,我得先知道/目录的状况,因此我就能够从/目录开始(假设/目录的inode号是0,而且这是【写死的】),而后再去一张叫作inode-table的表中查找inode号0所指向的数据域,而后从数据域里面能够找到一些相似于下面的内容:(看起来像一张表,不是么?其实能够想象到,目录文件就是一张表,存储了它内部有哪些【文件名】,以及该文件名对应的inode号)
文件名 inode号
bin 18
var 19
tmp 20
... ...
好了,咱们从“/”,这个目录文件中找到了“/tmp”【文件名】对应的inode号,就是20。(假设啊)
4.而后咱们经过inode号20,去inode-table里面找寻20对应的数据域,而后从数据域中,咱们又会找到一张表:(为何又是表呢?由于“/”是一个目录,“/tmp”也是一个目录,那固然数据域里面存的仍是表啦)
文件名 inode号
abc.txt 8899
bbb.mp3 10088
kkk.jpg 20000
... ...
好了,咱们找到了/tmp/abc.txt的inode号了,就是8899。根据上面的规律,咱们是否是又得去inode-table里面找8899号对应的数据域了?对,就是这样。
5.咱们找到inode号8899对应的数据域,因而咱们会发现以下一些内容:
“abcdefg”(假设文件内容就是这样)
...


又有疑问了,为毛此次不是表了?
答案:/tmp/abc.txt文件【不是目录文件】了,它【是一个普通文件,他存储的通常都是一些字符串】。

 


体如今本质上:
普通文件:存储普通数据,通常就是字符串。
目录文件:存储了一张表,该表就是该目录文件下,全部文件名和inode的映射关系。
从父目录中得到本文件的inode号---->找到inode-table表中找到这个inode号对应的数据域中的起点以及其余信息---->去这个数据域中读取该文件的内容(普通文件的内容通常是字符串,目录文件的内容是一张表)
若是你真心看懂上面我说的了,那么接下来就变得简单多了。


关键就是访问任何一个文件,要看是否能搞到inode号,搞不到就没辙了。搞到inode就好说了,拿着inode号去inode表中查找便可,最后找到数据域,那么就能够找到文件的内容了
而后整个过程这不只仅跟本文件权限有关,还跟它的父目录(还有父目录的父目录...)权限有关(是否能搞到本文件的inode)


体如今命令上:(话说这才是最实际的表象)
======
对于普通文件来讲,rwx的意义是:
r:能够得到这个普通文件的名字和内容。
w:能够修改这个文件的内容和文件名。能够删除该文件,可是用户会获得是否删除写保护文件的prompt。
x:该文件是否具备被执行的权限。
======
对于目录文件来讲,rwx的意义是:
r-x:能够进入cd该目录,能够得到该目录下存储状况,可是不能修改这个目录内部存储的文件(目录)的名字,也不能在该目录下新建文件和目录
-wx:能够进入cd该目录,可是看不到该目录下的存储状况(ls不可用),能够往该目录下添加、修改、删除文件。能够经过cat来读取该目录下的文件or目录的内容,因为得不到该目录下存储了那些文件,在不知情的状况下只能经过猜,cat + 【文件名】得到文件内容,因此这样依然不保密。
--x:能够进入cd该目录,看不到存储状况,也不能往该目录下添加、修改、删除文件。可是依然能够经过cat + xx(猜)来得到该目录下的文件的内容。
rw-:不能进入cd该目录,用ls仅仅能够得到文件名和目录名,由于获取不到这些文件的inode号,固然也不能得到该目录下的文件的内容。不能往该目录下添加、修改、删除文件。
======

 

最后总结一下吧:
1.目录文件虽然是文件(唉,谁叫Linux的核心理念就是Everything is file),可是存储内容的只是一张表而已,关于文件名和inode号的映射关系。
2.文件的扩展名和文件类型之间,没一毛钱关系。
3.文件的文件名和文件实际存储内容之间,没一毛钱关系,只是做为用户的一种识别标记。
4.要知道如何查找到一个文件内容的过程。
5.为何同一个文件系统移动文件要比跨文件系统快?
答:由于只须要修改某个目录中路径和inode对应关系便可,不须要从新写一遍数据域。
6.什么是买来的500G的硬盘,格式化完后老是少了达不到500G?
答:从本文可知,inode-table也是须要占用存储空间的,因此缺乏的一部分中inode-table占用了很多。
7.我不想吃亏,那么我要如何了解Linux文件系统和inode的相关知识,可否推荐个文章?
答:http://www.cyberciti.biz/tips/understanding-unixlinux-filesystem-inodes.html

 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

3.2.1.一、普通文件(-    regular file)
(1)文本文件。文件中的内容是由文本构成的,文本指的是ASCII码字符。文件里的内容本质上都是数字(无论什么文件内容本质上都是数字,由于计算机中自己就只有1和0),而文本文件中的数字自己应该被理解为这个数字对应的ASCII码。常见的.c文件, .h文件  .txt文件等都是文本文件。文本文件的好处就是能够被人轻松读懂和编写。因此说文本文件天生就是为人类发明的。
(2)二进制文件。二进制文件中存储的本质上也是数字,只不过这些数字并非文字的编码数字,而是就是真正的数字。常见的可执行程序文件(gcc编译生成的a.out,arm-linux-gcc编译链接生成的.bin)都是二进制文件。
(3)对比:从本质上来看(就是刨除文件属性和内容的理解)文本文件和二进制文件并无任何区别。都是一个文件里面存放了数字。区别是理解方式不一样,若是把这些数字就看成数字处理则就是二进制文件,若是把这些数字按照某种编码格式去解码成文本字符,则就是文本文件。
(4)咱们如何知道一个文件是普通文本文件仍是二进制文件?在linux系统层面是不区分这两个的(譬如以前学过的open、read、write等方法操做文件文件和二进制文件时一点区别都没有),因此咱们没法从文件自己准确知道文件属于哪一种,咱们只能原本就知道这个文件的类型而后用这种类型的用法去用他。有时候会用一些【后缀名】来人为的标记文件的类型。
(5)使用文本文件时,常规用法就是用文本文件编辑器去打开它、编辑它。常见的文本文件编辑器如vim、gedit、notepad++、SourceInsight等,咱们用这些文本文件编辑器去打开文件的时候,编辑器会read读出文件二进制数字内容,而后按照编码格式去解码将其还原成文字展示给咱们。若是用文本文件编辑器去打开一个二进制文件会如何?这时候编辑器就觉得这个二进制文件仍是文本文件而后试图去将其解码成文字,可是解码过程不少数字并不对应有意义的文字因此成了乱码。
(6)反过来用二进制阅读工具去读取文本文件会怎么样?得出的就是文本文字所对应的二进制的编码。
 
3.2.1.二、目录文件(d    directory)就是目录里的文件。
(1)目录就是文件夹,文件夹在linux中也是一种文件,不过是特殊文件。用ls打开一个文件夹就能看到,文件夹其实也是一种特殊文件,里面存的内容包括这个文件的路径,还有文件夹里面的文件列表。
(2)可是文件夹这种文件比较特殊,自己并不适合用普通的方式来读写。linux中是使用特殊的一些API来专门【读写文件夹】的。
(3)目录文件和文件目录有什么区别?
好比你有1 2 3三个图片文件存放在E:\psd里。
“1”“2”“3”这三个文件就是“E:\psd”这个目录里的文件,“目录文件”指的是“1 2 3”这三个文件。 “E:\psd”是“1 2 3”这三个文件所在的目录,“文件目录”指的是“E:\psd”这个目录。 不一样的就是“目录文件”指的是某些“文件”,“目录”只是定义这些文件存放的位置。 “文件目录”指的是某个目录,“文件”只是定义这个目录里具备哪些文件。 前者定义的是“文件”后者定义的是“目录”
3.2.1.三、字符设备文件(c    character)
3.2.1.四、块设备文件(b    block)
(1)设备文件对应的是硬件设备,也就是说这个文件虽然在文件系统中存在,可是并非真正存在于硬盘上的一个文件,而是文件系统虚拟制造出来的(叫虚拟文件系统,如/dev            /sys /proc等)
(2)虚拟文件系统中的文件大多数不能或者说不用直接读写的,而是用一些特殊的API产生或者使用的,具体在驱动阶段会详解。
 
3.2.1.五、管道文件(p     pipe)
3.2.1.六、套接字文件(s    socket):这种文件类型用于进程间的网络通讯
3.2.1.七、符号连接文件(l    link):这种文件类型指向另外一个文件
 
【普通文件是一个"-",目录文件是一个"d"标识。字符设备文件是"c",块设备文件"b",管道文件“p”,套接字文件“S”,符号连接文件“l”。 】
3.2.2.经常使用文件属性获取
3.2.2.一、stat、fstat、lstat函数简介
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);   //带有const的是输入型参数,查看一个未打开的文件属性
int fstat(int fd, struct stat *buf);  //查看一个已经打开的文件属性
int lstat(const char *path, struct stat *buf);  //查阅的是符号连接文件自己的属性。
(1)每一个文件中都附带了这个文件的一些属性(属性信息是存在于文件自己中的,可是它不像文件的内容同样能够被vi打开看到,属性信息只能被专用的API打开看到)
(2)【文件属性信息】查看的API有三个:stat、fstat、lstat,三个做用同样,参数不一样,细节略有不一样。
(3)linux命令行下还能够去用stat命令去查看文件属性信息,实际上stat命令内部就是使用【stat系统调用】来实现的。
(4)
【int stat(const char *path, struct stat *buf);   //带有const的是输入型参数
stat这个API的做用就是让内核将咱们要查找属性的文件的属性信息结构体的值放入咱们传递给stat函数的buf中,当stat这个API调用从内核返回的时候buf中就被填充了文件的正确的属性信息,而后咱们经过查看buf这种结构体变量的元素就能够得知这个文件的各类属性了。
(5)fstat和stat的区别是:stat是从文件名出发获得文件属性信息结构体(命令使用时,直接就是stat FILENAME),而fstat是从一个已经打开的文件fd出发获得一个文件的属性信息。因此用的时候若是文件没有打开(咱们并不想打开文件操做而只是但愿获得文件属性)那就用stat,若是文件已经被打开了而后要属性那就用fstat效率会更高(stat是从磁盘去读取文件的,而fstat是从内存读取动态文件的)。
(6)lstat和stat/fstat的差异在于:对于符号连接文件,stat和fstat查阅的是【符号连接文件指向的那个文件的属性】,而lstat查阅的是符号连接文件自己的属性。
 
3.2.2.二、struct stat结构体简介          【 man  2   stat 】
(1)struct stat是内核定义的一个结构体,在<sys/stat.h>中声明,因此咱们能够用。这个结构体中的全部元素加起来就是咱们的【文件属性信息】。
int stat(const char *path, struct stat *buf);   //带有const的是输入型参数,后面是一个结构体指针
 
           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */
               mode_t    st_mode;    /* protection   查看一个文件的权限信息*/
               nlink_t   st_nlink;   /* number of hard links */  硬链接号码
               uid_t     st_uid;     /* user ID of owner */
               gid_t     st_gid;     /* group ID of owner */
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes  总共大小*/
               blksize_t st_blksize; /* blocksize for filesystem I/O */
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
               time_t    st_atime;   /* time of last access */
               time_t    st_mtime;   /* time of last modification */
               time_t    st_ctime;   /* time of last status change */
           };
 
一个文件1.file_shuxing_test1.c的属性信息:
File: ‘1.file_shuxing_test1.c’
Size: 173           Blocks: 1          IO Block: 1024   regular file
Device: 18h/24d    Inode: 66          Links: 1
Access: (0777/-rwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-04-11 02:03:14.242978200 +0000
Modify: 2016-04-11 03:03:35.280089700 +0000
Change: 2016-04-11 03:03:35.280089700 +0000
 Birth: -
 
3.2.2.三、写个程序来查看一些常见属性信息
代码以下:
int stat(const char *path, struct stat *buf);   //带有const的是输入型参数,后面是一个结构体指针
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define NAME     "1.txt"
int main(void)
{
    int ret = -1;
    struct stat buf;                             //定义一个结构体buf变量,buf只是个变量名而已,我也能够定义成其余名字
    memset(&buf, 0, sizeof(buf));            // memset后buf中全是0
    ret = stat(NAME, &buf);                // stat后buf中有内容了
    if (ret < 0)
    {
        perror("stat");
        exit(-1);
    }
    // 成功获取了stat结构体,从中能够获得各类属性信息了
    printf("inode = %d.\n", buf.st_ino);
    printf("size = %d bytes.\n", buf.st_size);
    printf("st_blksize = %d.\n", buf.st_blksize);
    return 0;
}
 
 
 
3.2.3.stat函数的应用案例
   stat结构体
 struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */
               mode_t    st_mode;    /* protection */
               nlink_t   st_nlink;   /* number of hard links */
               uid_t     st_uid;     /* user ID of owner */
               gid_t     st_gid;     /* group ID of owner */
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */
               blksize_t st_blksize; /* blocksize for filesystem I/O */
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
               time_t    st_atime;   /* time of last access */
               time_t    st_mtime;   /* time of last modification */
               time_t    st_ctime;   /* time of last status change */
           };
 
3.2.3.一、用代码判断文件类型
(1)文件类型就是-、d、l····
(2)文件属性中的文件类型标志在struct stat结构体的mode_t    st_mode元素中,这个元素实际上是一个按位来定义的一个位标志(有点相似于ARM CPU的CPSR寄存器的模式位定义)。这个东西有不少个标志位共同构成,记录了不少信息,若是要查找文件权限功能时按位&操做就知道结果了,可是由于这些位定义不容易记住,所以linux系统给你们事先定义好了不少宏来进行相应操做,咱们【只要把stat结构体中的mode_t    st_mode元素做为参数传给这些宏中】,根据宏的返回值就能够判断文件类型等。
/*
linux系统给你们事先定义好了不少宏:咱们把mode_t    st_mode元素做为参数传给这些宏中
           S_ISREG(m)  is it a regular file?
 
           S_ISDIR(m)  directory?
 
           S_ISCHR(m)  character device?
 
           S_ISBLK(m)  block device?
 
           S_ISFIFO(m) FIFO (named pipe)?
 
           S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)    //是否是一个符号连接文件
 
           S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)
*/
(3)譬如S_ISREG宏返回值是1表示这个文件是一个普通文件,若是文件不是普通文件则返回值是0.
 
3.2.3.二、用代码判断文件权限设置
(1)st_mode中除了记录了文件类型以外,还记录了一个重要信息:文件权限。
(2)linux并无给文件权限测试提供宏操做,而只是提供了【位掩码】,因此咱们只能用位掩码来本身判断是否具备相应权限。
/*
                                    位掩码
           S_IFMT        0170000   bit mask for the file type bit fields
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO
           S_ISUID    0004000   set-user-ID bit
           S_ISGID    0002000   set-group-ID bit (see below)
           S_ISVTX    0001000   sticky bit (see below)
           S_IRWXU    00700     mask for file owner permissions
           S_IRUSR    00400     owner has read permission
           S_IWUSR    00200     owner has write permission
           S_IXUSR    00100     owner has execute permission
           S_IRWXG    00070     mask for group permissions
           S_IRGRP    00040     group has read permission
           S_IWGRP    00020     group has write permission
 
           S_IXGRP    00010     group has execute permission
           S_IRWXO    00007     mask for permissions for others (not in group)
           S_IROTH    00004     others have read permission
           S_IWOTH    00002     others have write permission
           S_IXOTH    00001     others have execute permission
*/
 
 
代码测试:
/*
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
 
 
#define NAME "1.txt"
 
int main(void)
{
    int ret = -1;
    struct stat buf;
 
    memset(&buf, 0, sizeof(buf));        // memset后buf中全是0
    ret = stat(NAME, &buf);                // stat后buf中有内容了
    if (ret < 0)
    {
        perror("stat");
        exit(-1);
    }
 
#if 0   
    // 判断这个文件属性
    //int result = S_ISREG(buf.st_mode);
       int result = S_ISDIR(buf.st_mode);
       printf("result = %d\n", result);
#endif
 
    // 文件权限测试
    //unsigned int result = (buf.st_mode & S_IRWXU) >> 8;
    unsigned int result = ((buf.st_mode & S_IRUSR)? 1: 0);
    printf("file owner: %u.\n", result);
    return 0;
}
*/
 
-----------------------------------------------------------------------------------------------------------------------------------------------------------
3.2.4.文件权限管理1
3.2.4.一、st_mode中记录的文件权限位
(1)st_mode本质上是一个32位的二进制数(类型就是unsinged int),这个数里的每个位表示一个含义。
(2)【文件类型和文件的权限】都记录在st_mode中。咱们查找文件的权限的时候使用专门的掩码去取出相应的位便可得知相应的信息。
 
3.2.4.二、ls -l打印出的权限列表
(1)
123456789一共9位,3个一组。第一组三个表示文件的属主(owner、user)对该文件的可读、可写、可执行权限;第2组3个位表示文件的属主所在的组(group)对该文件的权限;第3组3个位表示其余用户(others其余组里的用户)对该文件的权限。
(2)属主就是这个文件属于谁,通常来讲文件建立时属主就是建立这个文件的那个用户。可是咱们一个文件建立以后还能够用chown命令去修改一个文件的属主,还能够用chgrp命令去修改一个文件所在的组。
3.2.4.三、文件操做时的权限检查规则
(1)一个程序a.out被执行,a.out中试图去操做一个文件1.txt,这时候如何断定a.out是否具备对1.txt的某种操做权限呢?
(2)断定方法是:首先1.txt具备9个权限位,规定了3种人(user、group、others)对该文件的操做权限。因此咱们断定1.txt是否能被a.out来操做,关键先搞清楚a.out对1.txt到底算哪一种人。准确的说是看a.out被谁执行,也就是当前程序(进程)是哪一个用户的进程。
(3)刚才上面说的是个人分析,到底对不对还得验证。
代码:
/*
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
#define NAME "1.txt"
 
int main(void)
{
    int ret = -1;
 
    ret = open(NAME, O_RDONLY);
    if (ret > 0)
    {
        printf("可读      ");
        close(ret);
 
    }
    else
    {
        perror("read");
    }
 
 
    ret = open(NAME, O_WRONLY);
    if (ret > 0)
    {
        printf("可写      ");
        close(ret);
    }
    else
        perror("write");
 
    return 0;
}
*/
-----------------------------------------------------------------------------------------------------------------------------------------------------------
3.2.5.文件权限管理2
3.2.5.一、access函数检查权限设置    man 2 access     [R_OK  W_OK  X_OK  F_OK]     返回值为0或-1
【 R_OK, W_OK, and X_OK test whether the file exists and grants read, write, and execute permissions, respectively.】
【The check is done using the calling process's real UID and GID】
【 On success (all requested permissions granted, or mode is F_OK and the file exists), zero is returned.  On error (at least one bit in mode  asked  for  a  permission that is denied, or mode is F_OK and the file does not exist, or some other error occurred), -1 is returned, and errno is set appropriately.】
【】
(1)文本权限管控其实蛮复杂,通常很难肯定对一个文件是否具备某种权限(由于不但跟文件自己有关系,还与谁执行这个文件有关系)。设计优秀的软件应该是:在操做某个文件以前先判断当前是否有权限作这个操做,若是有再作若是没有则提供错误信息给用户。
(2)access函数能够测试获得当前执行程序的那个用户在当前那个环境下对目标文件是否具备某种操做权限。
【 int access(const char *pathname, int mode);】
代码测试:
/*
#include <stdio.h>
#include <unistd.h>
#define NAME     "3.txt"
int main(void)
{
    int ret = -1;
    ret = access(NAME, F_OK);
    if (ret < 0)
    {
        printf("文件不存在 \n");
        return -1;
    }
    else
    {
        printf("文件存在    ");
    }
 
    ret = access(NAME, R_OK);
    if (ret < 0)
    {
        printf("不可读 ");
    }
    else
    {
        printf("可读 ");
    }
 
    ret = access(NAME, W_OK);
    if (ret < 0)
    {
        printf("不可写 ");
    }
    else
    {
        printf("可写 ");
    }
 
    ret = access(NAME, X_OK);
    if (ret < 0)
    {
        printf("不可执行 \n");
    }
    else
    {
        printf("可执行 \n");
    }   
    return 0;
}
*/
 
3.2.5.二、chmod/fchmod与权限修改
(1)chmod是一个linux命令,用来修改文件的各类权限属性。chmod命令【只有root用户】才有权利去执行修改,一种安全机制。
(2)chmod命令其实内部是用linux的一个叫【chmod的API】实现的。
fchmod是对一个已经打开的文件进行操做的。
 /*               man  2  chmod
 #include <sys/stat.h>
 int chmod(const char *path, mode_t mode);
 int fchmod(int fd, mode_t mode);
*/
代码:
/*
#include <stdio.h>
#include <sys/stat.h>
 
int main(int argc, char **argv)
{
    int ret = -1;
    if (argc != 2)           //   ./a.out  test.c
    {
        printf("usage: %s filename\n", argv[0]);
        return -1;
    }
    ret = chmod(argv[1], S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWOTH);
    if (ret < 0)
    {
        perror("chmod");
        return -1;
    }
    return 0;
}
*/ 
【可读 4 可写2 可执行1  chmod 777 最高权限  XXX用户、组、其余组】
3.2.5.三、chown/fchown/lchown与属主修改
(1)linux中有个chown命令来修改文件属主
(2)chown命令是用chown API实现的
(3)chgrp是修改组的
补充:
$ chmod u+x file                      给file的属主增长执行权限
$ chmod 751 file                      给file的属主分配读、写、执行(7)的权限,给file的所在组分配读、执行(5)的权限,给其余用户分配执行(1)的权限
$ chmod u=rwx,g=rx,o=x file      上例的另外一种形式
$ chmod =r file                     为全部用户分配读权限
$ chmod 444 file                   同上例
$ chmod a-wx,a+r   file          同上例
$ chmod -R u+r directory           递归地给directory目录下全部文件和子目录的属主分配读的权限
$ chmod 4755                            设置用ID,给属主分配读、写和执行权限,给组和其余用户分配读、执行的权限。
3.2.5.四、umask与文件权限掩码
(1)文件掩码【是linux系统中维护的一个全局设置】,umask的做用是用来设定咱们系统中新建立的文件的默认权限的。
(2)umask命令就是用umask API实现的
 
-----------------------------------------------------------------------------------------------------------------------------------------------------------
3.2.6.读取目录文件(目录文件就是一个特殊的文件)
3.2.6.一、opendir与readdir函数API来打开和读取一个目录文件
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);           //文件指针
DIR *fdopendir(int fd);
 
 
 
【#include <dirent.h>
struct dirent *readdir(DIR *dirp);                       //结构体指针,DIR *dirp是一个目录
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);】
(1)opendir打开一个目录后获得一个DIR类型的【指针】给readdir使用
(2)readdir函数调用一次就会返回一个struct dirent类型的结构体 指针,这个指针指向一个struct dirent类型的结构体变量,这个结构体变量里面记录了一个目录项(所谓目录项就是目录中的一个子文件)。    【man 3 readdir】
/*
struct dirent {
               ino_t          d_ino;       /* inode number */
               off_t          d_off;       /* not an offset; see NOTES */
               unsigned short d_reclen;    /* length of this record */
               unsigned char  d_type;      /* type of file; not supported           文件夹类型
                                              by all filesystem types */
               char           d_name[256]; /* filename */                                 
           };
*/
 
(3)readdir调用一次只能读出一个目录项,要想读出目录中全部的目录项必须【屡次调用readdir函数】。readdir函数内部会记住【哪一个目录项已经被读过了哪一个还没读】,因此屡次调用后不会重复返回已经返回过的目录项。当readdir函数返回NULL时就表示目录中全部的目录项已经读完了。
 
3.2.6.二、dirent结构体
比较重要的就是【type和name】两个选项。
3.2.6.三、读取目录实战演练
代码示例:
#include<stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
//DIR *opendir(const char *name);           //文件指针
//struct dirent *readdir(DIR *dirp);       
#define NAME  "./4.进程"
void main()
{
    struct dirent *p1;
    DIR *p=NULL;
    p=opendir(NAME);
    if(p==NULL)
    {
        perror("opendir");
        _exit(-1);
        }
while ((p1 = readdir(p)) != NULL) 
    printf("%s\n", p1->d_name);     //打印出该目录下的全部内容
    printf("%d\n", p1->d_ino);     //打印出该目录下全部文件的inode号
    //printf("%c\n", p1->d_type);     //打印出该目录下全部文件的类型
if (p1->d_type == DT_REG)    //判断文件类型This is a regular file.
     {
                printf("是普通文件\n");
    }
    else
   {
     printf("不是普通文件\n");
   }
}
 
 
3.2.6.四、可重入函数介绍
(1)有些函数是可重入的有些是不可重入的,具体概念能够去百度。
可重入函数:指一个能够被多个任务调用的函数,这种函数在不一样的任务调用的时候不会改变或者影响其余任务调用该函数时的数据,这种是安全的设计架构。
(2)readdir函数和咱们前面接触的一些函数是不一样的,首先readdir函数直接返回了一个【结构体变量指针,这个指针指向一个结构体,这个结构体中包含了该目录下文件的类型及名称等内容】,由于readdir内部申请了内存而且给咱们返回了地址。屡次调用readdir其实readir内部并不会重复申请内存而是使用第一次调用readdir时分配的那个内存。【这个设计方法是readdir不可重入的关键。】
(3)readdir在屡次调用时【是有关联】的,这个关联也标明readdir函数是不可重入的。
(4)库函数中有一些函数当年刚开始提供时都是不可重入的,后来意识到这种方式不安全,因此从新封装了C库,提供了对应的可重复版本(通常是不可重入版本函数名_r)
 
代码:
/*
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char **argv)
{
    DIR *pDir = NULL;                 //指向一个目录文件opendir
    struct dirent * pEnt = NULL;           //readdir返回的结构体指针
    unsigned int cnt = 0;               //计算文件夹下有多少个文件
 
    if (argc != 2)
    {
        printf("usage: %s dirname\n", argv[0]);
        return -1;
    }
 
    pDir = opendir(argv[1]);
    if (NULL == pDir)
    {
        perror("opendir");
        return -1;
    }
    while (1)
    {
        pEnt = readdir(pDir);                   //readdir函数返回的一个结构体指针,这个指针指向一个存放目录下文件(子文件)的结构体
        if(pEnt != NULL) //当pEnt == NULL时,表示已经读取完毕
        {
            // 还有子文件,在此处理子文件
            printf("name:[%s]    ,", pEnt->d_name);
            cnt++;
            if (pEnt->d_type == DT_REG)              //判断文件类型This is a regular file.
            {
                printf("是普通文件\n");
            }
            else
            {
                printf("不是普通文件\n");
            }
        }
        else
        {
            break;
        }
    };
    printf("总文件数为:%d\n", cnt);
    return 0;
}           
 
*/
root@ubuntu:/mnt/hgfs/Winshare/1.Linux应用编程和网络编程/2.file_shuxing# ./a.out  ../1.file_io/
name:[.]    ,不是普通文件
name:[..]    ,不是普通文件
name:[1.txt]    ,是普通文件
name:[a.out]    ,是普通文件
name:[file1.c]    ,是普通文件
name:[test.txt]    ,是普通文件
总文件数为:6
相关文章
相关标签/搜索