8.5  限额机制

设想一下,如果对用户不采取某些限制措施,则任用户可能用完文件系统的所有可用空间,在某些环境中,这种情况是不能接受的。Linux中为了限制一个用户可获得的文件资源数量,使用了限额机制。限额机制对一个用户可分配的文件数目和使用的磁盘空间设置了限制。系统管理员能分别为每一用户设置限额。

限制有软限制和硬限制之分,硬限制是绝对不允许超过的,而软限制则由系统管理员来确定。当用户占用的资源超过软限制时,系统开始启动定时机制,并在用户的终端上显示警告信息,但并不终止用户进程的运行,如果在规定时间内用户没有采取积极措施改正这一问题,则软限制将被强迫转化为硬限制,用户的进程将被中止。这个规定的时间可以由系统管理员来设置,默认为一周,在include/linux/quota.h中有如下宏定义:

#define MAX_IQ_TIME            604800 /* (7*24*60*60) =1 */

#define MAX_DQ_TIME           604800  /* (7*24*60*60) =1 */

分别是超过索引节点软限制的最长允许时间和超过块的软限制的最长允许时间。

 

下面看一下在Linux中,限额机制具体是怎样实现的。

首先,在编译内核时,要选择“支持限额机制”一项,默认情况下,Linux不使用限额机制。如果使用了限额机制,每一个安装的文件系统都与一个限额文件相联系,限额文件通常驻留在文件系统的根目录里,它实际是一组以用户标识号来索引的限额记录,每个限额记录可称为一个限额块,其数据结构如下(在inclue/linux/quota.h中定义):

 

struct dqblk {

    __u32 dqb_bhardlimit;  /* 块的硬限制*/

    __u32 dqb_bsoftlimit;    /* 块的软限制 */

    __u32 dqb_curblocks;     /* 当前占有的块数 */

    __u32 dqb_ihardlimit;  /* 索引节点的硬限制 */

    __u32 dqb_isoftlimit;  /* 索引节点的软限制 */

    __u32 dqb_curinodes;   /* 当前占用的索引节点数 */

    time_t dqb_btime;      /* 块的软限制变为硬限制前,剩余的警告次数*/

    time_t dqb_itime;     /* 索引节点的软限制变为硬限制前,剩余的警告次数 */

};

 

限额块调入内存后,用哈希表来管理,这就要用到另一个结构dquot(也在inclue/linux/quota.h中定义),其数据结构如下:

   struct dquot {

         struct list_head dq_hash;       /*在内存的哈希表*/

         struct list_head dq_inuse;      /*正在使用的限额块组成的链表*/

         struct list_head dq_free;       /* 空闲限额块组成的链表 */

         wait_queue_head_t dq_wait_lock; /* 指向加锁限额块的等待队列*/

         wait_queue_head_t dq_wait_free; /* 指向未用限额块的等等队列*/

         int dq_count;                   /* 引用计数 */

 

         /* fields after this point are cleared when invalidating */

         struct super_block *dq_sb;      /* superblock this applies to */

         unsigned int dq_id;             /* ID this applies to (uid, gid) */

         kdev_t dq_dev;                  /* Device this applies to */

         short dq_type;                  /* Type of quota */

         short dq_flags;                 /* See DQ_* */

         unsigned long dq_referenced;    /* Number of times this dquot was

                                            referenced during its lifetime */

         struct dqblk dq_dqb;            /* Diskquota usage */

};

 

 

 

哈希表是用文件系统所在的设备号和用户标识号为散列关键值的。   

vfs的索引节点结构中有一个指向dquot结构的指针。也就是说,调入内存的索引节点都要与相应的dquot结构联系,dquot结构中,引用计数就是反映了当前有几个索引节点与之联系,只有在引用计数为0时,才将该结构放入空闲链表中。

如果使用了限额机制,则当有新的块分配请求,系统要以文件拥有者的标识号为索引去查找限额文件中相应的限额块,如果限额并没有满,则接受请求,并把它加入使用计数中。如果已达到或超过限额,则拒绝请求,并返回错误信息。

下面是为一个用户设置限额的具体实现方法:

1) 检查/etc/fstab ,如果没有提供限额机制,则该文件类似这样:

/dev/hda1 / Ext2 defaults 1 1                                                   

/dev/hda2 /home Ext2 defaults 1 2                                               

2) 为了设置用户 user1 在目录 /home/user1 下所占用磁盘空间和使用文件数的限额, 将/etc/fstab改成 下面这样。                                                

/dev/hda1 / Ext2 defaults 1 1                                                   

/dev/hda2 /home Ext2 defaults,usrquota 1 2                                      

3)以root登录,在需要设置限额的分区目录下创建空文件quota.user                               #touch /home/quota.user                                                         

#chmod 600 /home/quota.user                                                     

4) 重新启动机器。

 5)为指定的用户分配磁盘空间和最多存放文件个数。                           

# edquota -u user1                                                              

Quota for user user1                                                            

/dev/hda2: blocks in use:10, limits (soft=4000,hard=5400)                       

inodes in use : 400, limits (soft=1200,hard=1600)                               

你只需对 limits 那一项进行修改即可。                                                  

#quota user1可以查看用户user1的磁盘限额设置情况。