linux 共享内存存在哪个内存空间?

没有更多推荐了,
不良信息举报
举报内容:
LINUX共享内存使用常见陷阱与分析
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!linux中如何用shmget在共享内存中分配一个Map类型的空间?
[问题点数:100分,结帖人OracleJ]
linux中如何用shmget在共享内存中分配一个Map类型的空间?
[问题点数:100分,结帖人OracleJ]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2012年5月 专题开发/技术/项目大版内专家分月排行榜第二2010年3月 C/C++大版内专家分月排行榜第二
2012年4月 Linux/Unix社区大版内专家分月排行榜第三2011年7月 Linux/Unix社区大版内专家分月排行榜第三2010年2月 C/C++大版内专家分月排行榜第三
2005年6月 Linux/Unix社区大版内专家分月排行榜第二2005年2月 Linux/Unix社区大版内专家分月排行榜第二2004年11月 Linux/Unix社区大版内专家分月排行榜第二
2005年7月 Linux/Unix社区大版内专家分月排行榜第三2004年12月 Linux/Unix社区大版内专家分月排行榜第三
2013年6月 Linux/Unix社区大版内专家分月排行榜第二2013年5月 Linux/Unix社区大版内专家分月排行榜第二2013年3月 Linux/Unix社区大版内专家分月排行榜第二2013年1月 Linux/Unix社区大版内专家分月排行榜第二2012年12月 Linux/Unix社区大版内专家分月排行榜第二2012年8月 Linux/Unix社区大版内专家分月排行榜第二2011年12月 Linux/Unix社区大版内专家分月排行榜第二2011年10月 C/C++大版内专家分月排行榜第二2011年10月 Linux/Unix社区大版内专家分月排行榜第二
2012年6月 C/C++大版内专家分月排行榜第三2012年6月 PHP大版内专家分月排行榜第三2012年5月 C/C++大版内专家分月排行榜第三2012年3月 Linux/Unix社区大版内专家分月排行榜第三2012年2月 Linux/Unix社区大版内专家分月排行榜第三2011年11月 C/C++大版内专家分月排行榜第三
匿名用户不能发表回复!|在互联网兴盛之初,BBS曾火爆一时,大家都可以在这块共享的领地分享自己的故事和心情。在计算机的世界里,如果把每个进程比作一个人,那么它们之间交流的手段又是什么呢?就是我们下面要介绍的Windows中的共享内存机制。
在应用层面共享内存的使用
我们知道,在Windows中每个进程的地址空间都是相互独立的。换句话说,对于两个进程同样的虚拟地址,背后映射的物理内存并不相同(内核地址空间例外)。但有时会有这样的需求,要将两个进程中不同或者相同的地址映射为同一块物理内存,这样做的目的可以是:
1)这段内存是不可修改的可执行程序,两个进程使用同样的代码。简单的例子就是打开两个Word进程,其处理的文档可能不同,但是Word本身的代码是可以共用的,代码段的物理内存可以共用。
2)将一块相同的物理内存映射到不同的进程后,这两个进程可以通过这段物理内存实现进程之间的通信。
以上是共享内存标准的用法,但在实际应用中,共享内存还可以用于文件的映射,即将一个文件的一块区域映射到某一进程的地址空间内,该进程对文件的操作就转换为对内存(编程中表现为对数组)的操作,这样可以有效的减少I/O操作的数量,提高效率。为了让大家对共享内存有个初步的概念,我们先看看编程世界里对共享内存的使用方法,标准步骤如下:
①hFile=CreateFile(pszFileName,….);
//创建或者打开文件对象
②hFileMap=CreateFileMapping(hFile,…);//创建一个文件映射内核对象
③pbFile=MapViewOfFile(hFileMap,….);
//将文件映射对象的部分或者全部映射到进程的地址空间
④pbFile[0]=1;
//共享内存的使用
⑤UnMapViewOfFile(pbFile,…);//取消上一步骤的映射
⑥CloseHandle(hFileMap);
⑦CloseHandle(hFile);
//关闭文件映射内核对象
//关闭文件内核对象
共七个步骤,如果细看,可以发现步骤①与步骤⑦相对应,步骤②与步骤⑥相对应,步骤③与步骤⑤相对应,都是互相对应的反向操作。
在第②步中,CreateFileMapping()函数创建了一个文件映射内核对象,该函数使用一个由步骤①中CreateFile()函数打开并返回的文件句柄,但若是为了两个进程之间共享内存,此句柄可以设置为0xFFFFFFFF,表示使用系统页面文件,则步骤①可以省略。该函数最后一个参数可以为内存映射对象指定名字,通过调用CreateFileMapping函数和OpenFileMapping函数,其他进程可用这个名字来访问相同的文件映像。
CreateFileMapping函数创建成功文件映射内核对象后,步骤③调用MapViewOfFile函数,把文件的一块区域映射到进程地址空间上,调用这个函数需要指定文件映射对象、目标文件的起始地址、操作的数量等参数。
完成步骤③后,操作数组pbFile就等同于操作目标文件本身。当不再需要把文件的数据映射到进程空间时,调用步骤⑤中的UnMapViewOfFile函数解除映射,同时会将一些映射数据写入文件。最后在步骤⑥、⑦中,释放文件映射对象和文件对象。
如果上面的步骤通过编程,亲自实践,能够顺利完成的话,那么就是一个合格的Windows编程人员,但作为一名研究Windows内核的同仁,还要想的更多,在CreateFileMapping函数和MapViewOfFile函数背后,共享内存实现的奥秘是什么呢?
内核层面共享内存的实现
在最初学习这段内容的时候,看着N多个数据结构,N多的连接关系,密密麻麻如八爪鱼般邪恶。为了使读者少一些痛苦,轻松一些,下面我将按照前面介绍共享内存使用的步骤
①~③进行分步讲解。
1.CreateFile的工作
因为本文并不专门针对文件的操作,所以只涉及共享内存有关的内容。当我们使用CreateFile创建或者打开一个文件时,系统会创建一个文件对象,如果该文件再次被打开,会有一个新的文件对象被创建,打开N次,生成N个文件对象。在每个文件对象中,有一个指针指向一个叫做“内存区对象指针”的结构。
“内存区对象指针”由三个32位的指针组成:指向共享的高速缓存映射的指针、指向数据控制区域的指针和指向映像控制区域的指针。指向共享的高速缓存映射的指针用于文件的缓存管理,是一个很重要的概念,以后的文章会有详细的描述,而后两者都指向控制区域结构,分别用来映射数据(Data)文件和可执行(Image)文件。
2.CreateFileMapping的工作
前面提到,CreateFileMapping函数会创建文件映射对象(FileMappingObject),该对象还有一个别名,叫做内存区对象(SectionObject)。内存区对象有两种:一种是需要具体文件支撑的,这个文件可以是可执行(Image)文件(Image),也可以是数据(Data)文件,通常这种内存区对象用于文件的映射操作,因此可以说这种内存区对象背靠的是映射文件。还有一种内存区对象是不需要具体文件,而使用页面文件支撑的,这种内存区对象通常用于两个或者多个进程共享内存,进行进程间通信,所以可以说这种内存区对象背靠的是页面文件。
注意,所谓的页面文件是操作系统创立的文件,专门用于将使用次数少的内存进行存储,从而空出内存,所以可以认为页面文件是内存的一个背靠文件。
CreateFileMapping函数通过间接调用MmCreateSection函数完成内存区对象的创建。
MmCreateSection函数实现的逻辑如下:
1)如果FileHandle非空,代表该内存区对象由映射文件支撑,那么新建一个Control_Area对象,并用文件对象中的信息填充,利用MiCreateImageFileMap或者MiCreateDataFileMap创建一个新的segment对象;
2)如果FileHandle为空,代表该内存区对象由页面文件支撑,则调用MiCreatePagingFileMap创建一个控制区对象和segment对象,而并不涉及到文件对象;
3)利用ObCreateObject函数创建section对象,并填充相应信息,返回该section对象。
好了,一会功夫,蹦出三个对象:控制区域(Control_Area)对象,内存区(Section)对象和段(Segment)对象,对象多了好头疼!
内存区对象:内存区对象属于内核对象之一,有标准的对象头,也有对象体,对象头由对象管理器负责,而对象体的内容由内存管理器管理,其对象体结构如下:
typedefstruct_SECTION{
MMADDRESS_NODEA
//当这个section是可执行程序时,放于专门存放可执行程序的VAD树中PSEGMENTS//指向段对象LARGE_INTEGERSizeOfS//内存区的大小union{ULONGLongFMMSECTION_FLAGSF}u;
//内存区的一组标志
MM_PROTECTION_MASKInitialPageP//页面保护模式
}SECTION,*PSECTION;
typedefstruct_CONTROL_AREA{
//指向段对象
ULONGNumberOfMappedV//反映了与之关联的内存区对象被映射了多少次
PFILE_OBJECTFileP
PEVENT_COUNTERWaitingForD
USHORTModifiedWriteC
USHORTFlushInProgressC
ULONGWritableUserR
ULONGQuadwordP
//指向文件对象
}CONTROL_AREA,*PCONTROL_AREA;
这个数据结构是Control_Area对象结构的主体,一个完整的Control_Area对象之后还紧跟着N个SUBSECTION结构,每个SUBSECTION对应着文件中的一个SECTION,用于描述文件中每节映射信息(只读、读写、写时复制等)。例如,我们知道一个PE文件有N个节(section,这个section和前面提到的不一样,它是PE文件的组成部分,可以翻译为“节”),那么PE文件中有几个节,在Control_Area对象中就有多少个Subsection。所有的SUBSECTION结构构成一个单链表,每个SUBSECTION结构有一个指针指回到Control_Area对象结构。
段对象的结构体如下:
typedefstruct_SEGMENT{
struct_CONTROL_AREA*ControlA
ULONGTotalNumberOfP
ULONGNonExtendedP
UINT64SizeOfS
MMPTESegmentPteT
SEGMENT_FLAGSSegmentF
PVOIDBasedA
PSECTION_IMAGE_INFORMATIONImageI
PVOIDFirstMappedVa;
PMMPTEPrototypeP
MMPTEThePtes[MM_PROTO_PTE_ALIGNMENT/PAGE_SIZE];
}SEGMENT,*PSEGMENT;
Segment段对象在分页缓冲池中分配,用来描述和存放内存区数据。大家会注意到该结
构中有很多PTE的字样,一个完整的Segment段对象除了上述的结构,紧接着还会有一个
PTE数组,形成一个原型PTE阵列,用于完成将内存区对象实际映射到物理内存上。
列出以上三个对象的数据结构,我们先看看它们之间的连接关系,如图2所示。
图2CreateFileMapping函数所做的工作
当控制区域对象被创建后,如果该内存区对象为可执行文件,则内存区对象指针中的映像控制指针指向该控制区域对象,如果该文件为数据文件,则内存区对象指针中的数据控制指针指向该控制区域对象。
3.MapViewOfFile的工作
好的,现在对象以及各个对象之间的关系都已经创建了,应用程序获得了内存区对象的句柄,但还不能访问内存区对象中的数据。为了使用内存区对象中的数据,应用程序必须映射一个视图,将内存区对象描述的地址映射到进程的地址空间,这个步骤由Windows内核的系统服务例程NtMapViewOfSection函数完成,对应于内存管理器中的函数是MmMapViewOfSection函数。
MmMapViewOfSection函数的大致逻辑是这样的:由内存区对象→段对象→控制区对象中的标志信息确定内存区的类型:
①若PhysicalMemory位为1,则映射的类型为物理内存,使用MiMapViewOfSpecialSection函数来映射内存区;
②若Image位为1,表明内存区对象是个镜像文件,则调用MiMapViewOflmageSection函数来映射内存区;
③若非以上两种情况,那么内存区对象为数据文件或者页面文件,则调用MiMapViewOfDataSection函数来映射。
下面我们以MiMapViewOfDataSection函数的逻辑为例,该函数大体完成两个任务:①在进程地址空间中找到内存区对象声明大小的空闲地址范围,建立一个与该地址范围对应的VAD对象之后,将该VAD对象中的ControlArea指向在CreateSection函数中创建的控制区对象,并将该VAD节点插入到进程的VAD树中;②针对该地址范围,设置相应页表中的内容
为段对象中的SegmentPteTemplate值。如果该内存区对象是使用页面文件支撑的,则仅设置保护属性。
在调用过MiMapViewOfDataSection函数后,系统就已经完成了从虚拟地址到物理内存再到文件的映射,应用程序就可以通过访问内存的方式来访问文件或者共享内存,其结构如图3所示。
图3MapViewOfFile函数所做的工作
4.原型PTE的使用
在前面的内容我们经常提到原型PTE,下面我们看看原型PTE的庐山真面目!可以说原型PTE是实现共享内存最根本的机制。一个原型PTE可以描述6种状态的页面:
①有效。对应的页面位于物理内存中,此时原型PTE已经是一个有效的PTE。
②位于页面文件中,对应的页面位于页面文件中。
③位于映射文件中,对应的页面位于映射文件中。
还有三种状态的页面分别是:要求零页面,转移页面,已修改但不写出页面。前面提到,在段对象中包含了内存区对应页面的原型PTE阵列,当进程访问该内存区对象中的页面时,内存管理器将页面对应的原型PTE中的内容填充到对应的页表PTE中,下面不妨用例子来说明。
为了表达更清楚,我们将进程A中P1页面的PTE定义为PTE1,进程B中P1页面的PTE定义为PTE2。
假设进程A和进程B共享一个内存区对象,而该内存区包含一个页面P1,目前该页面还没有被访问过,所以进程A和进程B中对应页面的PTE是无效的,并且都指向段对象中的P1的原型PTE,而该原型PTE指向页面文件中的页面P1,如图4所示。
图4原型PTE使用的例子,阶段1
当一个共享页面无效时,进程页表中的页表项由一个特殊的页表项来填充。这个特殊的页表项指向描述该页面的原型页表项,此时PTE1和PTE2中的格式如图5所示,其中有效位为0表示这是一个无效的PTE,原型位为1,表示这是一个指向原型PTE的PTE,两段原型PTE地址组成0~27共28位的地址,因为每个PTE是四个字节,所以28位的地址可以用来描述30位的空间。因为段对象在系统换页池中分配,那么原型PTE都在换页内存池中,因此图5中原型PTE的地址指的是该原型PTE相对于系统换页内存池起始位置的偏移。
图5指向原型PTE的无效PTE
为了将图5所示结构中的原型PTE地址转换为虚拟内存地址,需要将其进行转换,转换方法如图6所示。
将上图右移11位再左移9位得到原型PTE地址7—27位将上图左移24位再右移23位得到
图6PTE转换为虚拟地址(偏移)
因此,我们可以看到WRK中会有以下转换宏:
MiPteToProto(lpte)(PMMPTE)((PMMPTE)((((lpte)-&u.loong)&&11&&9)+\((((lpte)-&u.long))&&24)&&23)+MmProtopte_Base))
其中MmProtopte_Base定义为:#defineMmProtopte_Base((ULONG)MmPagedPoolStart)
实际上也就是换页内存池的开始位置。
当进程A访问该页面时,发生访问违例,系统将页面P1倒入内存,并将其页面号赋予段对象中的指向P1的原型PTE,同时将此原型PTE赋予PTE1,如图7所示;此时PTE1和段对象中的原型PTE的内容是一致的,都是有效的PTE,而PTE2则仍然是一个如图5所示的结构。
图7原型PTE使用的例子,阶段2
当进程B访问此页面时,依然会发生访问违例,发现指向此页面的PTE是个原型PTE(由原型位为1,valid位为0),并且页面已经导入内存,那么就直接将段对象中的对应的原型PTE赋予PTE2,从而快速的实现页面共享。为了跟踪每个共享页面的使用情况,在物理页面对应的帧号数据库中记录了该页面被几个进程共享,当一个共享页面已经不再被任何页表引用,内存管理器会将这个页面标记为无效,并将其移到转换链表或写回外存。如图8所示。
图8原型PTE使用的例子,阶段3
另外如在图7的状态下,内存区对象中的一个页面从有效变成无效时,它的硬件PTE将直接指向原型PTE,恢复图4中的状态。
共享内存不仅应用于进程间内存共享,也用于将文件映射到进程的地址空间,从而实现文件的快速访问。本文讲解了共享内存的实现机制,重点是要理解CreateFileMapping函数和MapViewOfFile函数所做的工作以及原型PTE的原理。新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
稍有积蓄, 积分 211, 距离下一级还需 289 积分
论坛徽章:0
请教有经验的大虾,如何在共享内存里面动态分配一块数据结构?
struct A {
& & int host_
& & int acct_
& & struct host_info {
& && &&&char hostname[128];
& && &&&int& &
& & } host_info [host_cnt];
& & struct acct_info {
& && &&&char acctname[128];
& && &&&int& &
& & } host_info[acct_cnt];
host_cnt的值是外部文件配置的,需要程序读入。acct_cnt也是外部文件配置的,需要程序读入。
然后根据这两个个数的值,在共享内存里面动态开辟两个结构体数组 。
host_into 的个数依赖于host_cnt的值,acct_info的个数依赖于acct_cnt的值。
在共享内存里面,好像用指针的话设计到对齐问题。
有做过这方面的大虾么?谢谢
稍有积蓄, 积分 211, 距离下一级还需 289 积分
论坛徽章:0
大虾还没有现身么?
大富大贵, 积分 11628, 距离下一级还需 8372 积分
论坛徽章:250
struct A {
& & int host_
& & int acct_
& & struct host_info {
& && &&&char hostname[128];
& && &&&int& &
& & struct acct_info {
& && &&&char acctname[128];
& && &&&int& &
开sizeof(A)+host_cnt*sizeof(host_info)+acct_cnt*sizeof(acct_info)大的共享内存即可
白手起家, 积分 48, 距离下一级还需 152 积分
论坛徽章:0
两个结构大小实际是一样的,可以先申请一块共享内存,划分成合适大小的块(上述结构体大小做字节对齐后的值,具体字节对齐取决于自己的需求),每需要增加一种类型就分配一个块。当申请的共享内存用完后,可以继续申请,上层加一个简单的共享内存管理就可以了。
稍有积蓄, 积分 211, 距离下一级还需 289 积分
论坛徽章:0
& & 非常感谢大牛的回复。谢谢。
&&想问一下。您给点这个方案。实际上就是按照结构体顺序存储去做。是吧?
&&这里面不涉及到字节填充的问题?
& &struct host_info {
& && &&&char hostname[121];
& && &&&char&&
这样的话按照你说的分配方法也是没有问题的?对吧?
大富大贵, 积分 11628, 距离下一级还需 8372 积分
论坛徽章:250
回复&&hellioncu
& & 非常感谢大牛的回复。谢谢。
&&想问一下。您给点这个方案。实际上就是按照结 ...
pinecrane 发表于
& & 上面的几个都自然对齐了的,这个需要自己处理下,省心点可以全部按8字节对齐。如果没有限制以及不考虑性能全部都按1字节紧凑存放也行
大富大贵, 积分 11628, 距离下一级还需 8372 积分
论坛徽章:250
& & 起始指针+偏移量,再强制转换成你需要的结构指针
稍有积蓄, 积分 211, 距离下一级还需 289 积分
论坛徽章:0
& & 严重感谢大牛。我顶你。
& &和你学到很多东西。谢谢啊。
& &我已经按照你的思路写测试代码,如果OK。我会在这里报告一下。
&&再次感谢
稍有积蓄, 积分 211, 距离下一级还需 289 积分
论坛徽章:0
& & 再次感谢大牛!
& &我自己写了个测试代码,这个问题解决了。
& &并且我用的struct里面的成员有的是非4字节对齐的。但是发现可以正确存入共享内存,也可以正确读出。
& &我是用的sizeof(A) + sizeof(B) * cnt_B + sizeof(C) * cnt_C 来开辟共享内存空间的。
& &然后往里面的对应的结构体成员赋值的时候。就用指针进行强制类型转换进行结构体数组的遍历赋值。
& &摘录如下:
& &iShmid = shmget(....);
& & arMsg = (void *)shmat(...);
& & arCountInfo = (MSG_STRU *)arM
& & arCountInfo-&host_cnt = host_
& & arCountInfo-&acct_cnt = acct_
& & arHostInfo = (HOST_INFO_STRU *)( arCountInfo + 1 );
& & for ( index = 0; index & host_ index++ )
& && && & sprintf( arHostInfo[index].hostname, &...&);
& && && & sprintf( arHostInfo[index].bflag, &...&);
& & arAcctInfo = (ACCT_INFO_STRU *)( arHostInfo + host_cnt );
& & for ( index = 0; index & acct_ index++ )
& && &&&sprintf( arAcctInfo[index].acctname, &...&);
& && &&&sprintf( arAcctInfo[index].bflag, &...&);
& & 这样看来即使定义的结构体有未对齐的,但是在sizeof的时候计算的是编译器已经填充好的SIZE,
&&并且后面往结构体数组的每一个成员赋值的时候,用指针进行offset的步进操做,那么这样做即使
&&是未对齐的也可以。
&&大牛你觉得我的理解正确么?谢谢
大富大贵, 积分 11628, 距离下一级还需 8372 积分
论坛徽章:250
& & 别叫大牛了,怪怪的{:3_189:}
本来不对齐也未必出问题,看是什么硬件架构的了。
如果你前面一个结构类似
& & char&&str[11];
这样的,count是3个,这样后面那个结构就不会对齐了
北京盛拓优讯信息技术有限公司. 版权所有 京ICP备号 北京市公安局海淀分局网监中心备案编号:22
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处正在初始化报价器笔记本共享内存容量是什么意思谁知道?2个回答soufun-s就是集成显卡,自己不带独立的显存,需要划走一部分内存当成显存使用。
共享系统内存就是拿一部分内存当显存,集成显卡和独立显卡都可以共享系统内存。
共享系统内存对玩游戏影响非常大,因为集成显卡效果不好,会影响Win7的视觉特效,所以共享内存技术多数用在集成显卡的主板上。
xiayunmo21you这表示你的显卡是集成显卡,对于显卡而言,是需要一定空间来存储数据的,而集成显卡没有设计储存空间,为了能运行,便借用内存的空间,这就是显卡共享内存空间,一般来讲是512M大小,也有更大或更小的,但不多
热门问答123456789101112131415161718192021222324252627282930相关问答1个回答填啥名能麻烦我觉得这个好像挺难评定的,太多房地产中介公司了,而且也没听说过哪家出名或者哪家厉害的。。 所以……就……3个回答猴掷堑19控制好预算。2个回答小鬼00805怎么说也算是笔记本吧,集成度比较高,应该是6层电路的板吧!1个回答2cc695bf1.选购这类桌子的时候,要注意焊接处是否光滑和无空隙。要注意镀膜是否均匀、柔和,弹簧的性能好不好。要看卡口是否牢固,滑槽涩不涩。要看框架的整体质量,用两手将整个折叠桌前后左右摇一摇...1个回答小南方方方胶管是不能走暗墙的。可以改用不锈钢的波纹管。可以在厨柜里走暗管。大多数柜内的都不会超过4M。专业师傅安装后是无问题的。我自己家装的,连接灶具的波纹管是2M。接燃气热水器的估计在4....1个回答点操萍乡瘙t大家都知道,一批货从厂里出来,先给一级批发商,再转到二级批发商,再给零售商~除非是直销~每经过1手价格都加一些,因为商家是要赚钱滴~ 不是说拿货不能到厂家拿,而是因为一般从厂家拿货...3个回答我_我朋友前几天买了台西班牙爱握乐空气能热水器5500元.用起来挺好的,方便省电 西安市场现在也有,我过两天去看看2个回答率土之滨95B你最好去问问 最长也就1个月吧 我的2个星期就下来了 一般跟银行有点关系的话会很快哦2个回答fanky2005加软包3个回答晴天764忘记密码,通过注册帐号时的手机号或者邮箱找回密码}

我要回帖

更多关于 b199共享内存空间版本 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信