命令ls的C语言实现

 #include <sys/types.h>
  2 #include <dirent.h>
  3 #include "../apuestudy/ourhdr.h"
  4
  5
  6 int main(int argc, char *argv[])
  7 {
  8         DIR       *dp;
  9         struct dirent *dirp;
 10
 11         if (argc != 2)
 12                 err_sys("a signal argument (the d    irectory name) is required");
 13
 14         if ( (dp = opendir (argv[1])) == NULL)
 15                 err_sys("can't open %s", argv[1])    ;
 16
 17         while ( (dirp = readdir (dp)) != NULL)
 18                 printf ("%s/n", dirp->d_name);
 19
 20
 21         closedir(dp);
 22         exit(0);
 23 }

这是最初的版本,是APUE上的,里面有几个函数和头文件

目录的实际格式依赖与UNIX的具体实现,早期系统如V7有比较简单的结构;每个目录项是16个字节,其中14个字节是文件名,2个字节是I节点编号.而对于4.2BSD而言,允许更长的文件名,每个目录项是可变的。这就意味着读目录的程序与系统有关,为啦简化这种情况。UNIX包含一套与读目录有关的历程,他们是POSIX1的一部分

#include <sys/types.h>

#include <dirent.h>

 

DIR   *opendir(const   char *pathname);

struct   dirent *readdir(DIR   *dp)

void    rewinddir (DIR   *dp);

int        closedir   (DIR  *dp);

 

定义在头文件<dirent.h>中的dirent结构与实现有关,但是都包含的成员有两个

struct    dirent

{

        ino_t        d_ino;                     /*节点*/

        char      d_name  [NAME_MAX +1]      /*FIEL  NAME */

}

 

 linux文件系统是Linux系统的心脏部分,提供了层次结构的目录和文件。文件系统将磁盘空间划分为每1024个字节一组,称为块 (也有用512字节为一块的,如:SCOXENIX)。编号从0到整个磁盘的最大块数。

     全部块可划分为四个部分,块0称为引导块 ,文件系统不用该块;块1称为专用块 ,专用块含有许多信息,其中有磁盘大小和全部块的其他两部分的大小。从块2开始是i节点表 ,i节点表中含有i节点,表的块数是可变的,后面将做讨论。i节点表之后是空闲存储块(数据存储块 ),可用于存放文件内容。

     文件的逻辑结构和物理结构是十分不同的,逻辑结构是用户敲入cat命令后所看到的文件,用户可得到表示文件内容的字符流。物理结构是文件实际上如何存放在 磁盘上的存储格式。用户认为自己的文件是边疆的字符流,但实际上文件可能并不是以边疆的方式存放在磁盘上的,长于一块的文件通常将分散地存放在盘上。然而 当用户存取文件时,linux文件系统将以正确的顺序取出各块,给用户提供文件的逻辑结构。

     当然,在linux系统的某处一定会有一个表,告诉文件系统如何将物理结构转换为逻辑结构。这就涉及到i节点了。i节点是一个64字节长的表 ,含有有关一个文件的信息,其中有文件大小、文件所有者、文件存取许可方式,以及文件为普通文件、目录文件还是特别文件等。在i节点中最重要的一项是磁盘地址表。

     该 表中有13个块号。前10个块号是文件前10块的存放地址。这10个块号能给出一个至多10块长的文件的逻辑结构,文件将以块号在磁盘地址表中出现的顺序 依次取得相应的块。当文件长于10块时又怎样呢?磁盘地址表中的第11项给出一个块号,这个块号指出的块中含有256个块号,至此,这种方法满足了至多长 于266块的文件(272384字节)。如果文件大于266块,磁盘地址表的第12项给出一个块号,这个块号指出的块中含有256个块号,这256个块号 的每一个块号又指出一块,块中含256个块号,这些块号才用于取文件的内容。磁盘地址中和第13项索引寻址方式与第12项类似,只是多一级间接索引。

     这样,在linux系统中,文件的最大长度是16842762块,即17246988288字节,有幸是Linux系统对文件的最大长度(一般为1到2M字节)加了更实际的限制,使用户不会无意中建立一个用完整个磁盘区所有块的文件。

    文件系统将文件名转换为i节点的方法实际上相当简单。一个目录实际上是一个含有目录表的文件:对于目录中的每个文件,在目录表中有一个入口项,入口项中含 有文件名和与文件相应的i节点号。当用户敲入catxxx时,文件系统就在当前目录表中查找名为xxx的入口项,得到与文件xxx相应的i节点号,然后开 始取含有文件xxx的内容的块。

 

 

8******************************************************************************************************************************************
UNIX文件系统包括引导块、超级块、i节点区、文件存储区、进程对换区等几部分。
引导块占用第0号物理块,不属于文件系统管辖,如果系统中有多个文件系统,只有根文件系统才有引导程序放在引导块中,其余文件系统都不使用引导块;
超级块占用第1号物理块,是文件系统的控制块,超级块包括:文件系统的大小、空闲块数目、空闲块索引表、空闲i节点数目、空闲i节点索引表、封锁标记等。超级块是系统为文件分配存储空间、回收存储空间的依据。
i节点区存放i节点,i节点是对文件进行控制和管理的一种数据结构。
 
文件存储区是存放文件内容的区域,文件存储区中各数据块的使用情况在超级块中由记录,系统利用超级块中的记录完成对数据块的分配和回收

unix文件系统中很重要的概念之一就是i节点,下面就开始说说这个重要概念。
 
每一个文件都有自己的i节点,每个i节点都有一个唯一的i节点号。
i节点结构如下(参考/usr/include/sys/ino.h):
struct dinode
{
 ushort di_mode;  /*文件类型+用户权限*/
 short di_nlink;  /*文件链接数*/
 ushort di_uid;  /*属主用户id*/
 ushort di_gid;  /*属主用户组id*/
 off_t di_size;  /*文件大小*/
 char di_addr[40]; /*文件数据区起点地址*/
 time_t di_atime; /*最后访问时间*/
 time_t di_mtime; /*最后修改时间*/
 time_t di_ctime; /*创建时间*/
};
从上面这个结构可以看出以下一些信息:
 
1、i节点保存了文件的属性和类型、存放文件内容的物理块地址、最近一次的存取时间、最近一次的修改时间、创建此文件的时间。
 
2、i节点中没有记录文件名字,那文件名是怎么关联到i节点,这么设计又有什么好处呢?
呵呵,这里就关系到了 硬连接与符号连接的区别?
 
3、di_mode这个是怎么保存文件类型+用户权限的,这个如果引申下来也很值得一说。
一般我们用l列文件看到的是这样的结果:
drwxr-xr-x    7 root     sys          512 Dec 15  2002 var
-rw-r--r--    1 root     sys         4003 Jul  4 23:37 1
红色字体部门说明就是文件类型记文件权限。这个字符串跟ushort di_mode怎么关联,用到了一个编码跟掩码的算法(Ip地址用的就是东东

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值