精华内容
下载资源
问答
  • 共享内存

    2012-11-26 17:49:00
    我们知道,如果我们模块需要一块共享的内存,需要调用ngx_share_memory_add来创建共享内存,而该函数... ngx_shared_memory_add这个函数共享内存分配登记在哪里,在ngx_cycle_s这个结构体中有一个成员,即ngx_cy...

         我们知道,如果我们模块需要一块共享的内存,需要调用ngx_share_memory_add来创建共享内存,而该函数不会马上创建一个共享内存,它是先登记一下共享内存的信息,例如名称,大小,然后在进程初始化时再进行共享内存的创建和初始化.

         ngx_shared_memory_add这个函数是将共享内存的分配登记在哪里,在ngx_cycle_s这个结构体中有一个成员,即ngx_cycle_s->shared_memory,它是个list,用来保存所有登记的共享内存,这个list中保存的ngx_shm_zone_t类型的数据,

          ngx_shm_zone_t的结构体:

    struct ngx_shm_zone_s {  
        // 这里可以指向自定义的一个数据结构,主要是为了在数据初始化的时候使用到,或通过共享内存直接拿到与共享内存相关的数据,它不一定指向共享内存中的地址  
        void                     *data;  
        // 实际的共享内存  
        ngx_shm_t                 shm;  
        // 共享内存的初始化函数  
        ngx_shm_zone_init_pt      init;  
        // 标记  
        void                     *tag;  
    };  

      研究一下ngx_shared_memory_add这个函数的实现,该函数先检查要添加的共享内存是否存在,如果存在,直接返回.如果不存在,创建一个新的.

    1. 两个相同名字的共享内存大小要一样。
    2. 两个相同名字的共享内存tag要一样。
    3. 如果当前共享内存已经存在,则不需要再次添加。会返回同一个共享内存
    4. 如果此共享内存不存在,则添加一个新的ngx_shm_zone_t
    添加完后,会返回ngx_shm_zone_t,然后再设置init函数与data数据。

    ngx_shm_zone_t *
    ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)//tag为某一模块
    {
        ngx_uint_t        i;
        ngx_shm_zone_t   *shm_zone;
        ngx_list_part_t  *part;
    
    //先查找是否共享内存是否存在,存在 返回,不存在 创建 part
    = &cf->cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (name->len != shm_zone[i].shm.name.len) { continue; } if (ngx_strncmp(name->data, shm_zone[i].shm.name.data, name->len) != 0) { continue; } if (tag != shm_zone[i].tag) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the shared memory zone \"%V\" is " "already declared for a different use", &shm_zone[i].shm.name); return NULL; } if (size && size != shm_zone[i].shm.size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the size %uz of shared memory zone \"%V\" " "conflicts with already declared size %uz", size, &shm_zone[i].shm.name, shm_zone[i].shm.size); return NULL; } //如果共享内存已经存在,则直接返回共享内存 return &shm_zone[i]; } shm_zone = ngx_list_push(&cf->cycle->shared_memory); if (shm_zone == NULL) { return NULL; } shm_zone->data = NULL; shm_zone->shm.log = cf->cycle->log; shm_zone->shm.size = size; shm_zone->shm.name = *name; shm_zone->shm.exists = 0; shm_zone->init = NULL; shm_zone->tag = tag; //返回一个新的共享内存 return shm_zone; }

         一般,在我们的模块中,我们会保存ngx_shared_memory_add所创建的ngx_shm_zone_t,然后设置我们自己的初始化函数,ngx_shm_zone_t->init,这样,在进程初始化的时候,会创建这个共享内存,然后会调用我们的init函数。这个init函数的原型是:

        typedef ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, void *data);

        添加共享内存代码实例:

    hm_zone = ngx_shared_memory_add(cf, &name, size,  
                                     &ngx_http_limit_req_module);  
    if (shm_zone == NULL) {  
        return NGX_CONF_ERROR;  
    }  
      
    shm_zone->init = ngx_http_limit_req_init_zone;  
    shm_zone->data = ctx;  

        在进行初始化时,就会创建共享内存了,我们来看看它是如何做的,初始化工作是在ngx_init_cycle这个函数里面做的,这里我们只看进行共享内存初始化的代码.

        

    ngx_cycle_t *  
    ngx_init_cycle(ngx_cycle_t *old_cycle)  
    {  
     ........  
       /* create shared memory */  
      
        part = &cycle->shared_memory.part;  
        shm_zone = part->elts;  
        for (i = 0; /* void */ ; i++) {  
            if (i >= part->nelts) {  
                if (part->next == NULL) {  
                    break;  
                }  
                part = part->next;  
                shm_zone = part->elts;  
                i = 0;  
            }  
            if (shm_zone[i].shm.size == 0) {  
                ngx_log_error(NGX_LOG_EMERG, log, 0,  
                              "zero size shared memory zone "%V"",  
                              &shm_zone[i].shm.name);  
                goto failed;  
            }  
      
            // 跳过未使用的共享内存  
            if (shm_zone[i].init == NULL) {  
                /* unused shared zone */  
                continue;  
            }  
      
            shm_zone[i].shm.log = cycle->log;  
      
            // 这里主要是考虑到在做reload等操作时,应该如何做  
            opart = &old_cycle->shared_memory.part;  
            oshm_zone = opart->elts;  
            for (n = 0; /* void */ ; n++) {  
      
                if (n >= opart->nelts) {  
                    if (opart->next == NULL) {  
                        break;  
                    }  
                    opart = opart->next;  
                    oshm_zone = opart->elts;  
                    n = 0;  
                }  
                if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {  
                    continue;  
                }  
                if (ngx_strncmp(shm_zone[i].shm.name.data,  
                                oshm_zone[n].shm.name.data,  
                                shm_zone[i].shm.name.len)  
                    != 0)  
                {  
                    continue;  
                }  
                // 如果新的共享内存的大小与原有的共享内存大小相同,就不需要重新添加了  
                if (shm_zone[i].shm.size == oshm_zone[n].shm.size) {  
                    // 新的共享内存直接指向已经存在的共享内存的地址  
                    shm_zone[i].shm.addr = oshm_zone[n].shm.addr;  
                    // 当然,还是需要重新初始化一下的,因为重新初始化的函数中,可能会有一些对本地内存的操作,比如在某个本地内存结构体中保存共享内存地址等,所以在我们的初始化函数中,要小心处理  
                    if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data)  
                        != NGX_OK)  
                    {  
                        goto failed;  
                    }  
      
                    goto shm_zone_found;  
                }  
      
                // 如果不存在,则释放掉老的共享内存  
                // 注意,如果新配置的共享内存大小与老的共享内存大小不一样,那老的共享内存大小就被释放掉了,所以这点我们要特别注意  
                ngx_shm_free(&oshm_zone[n].shm);  
      
                break;  
            }  
      
            // 创建共享内存  
            if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {  
                goto failed;  
            }  
      
            // 初始化共享内存池,这里主要是初始化为slab来管理内存池  
            if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {  
                goto failed;  
            }  
      
            // 这里调用我们自己的初始化函数,注意第二个参数是NULL的  
            if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {  
                goto failed;  
            }  
      
        shm_zone_found:  
      
            continue;  
        }  
     ........  

         我们看到,在对每一个共享内存,先调用ngx_shm_alloc创建共享内存,然后调用ngx_init_zone_pool对共享内存块进行初始化,然后调用我们自己添加的共享内存init函数。ngx_init_zone_pool函数是对共享内存进行slab的初始化,之后,我们就可以通过slab进行共享内存的管理.接下来,在我们的init函数里面,将共享内存强制转化成slab。以后我们对共享内存的分配和释放 ,就可以通过slab实现.

      ngx_init_zone_pool函数实现:

    static ngx_int_t  
    ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)  
    {  
        u_char           *file;  
        ngx_slab_pool_t  *sp;  
      
        // 使用slab来进行共享内存的管理  
        sp = (ngx_slab_pool_t *) zn->shm.addr;  
      
        if (zn->shm.exists) {  
      
            if (sp == sp->addr) {  
                return NGX_OK;  
            }  
      
            ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,  
                          "shared zone "%V" has no equal addresses: %p vs %p",  
                          &zn->shm.name, sp->addr, sp);  
            return NGX_ERROR;  
        }  
      
        // 初始化slab分配器  
        sp->end = zn->shm.addr + zn->shm.size;  
        sp->min_shift = 3;  
        sp->addr = zn->shm.addr;  
      
    #if (NGX_HAVE_ATOMIC_OPS)  
      
        file = NULL;  
      
    #else  
      
        file = ngx_pnalloc(cycle->pool, cycle->lock_file.len + zn->shm.name.len);  
        if (file == NULL) {  
            return NGX_ERROR;  
        }  
      
        (void) ngx_sprintf(file, "%V%V%Z", &cycle->lock_file, &zn->shm.name);  
      
    #endif  
      
        // 创建此共享内存的锁  
        if (ngx_shmtx_create(&sp->mutex, (void *) &sp->lock, file) != NGX_OK) {  
            return NGX_ERROR;  
        }  
      
        // 初始化slab  
        ngx_slab_init(sp);  
      
        return NGX_OK;  
    }  

    在nginx_init_zone_pool之后,我们在共享内存里面分配的工作,就需要slab.

    另外,共享内存实际的分配函数是ngx_shm_alloc(),nginx里面包含了共享内存的多种实现方式,lunix中默认使用mmap实现.

    ngx_int_t  
    ngx_shm_alloc(ngx_shm_t *shm)  
    {  
        shm->addr = (u_char *) mmap(NULL, shm->size,  
                                    PROT_READ|PROT_WRITE,  
                                    MAP_ANON|MAP_SHARED, -1, 0);  
      
        if (shm->addr == MAP_FAILED) {  
            ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,  
                          "mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size);  
            return NGX_ERROR;  
        }  
      
        return NGX_OK;  
    }  

     

     

       

    转载于:https://www.cnblogs.com/fll369/archive/2012/11/26/2789464.html

    展开全文
  • 物理地址空间 在写程序时不知道写在哪里了,这样不方便的 0~ MAXsys 逻辑地址空间 在CPU运行的进程看到的地址 0~ MAXprog 逻辑地址生成 需要靠重定位来定位到物理地址 地址检查 段长度寄存器和段基址寄存器来...

    计算机体系结构和内存层次

    在这里插入图片描述
    抽象、保护、共享、虚拟化

    操作系统的内存管理方式

    • 重定位(relocation)
    • 分段(segmentation)
    • 分页(paging)
    • 虚拟存储(virtual memory)(目前多数系统采用按需页式虚拟存储)

    地址空间和地址生成

    物理地址空间 在写程序时是不知道写在哪里了,这样是不方便的 0~ MAXsys
    逻辑地址空间 在CPU运行的进程看到的地址 0~ MAXprog

    逻辑地址生成
    需要靠重定位来定位到物理地址
    地址检查
    段长度寄存器和段基址寄存器来检查地址是否合法

    连续内存分配

    动态分配
    最先匹配、最佳匹配、最差匹配
    碎片整理

    给进程分配一块大小不小于指定大小的连续的物理内存区域
    不能被利用的空闲内存叫做内存碎片
    外部碎片:分配单元之间的未被使用的内存
    内部碎片:进程内部未使用的区域,比如需要510字节,但是只能分配512字节,那就有2字节的内部碎片

    动态分区分配
    指定大小可变的分区(块、内存块),分区的地址是连续的
    需要维护的数据结构:已分配的分区,空闲分区
    动态分区分配策略:

    • 最先匹配(First-fit)
    • 最佳匹配(Best-fit)
    • 最差匹配(Worst-fit)

    最先匹配

    分配n个字节,使用第一个可用的空间比n大的空闲块。比如说要400字节,按顺序查到1KB的区域,那就分给400字节,剩下的还是个空闲块
    在这里插入图片描述
    原理:
    空闲分区列表按顺序排序
    分配过程时,搜索第一个合适的分区
    释放分区时,检查是否可以与邻近的空闲分区合并

    优点:
    简单,在高地址空间有大块的分区
    缺点:
    外部碎片(越切越小,空闲块太小了就变成不能用的外部碎片了)
    分配大块时较慢(分配大块时还得检查一遍前面的被切得稀碎的空间)

    最佳匹配

    分配n字节时,查找并使用不小于n的最小空闲分区
    还是分配400字节,那最接近400的就是500字节大小的空间了
    在这里插入图片描述
    原理:
    空闲分区列表按照大小顺序排序
    分配时查找一个合适的分区
    释放时,查找并且合并邻近的空闲分区(如果有)
    优点:
    大部分分配的尺寸较小时,效果很好,可以避免大的空闲分区被拆分,可以减小外部碎片的大小,相对简单
    缺点:
    本来就小的空闲区域再被切一刀,会产生更多的外部碎片
    释放分区较慢
    容易产生很多无用的小碎片

    最差匹配
    分配n字节,使用尺寸不小于n的最大空闲分区
    在这里插入图片描述
    原理:
    空闲分区列表由大到小排序
    分配时选最大的分区
    释放时检查是否和邻近的合并,进行合并,并调整空闲分区列表顺序
    优点:
    中等大小的分配较多时,效果最好,避免出现太多小碎片
    缺点
    释放分区较慢(因为释放时要搜索合适的位置),容易破坏大的空闲分区,因此后面需要大块时可能不能满足需求

    开销:
    分配之前的查找开销、分配结束后合并临近空闲分区开销、为合并后的空闲区域在空闲分区列表中找合适位置开销

    碎片整理

    • 紧凑
    • 分区对换

    碎片整理:通过调整给进程占用的分区来减少和避免分区碎片。
    在这里插入图片描述

    如图中没有进程的部分,如果计算机现在要四块,那按照下图所示把碎片挪到一起就够用了。
    在这里插入图片描述
    但是,挪动进程是不可以随便动的,地址引用引用的如果是绝对地址,挪了就乱了。
    碎片紧凑需要一些条件:所有进程都可以动态重定位。
    什么时候搬动?等待状态时。
    开销?很多进程都挪一遍,这开销是很大的。

    分区对换

    通过抢占并回收处于等待状态的进程的分区,以增大可用的内存空间。把等待进程的数据存到外存中去。图示:
    在这里插入图片描述

    当进程P1P2P3占满内存了,而此时P1处于等待状态,又来了个P4
    在这里插入图片描述
    P4就会抢占P1的位置,并把P1存到外存中去
    在这里插入图片描述
    对换区,是一种充分利用内存的做法。早期内存很紧张的时候,内存里只有一个进程P1,这时如果来了一个新进程P2,当P1暂停时,就把P1写入外存中,和P2交换。
    在这里插入图片描述
    在这里插入图片描述
    这个交替开销很大,因为内存和外存的速度差别是很大的。
    需要解决的问题是,交换哪个程序?这就要花时间了

    伙伴系统

    连续存储分配的一种方法
    比较好地折中了合并和分配块位置、碎片的问题

    实现

    整个可分配的分区大小为2n
    在这里插入图片描述
    分配的空间的大小A,需要的大小a,保证a<A<2a,哪怕是这种情况,129<256<258,也要用256的空间装129个字节

    数据结构

    • 空闲块按大小和起始地址组织成二维数组(由小到大第一维,相同大小的空闲块地址排序第二维)
    • 起始状态只有一个大小为2N的空闲块

    分配过程

    • 由小到大在空闲块数组中找最小的可用空闲块
    • 过大,则二等分,直至满足大于一倍小于二倍的条件

    下面这个例子很直观。合并的过程很像是之前玩的2048小游戏,两个一样大小的才能合并,合并完一看还有一样大的,那就继续合并。

    在这里插入图片描述
    合并条件:大小相同都为2i,地址相邻,起始地址较小的块必须是2i+1的倍数

    在这里插入图片描述

    ucore中的实现接口

    在这里插入图片描述
    alloc_pages和free_pages重要
    在这里插入图片描述

    练习

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 虚函数表存放在哪里

    千次阅读 2018-09-24 17:28:07
    3.虚函数表存储虚函数的地址,即虚函数表的元素是指向类成员函数的指针,而类中虚函数的个数在编译时期可以确定,即虚函数表的大小可以确定,即大小是在编译时期确定的,不必动态分配内存空间存储虚函数表,所以不再堆中. ...

    1.虚函数表是全局共享的元素,即全局仅有一个.

    2.虚函数表类似一个数组,类对象中存储vptr指针,指向虚函数表.即虚函数表不是函数,不是程序代码,不肯能存储在代码段.

    3.虚函数表存储虚函数的地址,即虚函数表的元素是指向类成员函数的指针,而类中虚函数的个数在编译时期可以确定,即虚函数表的大小可以确定,即大小是在编译时期确定的,不必动态分配内存空间存储虚函数表,所以不再堆中.

    根据以上特征,虚函数表类似于类中静态成员变量.静态成员变量也是全局共享,大小确定.

    所以我推测虚函数表和静态成员变量一样,存放在全局数据区.

     

    c/c++程序所占用的内存一共分为五种: 栈区,堆区,程序代码区,全局数据区(静态区),文字常量区.

    显而易见,虚函数表存放在全局数据区.

     

    几个值得注意的问题

      1、虚函数表是class specific的,也就是针对一个类来说的,这里有点像一个类里面的staic成员变量,即它是属于一个类所有对象的,不是属于某一个对象特有的,是一个类所有对象共有的。  

    2、虚函数表是编译器来选择实现的,编译器的种类不同,可能实现方式不一样,就像前面我们说的vptr在一个对象的最前面,但是也有其他实现方式,不过目前gcc 和微软的编译器都是将vptr放在对象内存布局的最前面。  

    3、虽然我们知道vptr指向虚函数表,那么虚函数表具体存放在内存哪个位置呢,虽然这里我们已经可以得到虚函数表的地址。实际上虚函数指针是在构造函数执行时初始化的,而虚函数表是存放在可执行文件中的。下面的一篇博客测试了微软的编译器将虚函数表存放在了目标文件或者可执行文件的常量段中,http://blog.csdn.net/vicness/article/details/3962767,不过我在gcc下的汇编文件中没有找到vtbl的具体存放位置,主要是对可执行文件的装载和运行原理还没有深刻的理解,相信不久有了这些知识之后会很轻松的找到虚函数表到底存放在目标文件的哪一个段中。

    4、经过测试,在gcc编译器的实现中虚函数表vtable存放在可执行文件的只读数据段.rodata中。 

     

    虚函数表vtable在Linux/Unix中存放在可执行文件的只读数据段中(rodata),这与微软的编译器将虚函数表存放在常量段存在一些差别。 

     

    参考文献:

    1. http://blog.csdn.net/vicness/article/details/3962767

    2. 深度探索c++对象模型 

    展开全文
  • 3.虚函数表存储虚函数的地址,即虚函数表的元素是指向类成员函数的指针,而类中虚函数的个数在编译时期可以确定,即虚函数表的大小可以确定,即大小是在编译时期确定的,不必动态分配内存空间存储虚函数表,所以不再堆中. ...

    1.虚函数表是全局共享的元素,即全局仅有一个.

    2.虚函数表类似一个数组,类对象中存储vptr指针,指向虚函数表.即虚函数表不是函数,不是程序代码,不肯能存储在代码段.

    3.虚函数表存储虚函数的地址,即虚函数表的元素是指向类成员函数的指针,而类中虚函数的个数在编译时期可以确定,即虚函数表的大小可以确定,即大小是在编译时期确定的,不必动态分配内存空间存储虚函数表,所以不再堆中.

    根据以上特征,虚函数表类似于类中静态成员变量.静态成员变量也是全局共享,大小确定.

    所以我推测虚函数表和静态成员变量一样,存放在全局数据区.

    c/c++程序所占用的内存一共分为五种: 栈区,堆区,程序代码区,全局数据区(静态区),文字常量区.

    显而易见,虚函数表存放在全局数据区.

    几个值得注意的问题

    1、虚函数表是class specific的,也就是针对一个类来说的,这里有点像一个类里面的staic成员变量,即它是属于一个类所有对象的,不是属于某一个对象特有的,是一个类所有对象共有的。

    2、虚函数表是编译器来选择实现的,编译器的种类不同,可能实现方式不一样,就像前面我们说的vptr在一个对象的最前面,但是也有其他实现方式,不过目前gcc 和微软的编译器都是将vptr放在对象内存布局的最前面。

    3、虽然我们知道vptr指向虚函数表,那么虚函数表具体存放在内存哪个位置呢,虽然这里我们已经可以得到虚函数表的地址。实际上虚函数指针是在构造函数执行时初始化的,而虚函数表是存放在可执行文件中的。下面的一篇博客测试了微软的编译器将虚函数表存放在了目标文件或者可执行文件的常量段中,http://blog.csdn.net/vicness/article/details/3962767,不过我在gcc下的汇编文件中没有找到vtbl的具体存放位置,主要是对可执行文件的装载和运行原理还没有深刻的理解,相信不久有了这些知识之后会很轻松的找到虚函数表到底存放在目标文件的哪一个段中。

    4、经过测试,在gcc编译器的实现中虚函数表vtable存放在可执行文件的只读数据段.rodata中。

    虚函数表vtable在Linux/Unix中存放在可执行文件的只读数据段中(rodata),这与微软的编译器将虚函数表存放在常量段存在一些差别。

    展开全文
  • C++ 动态内存

    2018-03-02 16:19:34
    动态分配的对象的生存期与它们在哪里创建的无关,只有当显式地释放时,这些对象才会被销毁。 使用动态内存的一个常见原因为了让多个对象共享(不是拷贝)内部的数据,并使得当一个对象销毁时,该数据不会被销毁,...
  • 1. 栈(stack)与堆(heap)都Java用来Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,其对象存储位置由系统自然分配,程序员不能直接地...堆的优势可以动态地分配内存大小,生存期也不必事先告诉编译器...
  • 3、但:malloc和 new内存是在当前进程的私有地址空间中分配内存,并不能被所有进程共享。 4、所有:用GlobalAlloc分配内存,此内存不为任一进程私有,而是由操作系统管理。 5、特点:只能用于本地进程间通信。
  • 问题的提出:堆中的对象线程共享的,那么堆中可以有线程私有的空间吗? 给出答案:可以,就是TLAB,线程私有,都一份,提高效率、解决线程安全问题。 1.为什么有TLAB (Thread Local Allocation Buffer) ? 堆区...
  • QScopedPointer介绍

    2019-12-13 11:09:13
    zhezhelin QScopedPointer介绍 [Qt]QScopedPointer介绍 QScopedPointer ...但总有些时候我们需要在堆上分配一些空间,问题来了,我们该在哪里delete它,如何能够确保不产生内存泄露呢? QScoped...
  • 使用AllocateCommonBuffer分配两个视频帧大小物理内存设备中断中,交换前后buffer,分别送显和触发下一帧传送。搜索发现要使用FlushAdapterBuffers来刷新,但WDK提到common buffer master模式,不需要执行...
  • windowsnt 技术内幕

    2014-04-09 20:47:17
    复制用户帐号 为简化多个帐号的创建工作而建立用户帐号模板 删除和重新命名用户帐号 理解保护缺省的Administrator帐号的重要性 重新命名管理员帐号 理解缺省的Guest帐户 Windows NT在哪里创建帐号 设置口令限制条件 ...
  • 进程间通信的方式有 共享内存, 管道 ,Socket ,消息队列 , DDE等 18.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中? 答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理...
  • 答:Class可以被实例化,属于引用类型,是分配在内存的堆上的,Struct属于值类型,是分配在内存的栈上的. [Page] 26.根据委托(delegate)的知识,请完成以下用户控件中代码片段的填写: namespace test { public ...
  • FreePrinterNotifyInfo 释放由FindNextPrinterChangeNotification函数分配的一个缓冲区 GetForm 取得与指定表单有关的信息 GetJob 获取与指定作业有关的信息 GetPrinter 取得与指定打印机有关的信息 ...
  • Linux核心编程.pdf

    热门讨论 2010-09-17 18:03:34
    5.3.4 共享内存 51 第六章 PCI 53 6.1 PCI地址空间 53 6.2 PCI 配置头 54 6.3 PCI I/O和PCI内存地址 55 6.4 PCI-ISA 桥接器 56 6.5 PCI-PCI 桥接器 56 6.5.1 PCI-PCI桥接器:PCI I/O和PCI 内存窗口 56 6.5.2 PCI-PCI...
  • 主要是在把函数当值传递的时候用,或者是把函数当返回值,比如: <pre><code> JavaScript function d(callback){ callback(); } d(function(){ alert('123') }); //或者 function b()...
  • 1.1.8 NFS 和 SMB 最常见的两种 NAS(Network Attached Storage)协议,当把一个文件系统同时通过 NFS 和 SMB 协议共享给多个主机访问时,以下哪些说法错误的 1.1.9 输入 ping IP 后敲回车,发包前会发生什么?...
  • 预定义角色是在数据库安装后,系统自动创建的一些常用的角色。下面我们就简单介绍些系统角色:  CONNECT, RESOURCE, DBA这些预定义角色主要是为了向后兼容。其主要是用于数据库管理。oracle建议用户自己设计数据库...
  •  这本书里,你将会学到笔者性能优化方面的一些思路和思考,一些故障处理的方法和原则,这些东西笔者实践中长期积累的心得体会,笔者看来,掌握处理问题的方法和分析问题的思路日常工作中显得更为重要,...
  • 11.2.7 GUI中分配域名 135 11.2.8 设置动态路由分配 136 11.2.9 Red Hat发行版本中设置静态路由 分配 138 11.2.10 为计算机配置域名解析 139 11.2.11 建立LAN 140 11.2.12 配置打印服务 141 11.2.13 GUI中添加...
  • 11.2.7 GUI中分配域名 135 11.2.8 设置动态路由分配 136 11.2.9 Red Hat发行版本中设置静态路由 分配 138 11.2.10 为计算机配置域名解析 139 11.2.11 建立LAN 140 11.2.12 配置打印服务 141 11.2.13 ...

空空如也

空空如也

1 2
收藏数 39
精华内容 15
关键字:

共享内存是在哪里分配的