精华内容
下载资源
问答
  • OpenStack存储管理功能介绍 技术创新变革未来 前言 OpenStack提供多种类型存储服务用户可以根据业务需求自由选择存储服 务 本章节重点介绍OpenStack中块存储服务Cinder 简单介绍对象存储服务Swift 本章节分为两...
  • 切内以下关于药品零售企业管理说法不正确的是容都“一题多解”是属于哪种思维类型对特珠管理的药品出库复核,中对n中应实行概念正中神经如在臂部受损伤可出现切内药品经营企业应当配备专用终端设备的岗位可以不包括...

    患者血浆PT延长,中对n中蝰蛇毒时间(RVVT)正常,下列哪一项正确( )。

    概念“????”可以单独构成单词的意思是( )?

    切内以下关于药品零售企业管理说法不正确的是

    容都“一题多解”是属于哪种思维类型

    对特珠管理的药品出库复核,中对n中应实行

    概念正中神经如在臂部受损伤可出现

    切内药品经营企业应当配备专用终端设备的岗位可以不包括

    容都下面不属于收敛思维特点的是

    中对n中D-Dimer测定的首选方法是( )。

    42岁男性患者,因“胃区疼痛,餐后加重,伴嗳气,反酸1周”入院。查体:剑突下有轻微压痛,胃镜检查:近幽门窦处胃小弯侧可见一1.5×25px溃疡面。诊断:胃溃疡。若手术治疗,术式为胃大部切除术,确认幽门的重要标志是

    概念企业健康档案可以不包括

    以下不属于满族人给酒的美称的有哪些?

    切内东北抗联群体品格的突出特征是什么

    容都颅顶部“危险区”是

    中对n中抗联一路军少数民族战士中有哪些民族?

    颞区的血管、概念神经错误的是

    切内以下哪些属于长白山特产的药材?

    面部和额顶枕区皮肤的共同特点是

    满族说部不属于满族先民传承下来的哪种艺术形式?

    展开全文
  • 一、涉及内容 1.掌握用户、方案与权限基本概念。 2.熟练掌握用户操作相关命令。 二、具体操作 (一)选择题: ... 1.关于方案描述下列哪一项不正确?... A....下列哪个对象属于方案对象?(C...

    一、涉及内容

     1.掌握用户、方案与权限的基本概念。

     2.熟练掌握用户操作的相关命令。

    二、具体操作

    (一)选择题:

        1.关于方案的描述下列哪一项不正确?(C)

      A.表或索引等对象一定属于某一个方案

      B.在oracle 数据库中,方案与数据库用户是一一对应

      C.一个表可以属于多个方案

      D.一个方案可以拥有多个表

       2.下列哪个对象属于方案对象?(C )

      A.数据段

       B.盘区

       C.表

       D.表空间

        3.以下哪个命令用来连接Oracle 数据库?(B )

      A.CREATE

      B.CONNECT

      C.ALTER

      D.SELECT

    (二)简答题:

    1.简要介绍方案与用户之间的关系?

      答:Oracle用户,通俗的讲就是访问Oracle数据库的“人”。 每个用户都有一个口令和相应的权限。而方案是一系列逻辑数据结构或对象的集合,可以理解为命名空间或包。一个方案只能够被一个数据库用户拥有,并且方案的名称与这个用户的名称相同,当创建新用户时,系统自动创建该用户的方案。 该用户创建的方案对象默认被保存在自己的方案中。

    2.说明在CREATE USER命令中各个选项的作用是什么?哪些是必须有的?

      答:CREATE USER命令中各个选项如下:

    (1)CREATE USER username ---用户名

    (2)IDENTIFIED BY password---口令

    (3)[DEFAULT TABLESPACE tablespace ]--- 缺省的表空间,该用户创建的对象默认存放在这里。

    (4)[TEMPORARY TABLESPACE tablespace] ---该用户使用的缺省的临时表空间

    (5)[QUOTA [integer K[M]][UNLIMITED] ON tablespace_name ---用户在该表空间中允许使用k[m]字节

    (6)[PROFILES profile_name] ---概要文件的名字。对用户能够使用的资源进行限制。

    (7)[PASSWORD EXPIRE] ---立即将口令设成过期状态,用户在登录进入前必须修改口令。

    (8)[ACCOUNT LOCK or ACCOUNT UNLOCK] ---用户是否被加锁。

    其中,(1)CREATE USER username 和(2)IDENTIFIED BY password是必须有的,其余是可选的。

     

    (三)操作题:

    1.创建用户ora_temp,密码为tem。

      先使用system/orcl1234 连接到SQL*Plus ,使用以下语句创建用户

     

    2.将用户ora_temp密码改为ora。

      

    3.用户ora_temp帐号锁定。

     

    4.将用户ora_temp帐号解锁。

     

    5.授予用户ora_temp建立会话的权限(create session)。

      

    6.使用ora_temp身份连接数据库。

      

    7.断开ora_temp用户的连接,使用system身份连接到数据库。

     

    8.删除ora_temp用户。

     

    9.使用OEM工具为内置用户账户scott解锁,查看scott用户方案的所有表。

      (1)在浏览器中输入URL地址为:http://localhost:1158/em 进入OEM登录界面

           

      (2)在“管理”界面找到“用户”,点击打开用户

     

      (3)进入“用户”后,选择“scott”用户

              

          (4)编辑“scott”用户信息,状态为“未锁定”,而后点击“应用”保存。

            

           (5)在“管理”选项卡,点击进入“表”后,点击选择方案,选择“scott”

              

          (6)选择“scott”,

              

          (7)查看scott用户方案的所有表

             

    转载于:https://www.cnblogs.com/shenxiaolin/p/5510959.html

    展开全文
  • 【练习】学生成绩管理系统

    千次阅读 2017-11-19 20:35:37
    学生成绩管理是学校教务部门日常工作重要组成部分,其...  本项目数据是一组学生成绩信息,每条学生成绩信息由学号、姓名和成绩组成,这组学生成绩信息具有相同特性,属于同一数据对象,相邻数据元素之间存

      学生成绩管理是学校教务部门日常工作的重要组成部分,其处理信息量很大。这个项目是对学生成绩管理的简单模拟,用菜单选择方式完成下列功能:

    • 输入学生数据
    • 输出学生数据
    • 学生数据查询
    • 添加学生数据
    • 修改学生数据
    • 删除学生数据

      本项目的数据是一组学生的成绩信息,每条学生的成绩信息由学号、姓名和成绩组成,这组学生的成绩信息具有相同特性,属于同一数据对象,相邻数据元素之间存在序偶关系。由此可以看出,这些数据具有线性表中数据元素的性质,所以该系统的数据采用线性表来存储。在顺序存储结构下,逻辑关系相邻的两个元素在物理位置上也相邻,这是顺序表的特点,本项目可以采用顺序表的线性表顺序存储结构。

    • 源码如下
    #include<iostream>
    #include<iomanip>
    #include<malloc.h>
    #include<string.h>
    using namespace std;
    #define MaxListSize 20
    #define EQUAL 1
    
    typedef struct STU{
      char stuno [10];
      char name [10];
      float score;
      int age;
    }ElemType;
    class List
    {private:
      //线性表的数组表示
      ElemType elem[MaxListSize];
      int length;
      int MaxSize;
     public:
      //输入学生数据
      void init(List **L,int ms);
      //删除所有学生数据
      void DestroyList(List &L){free(&L);}
      //将顺序表置为空表
      void ClearList(){length=0;}
      //判断顺序表是否为空表
      bool ListEmpty()
       {return length==0;}
      //判断顺序表是否为满
      bool ListFull()
       {return length==MaxSize;}
      //删除某个学生数据
      bool ListDelete(int,ElemType &e);
      //遍历顺序表
      void ListTraverse();
      //返回顺序表的长度
      int ListLength();
      //学生数据查询
      void GetElem(int,ElemType *);
      //修改学生数据
      bool UpdateList(ElemType& e,ElemType);
      //添加学生数据
      bool ListInsert(int,ElemType &);
      //对学生数据按升序或降序输出
      void printlist(int);
      bool EqualList(ElemType *,ElemType *);
      bool Less_EqualList(ElemType *,ElemType *);
      bool LocateElem(ElemType ,int);
    };
    
    void List::init(List **L,int ms)
    {*L=(List *)malloc(sizeof(List));
     (*L)->length=0;
     (*L)->MaxSize=ms;
    }
    int List::ListLength()
    {return length;}
    
    bool List::ListDelete(int mark,ElemType &e)
    {int i,j;
     if(ListEmpty()) return false;
     if(mark>0) {  //删除表头元素
        e=elem[0];
        for(i=1; i<length; i++)
         elem[i-1]=elem[i];}
     else   //删除表尾元素
       if(mark<0) e=elem[length-1];
       else {  //删除值为e的元素
        for(i=0;i<length;i++)
         if(strcmp(elem[i].name,e.name)==0) break;
         if(i>=length) return false;
         else e=elem[i];
         for(j=i+1;j<length;j++)
          elem[j-1]=elem[j];}
     length--;
     return true;
    }
    void List::ListTraverse()
    {for(int i=0;i<length;i++)
       {cout<<setw(8)<<elem[i].name;
        cout<<setw(10)<<elem[i].stuno;
        cout<<setw(9)<<elem[i].age;
        cout<<setw(8)<<elem[i].score<<endl;}
    }
    void List::GetElem(int i,ElemType *e)
    {*e=elem[i];}
    
    bool List::EqualList(ElemType *e1,ElemType *e2)
    { if (strcmp(e1->name,e2->name))
        return false;
      if (strcmp(e1->stuno,e2->stuno))
        return false;
      if (e1->age!=e2->age)
        return false;
      if (e1->score!=e2->score)
        return false;
      return true;
    }
    bool List::Less_EqualList(ElemType *e1,ElemType *e2)
    { if(strcmp(e1->name,e2->name)<=0) return true;
      else return false;
    }
    bool List::LocateElem(ElemType e,int type)
    { int i;
      switch (type)
        { case EQUAL:
        for(i=0;i<length;i++)
          if(EqualList(&elem[i],&e))
            return true;
        break;
          default:break;}
      return false;
    }
    //修改学生数据
    bool List::UpdateList(ElemType& e,ElemType e1)
    {for(int i=0;i<length;i++)
       if(strcmp(elem[i].name,e.name)==0) {
         elem[i]=e1;return true;}
     return false;
    }
    bool List::ListInsert(int i,ElemType &e)
    {ElemType *p,*q;
     if(i<1||i>length+1) return false;
     q=&elem[i-1];
     for(p=&elem[length-1];p>=q;--p)
       *(p+1)=*p;
     *q=e;
     ++length;
     return true;
    }
    //对学生成绩按升序或降序输出
    void List::printlist(int mark)
    {int* b=new int[length];
     int i,k;
     cout<<"    姓名     学号      成绩\n";
     if(mark!=0){
      for(i=0; i<length;i++) b[i]=i;
      for(i=0; i<length;i++) {k=i;
       for(int j=i+1;j<length;j++) {
        if(mark==1&&elem[b[j]].score<elem[b[k]].score) k=j;
        if(mark==-1&&elem[b[k]].score<elem[b[j]].score) k=j;}
        if(k!=i) {int x=b[i];b[i]=b[k];b[k]=x;}}
      for(int i=0;i<length;i++)
      {cout<<setw(8)<<elem[b[i]].name;
       cout<<setw(10)<<elem[b[i]].stuno;
       cout<<setw(9)<<elem[b[i]].age;
       cout<<setw(8)<<elem[b[i]].score<<endl;}}
     else {
      for(i=0;i<length;i++)
       {cout<<setw(8)<<elem[i].name;
        cout<<setw(10)<<elem[i].stuno;
        cout<<setw(9)<<elem[i].age;
        cout<<setw(8)<<elem[i].score<<endl;}}
    }
    
    int main()
    { cout<<"linelist1m.cpp运行结果:\n";
      ElemType e,e1,e2,e3,e4,e5,e6;
      List *La,*Lb,*Lc;
      int k;
      cout<<"首先调用插入函数.\n";
      La->init(&La,4);
      strcpy(e1.name,"stu1");
      strcpy(e1.stuno,"100001");
      e1.age=22;
      e1.score=88;
      La->ListInsert(1,e1);
      strcpy(e2.name,"stu2");
      strcpy(e2.stuno,"100002");
      e2.age=21;
      e2.score=79;
      La->ListInsert(2,e2);
      strcpy(e3.name,"stu3");
      strcpy(e3.stuno,"100003");
      e3.age=19;
      e3.score=87;
      La->ListInsert(3,e3);
      La->printlist(0);
      cout<<"表La长:"<<La->ListLength()<<endl;
      cin.get();
    
      Lb->init(&Lb,4);
      strcpy(e4.name,"zmofun");
      strcpy(e4.stuno,"100001");
      e4.age=20;
      e4.score=94;
      Lb->ListInsert(1,e4);
      strcpy(e5.name,"bobjin");
      strcpy(e5.stuno,"100002");
      e5.age=23;
      e5.score=69;
      Lb->ListInsert(2,e5);
      strcpy(e6.name,"stu1");
      strcpy(e6.stuno,"100001");
      e6.age=22;
      e6.score=88;
      Lb->ListInsert(3,e6);
      Lb->printlist(0);
      cout<<"表Lb长:"<<Lb->ListLength()<<endl;
      cin.get();
    
      k=Lc->ListDelete(-1,e6);
      if(k==0) cout<<"删除失败!\n";
      else cout<<"删除成功!\n";
      cout<<"输出表Lc:\n";
      Lc->printlist(0);
      cin.get();
      cout<<"按成绩升序输出表Lc\n";
      Lc->printlist(1);cin.get();
      cout<<"按成绩降序输出表Lc\n";
      Lc->printlist(-1);cin.get();
      return 0;
    }
    
    展开全文
  • VFS中dentry管理

    2012-12-13 17:47:38
     每个dentry对象都属于下列几种状态之一:  (1)未使用(unused)状态:该dentry对象的引用计数d_count的值为0,但其d_inode指针仍然指向相关的的索引节点。该目录项仍然包含有效的信息,只是当前没有人引用他...
    Linux用数据结构dentry来描述fs中与某个文件索引节点相链接的一个目录项(可以是文件,也可以是目录)。
      每个dentry对象都属于下列几种状态之一:
      (1)未使用(unused)状态:该dentry对象的引用计数d_count的值为0,但其d_inode指针仍然指向相关的的索引节点。该目录项仍然包含有效的信息,只是当前没有人引用他。这种dentry对象在回收内存时可能会被释放。
      (2)正在使用(inuse)状态:处于该状态下的dentry对象的引用计数d_count大于0,且其d_inode指向相关的inode对象。这种dentry对象不能被释放。
      (3)负(negative)状态:与目录项相关的inode对象不复存在(相应的磁盘索引节点可能已经被删除),dentry对象的d_inode指针为NULL。但这种dentry对象仍然保存在dcache中,以便后续对同一文件名的查找能够快速完成。这种dentry对象在回收内存时将首先被释放。
      Linux为了提高目录项对象的处理效率,设计与实现了目录项高速缓存(dentry cache,简称dcache),它主要由两个数据结构组成:
      1. 哈希链表dentry_hashtable:dcache中的所有dentry对象都通过d_hash指针域链到相应的dentry哈希链表中。
      2. 未使用的dentry对象链表dentry_unused:dcache中所有处于“unused”状态和“negative”状态的dentry对象都通过其d_lru指针域链入dentry_unused链表中。该链表也称为LRU链表。
      目录项高速缓存dcache是索引节点缓存icache的主控器(master),也即dcache中的dentry对象控制着icache中的inode对象的生命期转换。无论何时,只要一个目录项对象存在于dcache中(非negative状态),则相应的inode就将总是存在,因为inode的引用计数i_count总是大于0。当dcache中的一个dentry被释放时,针对相应inode对象的iput()方法就会被调用。
      
      1 目录项对象的SLAB分配器缓存dentry_cache
      dcache是建立在dentry对象的slab分配器缓存dentry_cache(按照Linux的命名规则,似乎应该是dentry_cachep,^_^)之上的。因此,目录项对象的创建和销毁都应该通过kmem_cache_alloc()函数和kmem_cache_free()函数来进行。
      dentry_cache是一个kmem_cache_t类型的指针。它定义在dcache.c文件中:
      static kmem_cache_t *dentry_cache;
      这个slab分配器缓存是在dcache机制的初始化例程dcache_init()中通过调用函数kmem_cache_create()来创建的。
      
      1.1 分配接口
      dcache在kmem_cache_alloc()的基础上定义两个高层分配接口:d_alloc()函数和d_alloc_root()函数,用来从dentry_cache slab分配器缓存中为一般的目录项和根目录分配一个dentry对象。
      其中,d_alloc()的实现如下:
      #define NAME_ALLOC_LEN(len) ((len+16) & ~15)
      struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
      {
      char * str;
      struct dentry *dentry;
      
      dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
      if (!dentry)
      return NULL;
      
      if (name->len > DNAME_INLINE_LEN-1) {
      str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);
      if (!str) {
      kmem_cache_free(dentry_cache, dentry);
      return NULL;
      }
      } else
      str = dentry->d_iname;
      
      memcpy(str, name->name, name->len);
      str[name->len] = 0;
      
      atomic_set(&dentry->d_count, 1);
      dentry->d_flags = 0;
      dentry->d_inode = NULL;
      dentry->d_parent = NULL;
      dentry->d_sb = NULL;
      dentry->d_name.name = str;
      dentry->d_name.len = name->len;
      dentry->d_name.hash = name->hash;
      dentry->d_op = NULL;
      dentry->d_fsdata = NULL;
      INIT_LIST_HEAD(&dentry->d_vfsmnt);
      INIT_LIST_HEAD(&dentry->d_hash);
      INIT_LIST_HEAD(&dentry->d_lru);
      INIT_LIST_HEAD(&dentry->d_subdirs);
      INIT_LIST_HEAD(&dentry->d_alias);
      if (parent) {
      dentry->d_parent = dget(parent);
      dentry->d_sb = parent->d_sb;
      spin_lock(&dcache_lock);
      list_add(&dentry->d_child, &parent->d_subdirs);
      spin_unlock(&dcache_lock);
      } else
      INIT_LIST_HEAD(&dentry->d_child);
      
      dentry_stat.nr_dentry++;
      return dentry;
      }
      NOTE:
      (1)如果文件名的长度大于15,则调用kmalloc()函数从slab分配器中为文件名分配内存;否则将文件名拷贝到d_iname数组中,并让b_name.name指针指向d_iname。
      (2)引用计数d_count将被初始化为1,其余成员都被初始化为NULL。
      (3)如果父目录的dentry被给定,则设置d_parent指针指向父目录的dentry对象(因此必须通过dget函数来增加父目录dentry对象的引用计数)。并通过d_child指针域将这个dentry对象链入父目录dentry对象的d_subdirs链表。否则,将d_child初始化为指向自身。
      (4)将dcache统计信息中的dentry对象总数nr_dentry值加1。
      函数d_alloc_root()用来为fs的根目录(并不一定是系统全局文件系统的根“/”)分配dentry对象。它以根目录的inode对象指针为参数,如下所示:
      struct dentry * d_alloc_root(struct inode * root_inode)
      {
      struct dentry *res = NULL;
      
      if (root_inode) {
      res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });
      if (res) {
      res->d_sb = root_inode->i_sb;
      res->d_parent = res;
      d_instantiate(res, root_inode);
      }
      }
      return res;
      }
      (1)可以看出,首先还是必须调用d_alloc()函数来从dentry_cache slab分配器缓存中分配一个dentry对象。注意!特别之处在于d_alloc()函数的调用参数。
      (2)然后,将所分配的dentry对象的d_parent指针设置为指向自身。NOTE!这一点是判断一个dentry对象是否是一个fs的根目录的唯一准则(include/linux/dcache.h):
      #define IS_ROOT(x) ((x)==(x)->d_parent)
      (3)最后,通过调用d_instantiate()函数来实例化这个dentry对象。
      函数d_instantiate用于向dentry结构中填写inode信息,因此该函数会将一个dentry对象从negative状态转变为inuse状态。如下所示:
      void d_instantiate(struct dentry *entry, struct inode * inode)
      {
      spin_lock(&dcache_lock);
      if (inode)
      list_add(&entry->d_alias, &inode->i_dentry);
      entry->d_inode = inode;
      spin_unlock(&dcache_lock);
      }
      NOTE! 函数d_instantiate()假定在被调用之前,调用者已经增加了inode的引用计数。
      
      1.2 释放接口
      目录项缓存dcache定义了两个高层释放接口:d_free()函数和dentry_iput()函数。其中,d_free函数用来将dcache中不使用的dentry对象释放回dentry_cache slab分配器缓存;而dentry_iput()函数则用来释放一个dentry对象对一个inode对象的引用关联。
      函数d_free()首先调用dentry对象操作方法中的d_release()函数(如果定义了的话),通常在d_release()函数中释放dentry->fsdata数据。然后,用dname_external()函数判断是否已经为目录项名字d_name分配了内存,如果是,则调用kfree()函数释放d_name所占用的内存。接下来,调用kmem_cache_free()函数释放这个dentry对象。最后,修改dcache统计信息中的dentry对象总数(减1)。其源码如下:
      /* no dcache_lock, please */
      static inline void d_free(struct dentry *dentry)
      {
      if (dentry->d_op && dentry->d_op->d_release)
      dentry->d_op->d_release(dentry);
      if (dname_external(dentry))
      kfree(dentry->d_name.name);
      kmem_cache_free(dentry_cache, dentry);
      dentry_stat.nr_dentry--;
      }
      其中,dname_external()是定义在dcache.h头文件中的内联函数,如下:
      static __inline__ int dname_external(struct dentry *d)
      {
      return d->d_name.name != d->d_iname;
      }
      而dentry_iput()函数则主要用于在调用d_free()函数释放一个dentry对象之前,释放该dentry对象与相应inode对象的关联,从而将一个dentry对象转变为negative状态。主要包括如下几项任务:(1)将这个dentry对象从相应inode对象的别名链表i_dentry中摘除;(2)解除自旋锁dcache_lock;(3)调用dentry的操作方法d_iput()函数(如果有的话),或者iput()方法。
      该函数与d_instantiate()函数是相反的,如下:
      static inline void dentry_iput(struct dentry * dentry)
      {
      struct inode *inode = dentry->d_inode;
      if (inode) {
      dentry->d_inode = NULL;
      list_del_init(&dentry->d_alias);
      spin_unlock(&dcache_lock);
      if (dentry->d_op && dentry->d_op->d_iput)
      dentry->d_op->d_iput(dentry, inode);
      else
      iput(inode);
      } else
      spin_unlock(&dcache_lock);
      }
      NOTE:
      (1)如果定义了dentry方法d_iput(),则dentry_iput()通过调用d_iput()方法来释放inode对象,否则就通过iput()来释放inode对象。
      (2)dentry_iput()函数假定被调用时调用者已经持有了dcache_lock锁。因此它在返回之前对该自旋锁进行解锁。
      
      2 dcache数据结构
      Linux通过在dentry_cache slab分配器缓存上定义了各种dentry链表来有效地管理目录项对象,从而实现dcache机制。它们包括:
      1. dentry对象的哈希链表dentry_hashtable。
      2. dentry对象的LRU链表dentry_unused。
      3. 每个索引节点对象的别名链表i_dentry。每个非negative状态的dentry对象都通过d_alias指针域链入其对应的inode对象的别名链表i_dentry中。
      4. 父目录dentry对象的子目录项(目录或文件)链表d_subdirs。每个dentry对象都通过d_child指针域链入其父目录dentry对象的子目录项链表d_subdirs中。
      
      2.1 哈希链表dentry_hashtable
      dcache中的每个dentry对象都通过其中的d_hash指针域链入哈希链表dentry_hashtable,以便加快对dentry对象的查找速度。哈希链表dentry_hashtable定义在dcache.c文件中,如下:
      #define D_HASHBITS d_hash_shift
      #define D_HASHMASK d_hash_mask
      
      static unsigned int d_hash_mask;
      static unsigned int d_hash_shift;
      static struct list_head *dentry_hashtable;
      指针dentry_hashtable定义了dentry哈希链表表头数组的首地址,而d_hash_mask和d_hash_shift的含义与icache中的inode哈希链表的i_hash_mask和i_hash_shift的含义相同,这里就不再解释。
      每一个dentry对象都通过其父目录dentry对象的指针和其文件名的哈希值hash来唯一地确定它所属的哈希链表的表头指针,这是通过d_hash函数来完成的:
      static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash)
      {
      hash += (unsigned long) parent / L1_CACHE_BYTES;
      hash = hash ^ (hash >> D_HASHBITS) ^ (hash >> D_HASHBITS*2);
      return dentry_hashtable + (hash & D_HASHMASK);
      }
      每个目录项文件名的哈希值是通过full_name_hash()函数(定义在include/linux/dcache.h文件中)来计算的,如下所示:
      /* Compute the hash for a name string. */
      static __inline__ unsigned int full_name_hash(const unsigned char * name, unsigned int len)
      {
      unsigned long hash = init_name_hash();
      while (len--)
      hash = partial_name_hash(*name++, hash);
      return end_name_hash(hash);
      }
      可以看出,该函数又向下调用partial_name_hash()函数和end_name_hash()函数来完成哈希值的计算工作。
      n dcache的初始化
      函数dcache_init()完成整个dcache机制的初始化工作,它主要做两件事:(1)哈希链表表头数组的初始化;(2)slab分配器缓存dentry_cache的创建。该函数的实现思想与icache的初始化函数inode_init()相似,这里就不再详细分析了。如下所示:
      static void __init dcache_init(unsigned long mempages)
      {
      struct list_head *d;
      unsigned long order;
      unsigned int nr_hash;
      int i;
      
      /*
      * A constructor could be added for stable state like the lists,
      * but it is probably not worth it because of the cache nature
      * of the dcache.
      * If fragmentation is too bad then the SLAB_HWCACHE_ALIGN
      * flag could be removed here, to hint to the allocator that
      * it should not try to get multiple page regions.
      */
      dentry_cache = kmem_cache_create("dentry_cache",
      sizeof(struct dentry),
      0,
      SLAB_HWCACHE_ALIGN,
      NULL, NULL);
      if (!dentry_cache)
      panic("Cannot create dentry cache");
      
      #if PAGE_SHIFT < 13
      mempages >>= (13 - PAGE_SHIFT);
      #endif
      mempages *= sizeof(struct list_head);
      for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
      ;
      
      do {
      unsigned long tmp;
      
      nr_hash = (1UL << order) * PAGE_SIZE /
      sizeof(struct list_head);
      d_hash_mask = (nr_hash - 1);
      
      tmp = nr_hash;
      d_hash_shift = 0;
      while ((tmp >>= 1UL) != 0UL)
      d_hash_shift++;
      
      dentry_hashtable = (struct list_head *)
      __get_free_pages(GFP_ATOMIC, order);
      } while (dentry_hashtable == NULL && --order >= 0);
      
      printk("Dentry-cache hash table entries: %d (order: %ld, %ld bytes)\n",
      nr_hash, order, (PAGE_SIZE << order));
      
      if (!dentry_hashtable)
      panic("Failed to allocate dcache hash table\n");
      
      d = dentry_hashtable;
      i = nr_hash;
      do {
      INIT_LIST_HEAD(d);
      d++;
      i--;
      } while (i);
      }
      
      2.2 dentry对象的LRU链表
      对于那些处于“未使用”状态的dentry对象来说,它们被再次访问的可能性很大。因此,不能将它们立即丢弃,而必须将它们在dcache中保留一段时间。为此,Linux通过LRU链表来有效地管理这些未使用的dentry对象。每一个处于unused状态下的dentry通过其d_lru指针域链入系统全局的LRU链表,表头由dentry_unused指针来定义(dcache.c):
      static LIST_HEAD(dentry_unused);
      从某种程度上讲,dentry_unused链表就是处于inuse状态下的dentry对象的直接缓存。当一个dentry不再被使用时,它首先应被移到LRU链表中,而不是直接将其丢弃,因为该dentry对象很可能会再次被引用。
      另一方面,由于dentry_unused链表中的目录项对象是未使用的,因此当内存紧张时,应该将其中一些很长时间内未被使用的dentry对象释放掉,以缓解系统的压力。
      
      2.3 dcache链表的保护锁
      Linux在dcache.c文件中定义了自旋锁dcache_lock,来实现对dcache链表的互斥访问。也即,任何一段想要访问任何一条dcache链表的代码段,都必须首先持有该自旋锁。其定义如下:
      spinlock_t dcache_lock = SPIN_LOCK_UNLOCKED;
      
      2.4 dcache统计信息
      Linux在dcache.c文件中定义了全局变量dentry_stat来表示dcache的统计信息,如下:
      struct {
      int nr_dentry; /* dcache中的dentry对象总数 */
      int nr_unused; /* dcache中未使用的dentry对象个数 */
      int age_limit; /* age in seconds */
      int want_pages; /* pages requested by system */
      int dummy[2];
      } dentry_stat = {0, 0, 45, 0,};
      
      3 dentry访问接口——dget/dput函数
      要引用dcache中的任何一个dentry对象,都必须通过应用接口函数dget()或dget_locked()来进行;然后在使用完这个dentry对象后,通过释放引用接口dput()函数来释放对它的引用。
      
      3.1 引用接口
      引用函数dget()仅仅简单地增加dentry对象的引用计数器,如下所示(dcache.h):
      static __inline__ struct dentry * dget(struct dentry *dentry)
      {
      if (dentry) {
      if (!atomic_read(&dentry->d_count))
      BUG();
      atomic_inc(&dentry->d_count);
      }
      return dentry;
      }
      从上述实现可以看出,对于引用那些d_count=0的dentry对象,我们决不应该使用dget()函数,而是应该使用dget_locked()函数。这是因为:引用一个d_count=0的dentry对象,将使该dentry对象从unused状态转变为inuse状态,该dentry状态也必须从LRU链表中脱离,而在操作dcache链表时是必须先持有自旋锁dcache_lock的。函数dget()并不对调用者由任何调用假设,相反,dget_locked()函数则假定调用者在调用它之前已经持有自旋锁dentry_lock。
      函数dget_locked()定义在dcache.c中:
      struct dentry * dget_locked(struct dentry *dentry)
      {
      return __dget_locked(dentry);
      }
      可以看出,内部函数__dget_locked()完成实际的工作:
      /* This should be called _only_ with dcache_lock held */
      
      static inline struct dentry * __dget_locked(struct dentry *dentry)
      {
      atomic_inc(&dentry->d_count);
      if (atomic_read(&dentry->d_count) == 1) {
      dentry_stat.nr_unused--;
      list_del(&dentry->d_lru);
      INIT_LIST_HEAD(&dentry->d_lru); /* make "list_empty()" work */
      }
      return dentry;
      }
      
      3.2 释放接口dput
      函数dput()用于释放对一个dentry对象的引用。该函数的核心就是将dentry对象的引用计数d_count减1。如果d_count减1后还不为0,则dput直接返回即可;否则就将该dentry对象放到LRU链表中,或直接释放掉(在该dentry对象未链入哈希链表的情况下)。其源码如下:
      void dput(struct dentry *dentry)
      {
      if (!dentry)
      return;
      
      repeat:
      if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
      return;
      
      /* dput on a free dentry? */
      if (!list_empty(&dentry->d_lru))
      BUG();
      /*
      * AV: ->d_delete() is _NOT_ allowed to block now.
      */
      if (dentry->d_op && dentry->d_op->d_delete) {
      if (dentry->d_op->d_delete(dentry))
      goto unhash_it;
      }
      /* Unreachable? Get rid of it */
      if (list_empty(&dentry->d_hash))
      goto kill_it;
      list_add(&dentry->d_lru, &dentry_unused);
      dentry_stat.nr_unused++;
      /*
      * Update the timestamp
      */
      dentry->d_reftime = jiffies;
      spin_unlock(&dcache_lock);
      return;
      
      unhash_it:
      list_del_init(&dentry->d_hash);
      
      kill_it: {
      struct dentry *parent;
      list_del(&dentry->d_child);
      /* drops the lock, at that point nobody can reach this dentry */
      dentry_iput(dentry);
      parent = dentry->d_parent;
      d_free(dentry);
      if (dentry == parent)
      return;
      dentry = parent;
      goto repeat;
      }
      }
      NOTE:
      (1)首先判断是否对LRU链表中的一个dentry对象进行dput操作,如果是则报错。
      (2)如果定义了dentry操作方法d_delete(),则应该按照d_delete()方法的功能描述首先调用它来删除这个dentry独享。如果d_delete()返回非0值(执行出错),则跳转到unhash_it部分,将这个dentry对象从哈希链表中摘除,并将他释放回slab分配器缓存。
      (3)判断这个dentry对象是否链在哈希链表中,如果没有,则跳转到kill_it部分,将这个dentry对象释放掉。
      (4)如果这个dentry对象是链在哈希链表中的,则将它移到dentry_unused链表的首部,并将统计信息的nr_unused域加1,最后更新这个dentry对象的最近一次引用时间戳d_reftime,然后就直接返回。
      (5)unhash_it部分:将这个dentry对象从哈希链表中摘除。
      (6)kill_it部分:这一部分将dentry对象释放回给dentry_cache slab分配器缓存,其过程如下:
      n 首先,将dentry对象从它的父目录dentry的d_subdirs链表中摘除。
      n 然后,调用dentry_iput()函数释放其对相应inode对象的引用。
      n 保存父目录dentry对象的指针,然后调用d_free()函数将这个dentry对象释放回dentry_cache slab分配器缓存。
      n 如果这个dentry对象的父目录指针指向自身,这说明这个dentry对象就是fs的根目录,因此就可以返回了。否则,就要对父目录dentry对象做一次dput()操作。
      
      4 对哈希链表的操作
      (1) 向哈希链表中增加一个dentry对象
      函数d_rehash()实现这一功能,它首先通过d_hash()函数找到这个dentry对象应该挂到哪一个哈希链表中,然后设置d_hash指针。如下所示(dcache.c):
      void d_rehash(struct dentry * entry)
      {
      struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
      spin_lock(&dcache_lock);
      list_add(&entry->d_hash, list);
      spin_unlock(&dcache_lock);
      }
      (2) 从哈希链表中摘除一个dentry对象
      函数d_drop()实现这一点,如下所示(dcache.h):
      static __inline__ void d_drop(struct dentry * dentry)
      {
      spin_lock(&dcache_lock);
      list_del(&dentry->d_hash);
      INIT_LIST_HEAD(&dentry->d_hash);
      spin_unlock(&dcache_lock);
      }
      头文件dcache.h中还定义了一个函数d_unhashed(),用来测试一个dentry对象是否没有链接在哈希链表中,如下:
      static __inline__ int d_unhashed(struct dentry *dentry)
      {
      return list_empty(&dentry->d_hash);
      }
      
      5 对LRU链表的管理与操作
      对LRU链表dentry_unused的管理和维护主要体现在两点上:
      (1)当哈希链表中的一个dentry对象从inuse状态转变为unused状态时,应该将他插入到LRU链表的首部,具体请参见dput()函数的实现。
      (2)当系统内存紧张时,应该释放LRU链表中的一些dentry对象,且通常是释放LRU链表尾部的dentry对象(因为它们是最近最少使用的)。但是也可以根据指定条件释放LRU中特定的dentry对象,因此在这之前要做一个挑选过程,并由这一过程将所选中的dentry对象移到dentry_unused链表的尾部。这一机制也称为dcache的压缩(shrink)机制。
      下面将详细分析dcache的shrink机制实现。
      
      5.1 prune_one_dentry()函数
      该函数实现从LRU链表中释放一个指定的dentry对象。这是一个静态的内部函数,它通常被别的函数调用。NOTE! Prune_one_dentry()函数假定被调用之前,调用者已经将dentry对象从LRU链表中摘除,并且持有自旋锁dcache_lock。因此,它所要做的事情就是:①将这个dentry对象从哈希链表中摘除;②将这个dentry对象从其父目录对象的d_subdirs链表中摘除;③用dentry_iput()函数释放对相应inode对象的引用;④用d_free()释放这个dentry对象;⑤对父目录dentry对象做一次dput操作。
      该函数的源码如下:
      void prune_dcache(int count)
      {
      spin_lock(&dcache_lock);
      for (;;) {
      struct dentry *dentry;
      struct list_head *tmp;
      
      tmp = dentry_unused.prev;
      
      if (tmp == &dentry_unused)
      break;
      list_del_init(tmp);
      dentry = list_entry(tmp, struct dentry, d_lru);
      
      /* If the dentry was recently referenced, don't free it. */
      if (dentry->d_flags & DCACHE_REFERENCED) {
      dentry->d_flags &= ~DCACHE_REFERENCED;
      list_add(&dentry->d_lru, &dentry_unused);
      count--;
      continue;
      }
      dentry_stat.nr_unused--;
      
      /* Unused dentry with a count? */
      if (atomic_read(&dentry->d_count))
      BUG();
      
      prune_one_dentry(dentry);
      if (!--count)
      break;
      }
      spin_unlock(&dcache_lock);
      }
      
      5.2 prune_dcache()函数
      该函数用于实现从LRU链表的尾部开始倒序释放指定个数的dentry对象。它从尾部开始扫描LRU链表,如果被扫描的dentry对象设置了DCACHE_REFERENCED标志,则让其继续留在LRU链表中,否则就将其从LRU链表中摘除,然后调用prune_one_dentry()函数释放该dentry对象。其源码如下(dcache.c):
      void prune_dcache(int count)
      {
      spin_lock(&dcache_lock);
      for (;;) {
      struct dentry *dentry;
      struct list_head *tmp;
      
      tmp = dentry_unused.prev;
      
      if (tmp == &dentry_unused)
      break;
      list_del_init(tmp);
      dentry = list_entry(tmp, struct dentry, d_lru);
      
      /* If the dentry was recently referenced, don't free it. */
      if (dentry->d_flags & DCACHE_REFERENCED) {
      dentry->d_flags &= ~DCACHE_REFERENCED;
      list_add(&dentry->d_lru, &dentry_unused);
      count--;
      continue;
      }
      dentry_stat.nr_unused--;
      
      /* Unused dentry with a count? */
      if (atomic_read(&dentry->d_count))
      BUG();
      
      prune_one_dentry(dentry);
      if (!--count)
      break;
      }
      spin_unlock(&dcache_lock);
      }
      上述两个函数prune_one_dentry()和prune_dcache()是dcache的shrink机制的实现基础。在此基础上,Linux实现了根据指定条件压缩dcache的高层接口函数:①shink_dcache_sb()——根据指定的超级块对象,压缩dcache;②shrink_dcache_parent()——根据指定的父目录dentry对象,压缩dcache;③shrink_dcache_memory()——根据优先级压缩dcache。
      
      5.3 shrink_dcache_sb()函数
      该函数释放dcache的LRU链表中属于某个特定超级块对象的dentry对象。该函数的实现过程主要是两次遍历dentry_unused链表:
      ①第一次遍历过程将属于指定超级块对象的dentry对象移到dentry_unused链表的首部。
      ②第二次遍历则将属于指定超级块对象、且d_count=0的dentry对象释放掉(通过prune_one_dentry函数)。个人认为,判断条件d_count=0是不必要的,当然偏执一点也没什么不好:)
      函数源码如下:
      void shrink_dcache_sb(struct super_block * sb)
      {
      struct list_head *tmp, *next;
      struct dentry *dentry;
      
      /*
      * Pass one ... move the dentries for the specified
      * superblock to the most recent end of the unused list.
      */
      spin_lock(&dcache_lock);
      next = dentry_unused.next;
      while (next != &dentry_unused) {
      tmp = next;
      next = tmp->next;
      dentry = list_entry(tmp, struct dentry, d_lru);
      if (dentry->d_sb != sb)
      continue;
      list_del(tmp);
      list_add(tmp, &dentry_unused);
      }
      
      /*
      * Pass two ... free the dentries for this superblock.
      */
      repeat:
      next = dentry_unused.next;
      while (next != &dentry_unused) {
      tmp = next;
      next = tmp->next;
      dentry = list_entry(tmp, struct dentry, d_lru);
      if (dentry->d_sb != sb)
      continue;
      if (atomic_read(&dentry->d_count))
      continue;
      dentry_stat.nr_unused--;
      list_del(tmp);
      INIT_LIST_HEAD(tmp);
      prune_one_dentry(dentry);
      goto repeat;
      }
      spin_unlock(&dcache_lock);
      }
      
      5.4 shrink_dcache_parent()函数
      该函数释放LRU链表中属于给定父目录对象的子dentry对象。实现源码如下:
      void shrink_dcache_parent(struct dentry * parent)
      {
      int found;
      
      while ((found = select_parent(parent)) != 0)
      prune_dcache(found);
      }
      可以看出,shrink_dcache_parent()函数首先通过调用select_parent()函数来从LRU链表中查找父目录parent的子目录对象,并将这些子dentry对象移到LRU链表的尾部,并返回所找到的子dentry对象的个数(这一步是为调用prune_dcache()函数做准备的);然后,调用prune_dcache()函数将LRU链表尾部的子dentry对象释放掉。
      函数select_parent()是在dcache.c中实现的内部函数,他根据给定的参数parent,在LRU链表中查找父目录parent的子目录对象,并将这些子dentry对象移到LRU链表的尾部,并返回所找到的子dentry对象的个数。源代码如下:
      static int select_parent(struct dentry * parent)
      {
      struct dentry *this_parent = parent;
      struct list_head *next;
      int found = 0;
      
      spin_lock(&dcache_lock);
      repeat:
      next = this_parent->d_subdirs.next;
      resume:
      while (next != &this_parent->d_subdirs) {
      struct list_head *tmp = next;
      struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
      next = tmp->next;
      if (!atomic_read(&dentry->d_count)) {
      list_del(&dentry->d_lru);
      list_add(&dentry->d_lru, dentry_unused.prev);
      found++;
      }
      /*
      * Descend a level if the d_subdirs list is non-empty.
      */
      if (!list_empty(&dentry->d_subdirs)) {
      this_parent = dentry;
      #ifdef DCACHE_DEBUG
      printk(KERN_DEBUG "select_parent: descending to %s/%s, found=%d\n",
      dentry->d_parent->d_name.name, dentry->d_name.name, found);
      #endif
      goto repeat;
      }
      }
      /*
      * All done at this level ... ascend and resume the search.
      */
      if (this_parent != parent) {
      next = this_parent->d_child.next;
      this_parent = this_parent->d_parent;
      #ifdef DCACHE_DEBUG
      printk(KERN_DEBUG "select_parent: ascending to %s/%s, found=%d\n",
      this_parent->d_parent->d_name.name, this_parent->d_name.name, found);
      #endif
      goto resume;
      }
      spin_unlock(&dcache_lock);
      return found;
      }
      这是一个算法比较复杂的函数,对他的NOTE如下:
      (1)由于所有在以parent为根的部分目录树中的目录项都是parent目录的子目录项(直接或间接),而且dentry对象的父、子关系是级联的,因此函数select_parent()必须搜索出LRU链表中所有parent目录的直接或间接子目录项。
      为此,函数维护一个指针this_parent,表示当前正在对部分目录树(以parent为根)中的那一个中间目录(非叶节点)进行搜索。初始时,this_parent指针指向parent,因此整个搜索过程是从上到下、从左到右的一个树型结构遍历过程。
      (2)while循环对当前父目录this_parent的子目录项链表d_subdirs进行搜索。如果链表中dentry对象的d_count=0,则将该dentry对象移到LRU链表的表尾,并将返回值found加1。然后判断这个dentry对象的d_subdirs链表是否为空(也即是否为目录树的中间节点),如果不为空,则让this_parent指针指向这个dentry对象,并跳转回repeat部分,从而对这个dentry对象的子目录项链表开始进行搜索。
      (3)如果当前while循环中测试的每一个dentry对象都没有d_subdirs链表,也即this_parent目录的子目录项全部为目录树的叶节点,则在完成对这一层次的搜索后,退出while循环。函数接下来考虑上升搜索层次(直到this_parent=parent),于是它将next指针修改为this_parent->d_child.next(当前父目录的兄弟),然后将this_parent指针修改为this_parent->d_parent,然后跳转到resume部分,于是搜索过程就从上一层次正确地继续。
      (4)is_parent=parent的情况下退出while循环则宣告整个搜索过程结束。
      
      5.5 shringk_dcache_memory()函数
      当我们需要内存,但又不知道具体需要多少时,就可以调用这个函数来压缩dcache所占用的内存。该函数通常被kswapd守护进程所调用。如下:
      void shrink_dcache_memory(int priority, unsigned int gfp_mask)
      {
      int count = 0;
      
      /*
      * Nasty deadlock avoidance.
      *
      * ext2_new_block->getblk->GFP->shrink_dcache_memory->prune_dcache->
      * prune_one_dentry->dput->dentry_iput->iput->inode->i_sb->s_op->
      * put_inode->ext2_discard_prealloc->ext2_free_blocks->lock_super->
      * DEADLOCK.
      *
      * We should make sure we don't hold the superblock lock over
      * block allocations, but for now:
      */
      if (!(gfp_mask & __GFP_IO))
      return;
      
      if (priority)
      count = dentry_stat.nr_unused / priority;
      
      prune_dcache(count);
      kmem_cache_shrink(dentry_cache);
      }
      优先级参数priority值越大(优先级越低),表明对内存的需要就越不迫切。因此prune_dcache()函数释放的dentry对象个数就越少。
      
      6 对dentry对象的VFS操作接口
      VFS实现了几个对dcache中的dentry对象的操作函数,下面我们列举一些:
      1. d_invalidate()——是一个dcache中的dentry对象无效。该函数的核心就是要将指定的dentry对象从哈希链表中摘除。
      2. d_find_alias()——为指定inode对象找到一个位于哈希链表中的、且在该索引节点的别名链表i_dentry中的dentry对象。
      3. d_prune_aliases()——释放指定inode对象的别名链表i_dentry中未使用的dentry对象。
      4. have_submounts()——查看在参数parent指定的部分目录树中是否至少有一个安装点。
      5. d_lookup()——在参数parent指定的父目录中查找名字为name的目录项。
      6. d_validate()——验证一个dentry对象的有效性。
      7. d_delete()——删除一个dentry对象。实际上是将这个dentry对象转变为negative状态或unused状态。
      8. d_move()——移动一个dentry对象。
      9. __d_path()——得到一个dentry对象的全路径名。
      10. is_subdir()——判断一个dentry对象是否是另一个dentry对象的子孙。
      11. find_inode_number()——在父目录dir中,查找是否存在参数name指定的名字的目录项,并返回对应inode的索引节点。
    展开全文
  • 8、 视图设计一般有3种设计次序,下列属于视图设计的是()。 A、 自顶向下 B、由外向内 C、由内向外 D、自底向上 我的答案:C 9、下列有关数据库的描述,正确的是()。 A、数据库是一个DBF文件 B、数据库...
  • 数据库应用技术模拟试题 1 一单项选择题每个题只有一个答案是正确的请将正确的答案填写到括号内 1下列功能中不属于数据库管理系统功能的是 B 数据库对象定义 数据库文件读写 C数据查询 数据更新 2下列类型中属于定点...
  • 下列图符名标识的图符不属于数据流图合法图符的是(A) 注:P67 A. 控制流 B. 加工 C. 数据存储 D. 源和潭 (17) 软件需求分析阶段的工作,可以分为四个方面:需求获取、需求分析、编写需求规格说明书以及(B) 注:P66 A...
  • 1、下列对python和C语言错误的是:python和C均可以用来写内核 cpython是动态编译,C语言是静态编译语言python中内存问题由python解释器负责,C中内存管理是由开发者管理python和C均可以用来写内核python和C均含有第...
  • JAVA习题4培训讲学.doc

    2020-05-29 00:54:01
    JAVA习题4 精品文档 精品文档 收集于网络如有侵权请联系管理员删除 收集于网络如有侵权请联系管理员删除 精品文档 收集于网络如有侵权请联系管理员删除 一... AC BCOBOL CJAVA DFORTRAN 3下列常量中属于整型常量的是A
  • 下列属于面向对象开发方法的是(A B C D)。 A) Booch B) UML C) Coad D) OMT 6. 软件危机的主要表现是(B D)。 A) 软件成本太高 B) 软件产品的质量低劣 C) 软件开发人员明显不足 D) 软件生产率低下 7...
  • 下列图符名标识的图符不属于数据流图合法图符的是______。(A) A. 控制流 B. 加工 C. 数据存储 D. 源和潭 (17) 软件需求分析阶段的工作,可以分为四个方面:需求获取、需求分析、编写需求规格说明书以及______。(B) A...
  • flash shiti

    2014-03-14 10:32:41
    25.Flash锁定编辑对象的快捷操作是? A. Ctrl+Down B. Ctrl+Shift+Down C. Ctrl+Alt+L D. Ctrl+Alt+Shift+L 26.放大显示比例可使用什麽方式? A. 点选式 B. 框选式 C. 鼠标式 D. A和B都正确 27.以下不是...
  • 数据库习题及答案5

    千次阅读 2021-01-06 09:55:23
    模拟测验1 一、1 2 3 4 5 6 7 8 9 10 A D C c D A C A A C 一、选择题(在每个小题四个备选答案中选出一个正确答案,填在题末的括号中)...下列四项中,不属于SQL2005实用程序的是( )。 A.对象资源管理器 B.查询分析.
  • 广东省房产税施行细则 房产税是以房屋为征税对象,按房屋计税余值或租金收入为计税依据,向产权所有人征收一种财产税。下文是广东省房产税施行细则,欢迎阅读!广东省房产税施行细则最新全文 第一条 依据《中华...
  • 2016计算机二级JAVA上机题库一、选择题(每小题1分,共40分)1、以下叙述中不属于Java语言特点的是( )。...A.6 3B.7 4C.6 2D.7 34、下列选项默认的布局管理器不是BorderLayout的是( )。A.WindowB....
  • 存储过程(1)

    2009-06-10 14:03:00
    由系统管理员角色中任何成员创建任何对象均自动属于 dbo。在下列示例中包含了 dbo 名称限定符。作者: 向阳 发表于 2009-06-10 14:03 原文链接评论: 0 查看评论 发表评论最新新闻:· API对设计流程影响——...
  • 1、下列叙述中正确的是( )。 A.对长度为n的有序链表进行查找,最坏情况下需要的比较次数为n B.对长度为n的有序链表进行对分查找,最坏情况下需要的比较次数为(n/2) C.对长度为n的有序链表进行对分查找,最坏...
  • 如何处理单元测试产生数据,下列哪些说法是正确?ABC A .测试数据入库时加特殊前缀标识。 B .测试数据使用独立测试库。 C .自动回滚单元测试产生脏数据。 D .无须区别,统一在业务代码中进行判断和...
  • 会计理论考试题

    2012-03-07 21:04:40
    15.下列软件中不属于系统软件的是 ___D__ 。 A、Windows B、Visual FoxPro C、UCDOS D、WPS97 16.应用软件在计算机普及中起重要作用,下列 ___D__ 都属于应用软件。 A、WPS、DOS、Lotusl-2-3 B、WIndows95、Word、...
  • 软件工程(30分)一、单选题(10分)二、案例分析(20分) 一、单选题(10分) 消费者打电话给代理商,代理商通过网站购买鲜花...在软件过程中,下列活动属于辅助性活动的是() A. 设计 B. 风险管理 C. 集成 D. 测试 数
  • 2按照软件配置管理的原始指导思想,受控制的对象应是( C )。 A、软件过程;B、软件项目;C、软件配置项;D、软件元素; 3下列( D )不是风险管理的过程。 A、风险规划;B、风险识别; C、风险评估;D、风险收集; 4...
  • 例如:火车进遂道,最先进遂道的是火车头,最后是火车尾,而火车出遂道的时候也是火车头先出,最后出的是火车尾。若有队列: Q =(q1,q2,…,qn) 那么,q1为队头元素(排头元素),qn为队尾元素。队列中的元素是按照q1...
  • C++复习资料之系列

    2008-12-30 21:35:45
    下列选项中错误的是( c )。 (a) if(x == y)i++; (b) if(x = y)i--; (c) if( xy )i--; (d) if( x+y )i++; 2.设有函数关系为y= ,下面选项中能正确表示上述关系为( c )。 (a) y = 1; (b) ...
  • c#学习笔记.txt

    热门讨论 2008-12-15 14:01:21
    static声明属于类型本身而不是属于特定对象的成员。 unsafe声明不安全的上下文。 virtual在派生类中声明其实现可由重写成员更改的方法或访问器。 volatile指示字段可由操作系统、硬件或并发执行的线程等在程序中...
  • Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
    6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
  • 下面不属于基本类型的是:c (选择1项) A) boolean B) long C) String D) byte 题目2:d 如下程序中: (1)public class CharToInt (2){ (3) public static void main(String[] args) (4) { (5) int a,b=...

空空如也

空空如也

1 2 3
收藏数 55
精华内容 22
关键字:

下列属于管理对象的是