File指令

来源:互联网 发布:基本面分析软件 编辑:程序博客网 时间:2024/06/05 08:35

File指令

功能:file是通过查看文件的头部内容,来获取文件的类型。
使用file命令可以知道某个文件究竟是二进制(ELF格式)的可执行文件, 还是Shell Script文件,或者是其它的什么格式。
file能识别的文件类型:目录、Shell脚本、英文文本、二进制可执行文件、C语言源文件、文本文件、DOS的可执行文件。

在Linux系统中,文件类型根据文件的权限以及文件内容类型来划分的。在linux中文件本身是不需要后缀名称的,我们习惯上添加后缀名称仅仅是便于直观了解这是哪种用途类型。

file命令检验文件类型按以下顺序来完成:
检验文件系统(Filesystem)中支持的文件类型。
检验magic file规则。
检验文件内容的语言和字符集。

1. 检验文件系统(Filesystem)中支持的文件类型

文件系统支持的文件类型指的是通过ls -l 中第一个字符表示的文件类型:

  • -(regular):正规文件(包括文本文件(ASCII,会打印text),可执行文件(会打印excutable),其他二进制文件(会打印data))
  • d(directory):目录
  • l(link):软链接(不包括硬连接,硬链接会以正规文件显示
  • b(block buffered special):随机存储的设备文件,如硬盘,光盘等存储设备
  • c(character unbuffered special):持续输入的设备文件,如鼠标,键盘
  • s(socket):socket文件,最常在/var/run目录下看到这类文件
  • p(pipe):管道文件(first-in-first-out),它的目的在解决多个程序同时存取一个文件造成的错误问题

2.检验magic file规则

    magic file指的是那些具有特殊文件格式的文件,如C文件,它会有#include字样;tar文件的前几个字节会有特殊的规则。而检验magic file规则就是根据这些特殊的格式去判断一个文件的类型。而这些规则是保存在$HOME/.magic.mgc,$HOME/.magic,/etc/magic.mgc,/etc/magic/usr/share/misc/magic.mgc,/usr/share/misc/magic中。

      */magic文件是文本文件,而*/magic.mgc文件则是由*/magic编译后的二进制文件。同一目录下若存在*/magic.mgc则使用该文件,否则使用*/magic。
这些配置的优先级为$HOME/.magic*>/etc/magic*>/usr/share/misc/magic*。

*/magic文件内容格式

文件中的每行都指定了一个规则测试去检验文件类型,这个规则由4个域指定:

  • offset:指定由文件起始的第几个byte开始检验。
  • type:要进行检验的数据类型,即由offset那个byte开始的那个数据类型是什么。具体有哪些数据类型,可以参才magic(5)。常用的数据类型有
    byte:一个byte的值
    short:两个byte的值
    long:四个byte的值
    string:字符串。
  • test:检验值。用于检验offset下的type是否是这个test值。使用C语言的数值或字符表示形式。
  • message:用于显示检验结果的信息显示

如果type为数值类型,那么其后面可添加&value,表示先与后面的test值进行‘与’操作,再进行比较。如果type为字符串类型,则其后可跟/[Bbc]*,/b表示忽略空格,/c表示忽略字母大小写。
如果test的值为数值类型,可以数值前添加=,<,>,&,^,~,分别表示相等、小于、大于、与操作、异或操作、取反操作。如果test的值为字符串类型,可以在其前添加=、<、>。

file命令返回结果以及含义(常见)empty空文件directory目录文件English text英文正式文件assembler program text汇编语言程序的正文文件ascii textASCII编码的文本文件command text命令语言编写的命令正文程序c programC语言正文程序relocation text用于连接的目标文件executable可执行的目标代码文件data数据文件

 

短选项长选项涵义-m--magic-file LIST指定魔法数字名-z--uncompress探测压缩过的文件类型-b--brief列出辨识结果时,不显示文件名称-c--checking-printout详细显示指令执行过程,便于排错或分析程序执行的情形-e--exclude TEST对文件列表排除TEST类型。有效的测试:ascii, apptype, compress, elf, soft, tar, tokens, troff-f--files-from FILE指定文件列表参数,获取该列表里面的所有文件的类型-F--separator STRING使用字符串作为分隔符而不是“:”-i--mime显示MIME类别 --apple显示Apple CREATOR/TYPE --mime-type显示MIME类别 --mime-encoding显示MIME编码-k--keep-going执行命令错误时不终止-l--listlist magic strength-L--dereference跟随符号链接(默认)-h--no-dereference不跟随符号链接-n--no-buffer没有缓冲输出-N--no-paddo not pad output-0--print0terminate filenames with ASCII NUL-p--preserve-datepreserve access times on files-r--rawdon't translate unprintable chars to ooo-s--special-filestreat special (block/char devices) files as ordinary ones-C--compilecompile file specified by -m-d--debugprint debugging messages

 

file 使用实例

显示文件类型 

[root@master lianxi]# file filetest: directory[root@master lianxi]# > 1   使用>输出方法创建新文件1 [root@master lianxi]# file 1 1: empty  [root@web ~]# file tmp tmp:directory[root@web ~]# file -b tmp   不显示文件名称 directory


-i参数,显示MIME类型



file 列出全部文件类型



-z 参数,可以获取用gzip、zip压缩过的文件的类型 

-L 参数,获取软链指向的文件的类型。默认是返回软链本身类型 

-f 参数,获取一个文件名列表的所有文件的类型 

 FILE结构体

FILE结构是包含有文件描述符的
FILE结构函数可以看作是对fd直接操作的系统调用的封装, 它的优点是带有I/O缓存

定义:

C语言的stdio.h头文件中,定义了用于文件操作的结构体FILE。这样,我们通过fopen返回一个文件指针(指向FILE结构体的指针)来进行文件操作。可以在stdio.h(位于visual studio安装目录下的include文件夹下)头文件中查看FILE结构体的定义,如下:

#ifndef _FILE_DEFINEDstruct _iobuf {    char *_ptr; //文件输入的下一个位置    int _cnt; //当前缓冲区的相对位置    char *_base; //指基础位置(即是文件的其始位置)     int _flag; //文件标志    int _file; //文件的有效性验证    int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取    int _bufsiz; //???这个什么意思    char *_tmpfname; //临时文件名        };typedef struct _iobuf FILE;#define _FILE_DEFINED#endif

C语言文件管理的实现

 

C程序用不同的FILE结构管理每个文件。程序员可以使用文件,但是不需要知道FILE结构的细节。实际上,FILE结构是间接地操作系统的文件控制块
(FCB)来实现对文件的操作的,如下图:

 

上面图中的_file实际上是一个描述符,作为进入打开文件表索引的整数。

操作系统文件管理

从2.2中的图可以看出,C语言通过FILE结构可以间接操作文件控制块(FCB)。为了加深对这些的理解,这里科普下操作系统对打开文件的管理。

文件是存放在物理磁盘上的,包括文件控制块(FCB)和数据块。文件控制块通常包括文件权限、日期(创建、读取、修改)、拥有者、文件大小、数据块信息。数据块用来存储实际的内容。对于打开的文件,操作系统是这样管理的:

系统维护了两张表,一张是系统级打开文件表,一张是进程级打开文件表(每个进程有一个)。

系统级打开文件表复制了文件控制块的信息等;进程级打开文件表保存了指向系统级文件表的指针及其他信息。

系统级文件表每一项都保存一个计数器,即该文件打开的次数。我们初次打开一个文件时,系统首先查看该文件是否已在系统级文件表中,如果不在,则创建该项信息,否则,计数器加1。当我们关闭一个文件时,相应的计数也会减1,当减到0时,系统将系统级文件表中的项删除。

进程打开一个文件时,会在进程级文件表中添加一项。每项的信息包括当前文件偏移量(读写文件的位置)、存取权限、和一个指向系统级文件表中对应文件项的指针。系统级文件表中的每一项通过文件描述符(一个非负整数)来标识。

联系2.2和2.3上面的内容,可以发现,应该是这样的:FILE结构体中的_file成员应该是指向进程级打开文件表,然后,通过进程级打开文件表可以找到系统级打开文件表,进而可以通过FCB操作物理磁盘上面的文件。

文件操作的例子

filetest.cpp中的内容如下:

复制代码
#include<stdio.h>  int main()  {      printf("Hello World!\n");      return 0;  }  
复制代码

运行结果如下:

 


通过这个程序可以看出,应该是每打开一次文件,哪怕多次打开的都是同一个文件,进程级打开文件表中应该都会添加一个记录。如果是打开的是同一个文件,这多条记录对应着同一个物理磁盘文件。由于每一次打开文件所进行的操作都是通过进程级打开文件表中不同的记录来实现的,这样,相当于每次打开文件的操作是相对独立的,这就是上面的程序的运行结果中,两次读取文件的结果是一样的(而不是第二次读取从第一次结束的位置进行)。

另外,还可以看出,程序运行的时候,默认三个流是打开的stdin,stdout和stderr,它们的_file描述符分别是0、1和2。也可以看出,该程序打开的文件描述符依次从3开始递增。

struct file:
  struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为filefilp

 

struct file 的最重要成员在这展示.

1.mode_t f_mode;
  
文件模式确定文件是可读的或者是可写的(或者都是), 通过位 FMODE_READ FMODE_WRITE. 你可能想在你的 open 或者 ioctl 函数中检查这个成员的读写许可, 但是不需要检查读写许可, 因为内核在调用你的方法之前检查. 当文件还没有为那种存取而打开时读或写的企图被拒绝, 驱动甚至不知道这个情况.

2.loff_t f_pos;
  
当前读写位置. loff_t 在所有平台都是 64 (  gcc 术语里是 long long ). 驱动可以读这个值,如果它需要知道文件中的当前位置, 但是正常地不应该改变它; 读和写应当使用它们作为最后参数而收到的指针来更新一个位置, 代替直接作用于 filp->f_pos. 这个规则的一个例外是在 llseek 方法中, 它的目的就是改变文件位置
.

3.unsigned int f_flags;
  
这些是文件标志, 例如 O_RDONLY, O_NONBLOCK,  O_SYNC. 驱动应当检查O_NONBLOCK 标志来看是否是请求非阻塞操作; 其他标志很少使用. 特别地, 应当检查读/写许可, 使用 f_mode 而不是f_flags. 所有的标志在头文件<linux/fcntl.h> 中定义.

4.struct file_operations *f_op;
  
和文件关联的操作. 内核安排指针作为它的open 实现的一部分, 接着读取它当它需要分派任何的操作时. filp->f_op 中的值从不由内核保存为后面的引用; 这意味着你可改变你的文件关联的文件操作, 在你返回调用者之后新方法会起作用. 例如, 关联到主编号 1 (/dev/null, /dev/zero, 等等) open 代码根据打开的次编号来替代 filp->f_op 中的操作. 这个做法允许实现几种行为, 在同一个主编号下而不必在每个系统调用中引入开销. 替换文件操作的能力是面向
对象编程的"方法重载"的内核对等体.

5.void *private_data;
  open
 系统调用设置这个指针为 NULL, 在为驱动调用 open 方法之前. 你可自由使用这个成员或者忽略它; 你可以使用这个成员
来指向分配的数据, 但是接着你必须记住在内核销毁文件结构之前,  release 方法中释放那个内存. private_data 是一个有用的资源, 在系统调用间保留状态信息, 我们大部分例子模块都使用它.

6.struct dentry *f_dentry;
关联到文件的目录入口( dentry )结构. 设备驱动编写者正常地不需要关心 dentry 结构, 除了作为 filp->f_dentry->d_inode 存取 inode 结构.


file 结构如下所示:
  

struct file {  union {  struct list_head fu_list; 文件对象链表指针linux/include/linux/list.h  struct rcu_head fu_rcuhead; RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制  } f_u;  struct path f_path; 包含dentry和mnt两个成员,用于确定文件路径  #define f_dentry f_path.dentry f_path的成员之一,当前文件的dentry结构  #define f_vfsmnt f_path.mnt 表示当前文件所在文件系统的挂载根目录  const struct file_operations *f_op; 与该文件相关联的操作函数  atomic_t f_count; 文件的引用计数(有多少进程打开该文件)  unsigned int f_flags; 对应于open时指定的flag  mode_t f_mode; 读写模式:open的mod_t mode参数  off_t f_pos; 该文件在当前进程中的文件偏移量  struct fown_struct f_owner; 该结构的作用是通过信号进行I/O时间通知的数据。  unsigned int f_uid, f_gid; 文件所有者id,所有者组id  struct file_ra_state f_ra; 在linux/include/linux/fs.h中定义,文件预读相关  unsigned long f_version;  #ifdef CONFIG_SECURITY  void *f_security;  #endif    void *private_data;  #ifdef CONFIG_EPOLL    struct list_head f_ep_links;  spinlock_t f_ep_lock;  #endif  struct address_space *f_mapping;  };


1.2struct dentry
  dentry的中文名称是目录项,是Linux文件系统中某个索引节点(inode)的链接。这个索引节点可以是文件,也可以是目录。 inode(可理解为ext2 inode)对应于物理磁盘上的具体对象,dentry是一个内存实体,其中的d_inode成员指向对应的inode。也就是说,一个inode可以在运行的时候链接多个dentry,而d_count记录了这个链接的数量。

struct dentry {  atomic_t d_count; 目录项对象使用计数器,可以有未使用态,使用态和负状态  unsigned int d_flags; 目录项标志  struct inode * d_inode; 与文件名关联的索引节点  struct dentry * d_parent; 父目录的目录项对象  struct list_head d_hash; 散列表表项的指针  struct list_head d_lru; 未使用链表的指针  struct list_head d_child; 父目录中目录项对象的链表的指针  struct list_head d_subdirs; 对目录而言,表示子目录目录项对象的链表  struct list_head d_alias; 相关索引节点(别名)的链表  int d_mounted; 对于安装点而言,表示被安装文件系统根项  struct qstr d_name; 文件名  unsigned long d_time;  struct dentry_operations *d_op; 目录项方法  struct super_block * d_sb; 文件的超级块对象  vunsigned long d_vfs_flags;  void * d_fsdata; 与文件系统相关的数据  unsigned char d_iname [DNAME_INLINE_LEN]; 存放短文件名  };

1.3struct files_struct
  对于每个进程,包含一个files_struct结构,用来记录文件描述符的使用情况,定义在include/linux/file.h

struct files_struct  {  atomic_t count; 使用该表的进程数  struct fdtable *fdt;  struct fdtable fdtab;  spinlock_t file_lock ____cacheline_aligned_in_smp;  int next_fd; 数值最小的最近关闭文件的文件描述符,下一个可用的文件描述符  struct embedded_fd_set close_on_exec_init; 执行exec时需要关闭的文件描述符初值集合  struct embedded_fd_set open_fds_init; 文件描述符的屏蔽字初值集合  struct file * fd_array[NR_OPEN_DEFAULT]; 默认打开的fd队列  };  struct fdtable {  unsigned int max_fds;  struct file ** fd; 指向打开的文件描述符列表的指针,开始的时候指向fd_array,  当超过max_fds时,重新分配地址  fd_set *close_on_exec; 执行exec需要关闭的文件描述符位图(fork,exec即不被子进程继承的文件  描述符)  fd_set *open_fds; 打开的文件描述符位图  struct rcu_head rcu;  struct fdtable *next;  };
1.4 struct fs_struct
struct fs_struct {  atomic_t count; 计数器  rwlock_t lock; 读写锁  int umask;  struct dentry * root, * pwd, * altroot;根目录("/"),当前目录以及替换根目录  struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;  };
1.5 struct inode  

索引节点对象由inode结构体表示,定义文件在linux/fs.h中。

struct inode {  struct hlist_node i_hash; 哈希表  struct list_head i_list; 索引节点链表  struct list_head i_dentry; 目录项链表  unsigned long i_ino; 节点号  atomic_t i_count; 引用记数  umode_t i_mode; 访问权限控制  unsigned int i_nlink; 硬链接数  uid_t i_uid; 使用者id  gid_t i_gid; 使用者id组  kdev_t i_rdev; 实设备标识符  loff_t i_size; 以字节为单位的文件大小  struct timespec i_atime; 最后访问时间  struct timespec i_mtime; 最后修改(modify)时间  struct timespec i_ctime; 最后改变(change)时间  unsigned int i_blkbits; 以位为单位的块大小  unsigned long i_blksize; 以字节为单位的块大小  unsigned long i_version; 版本号  unsigned long i_blocks; 文件的块数  unsigned short i_bytes; 使用的字节数  spinlock_t i_lock; 自旋锁  struct rw_semaphore i_alloc_sem; 索引节点信号量  struct inode_operations *i_op; 索引节点操作表  struct file_operations *i_fop; 默认的索引节点操作  struct super_block *i_sb; 相关的超级块  struct file_lock *i_flock; 文件锁链表  struct address_space *i_mapping; 相关的地址映射  struct address_space i_data; 设备地址映射  struct dquot *i_dquot[MAXQUOTAS];节点的磁盘限额  struct list_head i_devices; 块设备链表  struct pipe_inode_info *i_pipe; 管道信息  struct block_device *i_bdev; 块设备驱动  unsigned long i_dnotify_mask;目录通知掩码  struct dnotify_struct *i_dnotify; 目录通知  unsigned long i_state; 状态标志  unsigned long dirtied_when;首次修改时间  unsigned int i_flags; 文件系统标志  unsigned char i_sock; 套接字  atomic_t i_writecount; 写者记数  void *i_security; 安全模块  __u32 i_generation; 索引节点版本号  union {  void *generic_ip;文件特殊信息  } u;

Linux_Struct file()结构体

struct file结构体定义在/linux/include/linux/fs.h(Linux 2.6.11内核)中,其原型是:
struct file {        /*         * fu_list becomes invalid after file_free is called and queued via         * fu_rcuhead for RCU freeing         */        union {                struct list_head        fu_list;                struct rcu_head         fu_rcuhead;        } f_u;        struct path             f_path;#define f_dentry        f_path.dentry#define f_vfsmnt        f_path.mnt        const struct file_operations    *f_op;        atomic_t                f_count;        unsigned int            f_flags;        mode_t                  f_mode;        loff_t                  f_pos;        struct fown_struct      f_owner;        unsigned int            f_uid, f_gid;        struct file_ra_state    f_ra;        unsigned long           f_version;#ifdef CONFIG_SECURITY        void                    *f_security;#endif        /* needed for tty driver, and maybe others */        void                    *private_data;#ifdef CONFIG_EPOLL        /* Used by fs/eventpoll.c to link all the hooks to this file */        struct list_head        f_ep_links;        spinlock_t              f_ep_lock;#endif /* #ifdef CONFIG_EPOLL */        struct address_space    *f_mapping;};

文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。一下是对结构中的每个数据成员的解释:
一、
union {    struct list_head fu_list;    struct rcu_head rcuhead;}f_u;

其中的struct list_head定义在 linux/include/linux/list.h中,原型为:
struct list_head {        struct list_head *next, *prev;};


用于通用文件对象链表的指针。
struct rcu_head定义在linux/include/linux/rcupdate.h中,其原型为:

/*** struct rcu_head - callback structure for use with RCU* @next: next update requests in a list* @func: actual update function to call after the grace period.*/struct rcu_head {        struct rcu_head *next;        void (*func)(struct rcu_head *head);};


RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制,具体在这里有介绍:
http://www.ibm.com/developerworks/cn/linux/l-rcu/

二、struct path             f_path;
被定义在linux/include/linux/namei.h中,其原型为:

struct path {        struct vfsmount *mnt;        struct dentry *dentry;};


在早些版本的内核中并没有此结构,而是直接将path的两个数据成员作为struct file的数据成员,
struct vfsmount *mnt的作用是指出该文件的已安装的文件系统,
struct dentry *dentry是与文件相关的目录项对象。

三、const struct file_operations    *f_op;
被定义在linux/include/linux/fs.h中,其中包含着与文件关联的操作,如:

loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
等。当打开一个文件时,内核就创建一个与该文件相关联的struct file结构,其中的*f_op就指向的是
具体对该文件进行操作的函数。例如用户调用系统调用read来读取该文件的内容时,那么系统调用read最终会陷入内核调用sys_read函数,而sys_read最终会调用于该文件关联的struct file结构中的f_op->read函数对文件内容进行读取。

四、atomic_t                f_count;
atomic_t被定义为:
typedef struct { volatile int counter; } atomic_t;
volatile修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。 
本质是int类型,之所以这样写是让编译器对基于该类型变量的操作进行严格的类型检查。此处f_count的作用是记录对文件对象的引用计数,也即当前有多少个进程在使用该文件。

五、unsigned int            f_flags;
当打开文件时指定的标志,对应系统调用open的int flags参数。驱动程序为了支持非阻塞型操作需要检查这个标志。

六、mode_t                  f_mode;
对文件的读写模式,对应系统调用open的mod_t mode参数。如果驱动程序需要这个值,可以直接读取这个字段。
mod_t被定义为:

typedef unsigned int __kernel_mode_t;typedef __kernel_mode_t         mode_t;

七、loff_t                  f_pos;
当前的文件指针位置,即文件的读写位置。
loff_t被定义为:
typedef long long       __kernel_loff_t;typedef __kernel_loff_t         loff_t;

八、struct fown_struct      f_owner;
struct fown_struct在linux/include/linux/fs.h被定义,原型为:
struct fown_struct {        rwlock_t lock;          /* protects pid, uid, euid fields */        struct pid *pid;        /* pid or -pgrp where SIGIO should be sent */        enum pid_type pid_type; /* Kind of process group SIGIO should be sent to */        uid_t uid, euid;        /* uid/euid of process setting the owner */        int signum;             /* posix.1b rt signal to be delivered on IO */};该结构的作用是通过信号进行I/O时间通知的数据。

九、unsigned int            f_uid, f_gid;
标识文件的所有者id,所有者所在组的id.

十、struct file_ra_state    f_ra;
struct file_ra_state结构被定义在/linux/include/linux/fs.h中,原型为:

struct file_ra_state {        pgoff_t start;                  /* where readahead started */        unsigned long size;             /* # of readahead pages */        unsigned long async_size;       /* do asynchronous readahead when                                           there are only # of pages ahead */        unsigned long ra_pages;         /* Maximum readahead window */        unsigned long mmap_hit;         /* Cache hit stat for mmap accesses */        unsigned long mmap_miss;        /* Cache miss stat for mmap accesses */        unsigned long prev_index;       /* Cache last read() position */        unsigned int prev_offset;       /* Offset where last read() ended in a page */};
文件预读状态,文件预读算法使用的主要数据结构,当打开一个文件时,f_ra中出了perv_page(默认为-1)和ra_apges(对该文件允许的最大预读量)这两个字段外,其他的所有西端都置为0。

十一、unsigned long           f_version;
记录文件的版本号,每次使用后都自动递增。

十二、
#ifdef CONFIG_SECURITY
        void                    *f_security;


0 0
原创粉丝点击