




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、.FrameBuffer的原理118131 0500 20 0OTHER 119 042 4243 01 0星级BLOG 0yjvijfhvk#FFFFFF#187218 no-repeat _blank 142802 02020-08-22 22:10:52 148752 02020-12-12 19:00:32 149421 02020-12-25 22:18:31 142904 02020-08-25 00:12:50 142900 02020-08-24 23:40:46 143241 02020-08-29 21:58:21 143218 02020-08-29 13:44:47 1
2、42597 02020-08-18 23:50:04 142902 02020-08-25 00:11:34 142602 02020-08-18 23:51:00 144883 02020-09-27 20:50:30"20202019","20202022","20202024","20202025","20202029","20202030","20202031","20202001","20202002",&
3、quot;20202005","20202006","20202027","20202006","20202020","20202020","20202020","20202020","20202021","20202021","20202106","20202112","20202123","20202124","2
4、0202125",""2448686 149421 2020-12-25 22:26:35 2020-12-25 22:26:35 10 0FrameBuffer的原理FrameBuffer是出如今2.2.xx内核当中的一种驱动程序接口。Linux是工作在保护形式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模拟显卡的功能,将显卡硬件构造抽象掉,可以通过Framebuffer的读写直接对显存进展操作。用户可以将Framebuff
5、er看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进展读写操作,而写操作可以立即反响在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等详细细节。这些都是由Framebuffer设备驱动来完成的。但Framebuffer本身不具备任何运算数据的才能,就只好比是一个暂时存放水的水池.CPU将运算后的结果放到这个水池,水池再将结果流到显示器.中间不会对数据做处理.应用程序也可以直接读写这个水池的内容.在这种机制下,尽管Framebuffer需要真正的显卡驱动的支持,但所有显示任务都有CPU完成,因此CPU负担很重.framebuffer的设备文件一般是/d
6、ev/fb0、/dev/fb1等等。可以用命令:#dd if=/dev/zero of=/dev/fb清空屏幕.假设显示形式是1024x768-8位色,用命令:$dd if=/dev/zero of=/dev/fb0 bs=1024 count=768清空屏幕用命令:#dd if=/dev/fb of=fbfile可以将fb中的内容保存下来;可以重新写回屏幕:#dd if=fbfile of=/dev/fb在使用Framebuffer时,Linux是将显卡置于图形形式下的.在应用程序中,一般通过将FrameBuffer设备映射到进程地址空间的方式使用,比方下面的程序就翻开/dev/fb0设备,
7、并通过mmap系统调用进展地址映射,随后用memset将屏幕清空这里假设显示形式是1024x768-8位色形式,线性内存形式:int fb;unsigned char*fb_mem;fb=open"/dev/fb0",O_RDWR;fb_mem=mmapNULL,1024*768,PROT_READ|PROT_WRITE,MAP_SHARED,fb,0;memsetfb_mem,0,1024*768;FrameBuffer设备还提供了假设干ioctl命令,通过这些命令,可以获得显示设备的一些固定信息比方显示内存大小、与显示形式相关的可变信息比方分辨率、象素构造、每扫描线的字
8、节宽度,以及伪彩色形式下的调色板信息等等。通过FrameBuffer设备,还可以获得当前内核所支持的加速显示卡的类型通过固定信息得到,这种类型通常是和特定显示芯片相关的。比方目前最新的内核2.4.9中,就包含有对S3、Matrox、nVidia、3Dfx等等流行显示芯片的加速支持。在获得了加速芯片类型之后,应用程序就可以将PCI设备的内存I/Omemio映射到进程的地址空间。这些memio一般是用来控制显示卡的存放器,通过对这些存放器的操作,应用程序就可以控制特定显卡的加速功能。PCI设备可以将自己的控制存放器映射到物理内存空间,而后,对这些控制存放器的,给变成了对物理内存的访问。因此,这些存
9、放器又被称为"memio"。一旦被映射到物理内存,Linux的普通进程就可以通过mmap将这些内存I/O映射到进程地址空间,这样就可以直接访问这些存放器了。当然,因为不同的显示芯片具有不同的加速才能,对memio的使用和定义也各自不同,这时,就需要针对加速芯片的不同类型来编写实现不同的加速功能。比方大多数芯片都提供了对矩形填充的硬件加速支持,但不同的芯片实现方式不同,这时,就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。FrameBuffer只是一个提供显示内存和显示芯片存放器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,假设希望在FrameBuf
10、fer之上进展图形编程,还需要自己动手完成其他许多工作。二、FrameBuffer在LINUX中实现和机制Framebuffer对应的源文件在linux/drivers/video/目录下。总的抽象设备文件为fbcon.c,在这个目录下还有与各种显卡驱动相关的源文件。一、分析Framebuffer设备驱动需要特别提出的是在INTEL平台上,老式的VESA 1.2卡,如CGA/EGA卡,是不能支持Framebuffer的,因为Framebuffer要求显卡支持线性帧缓冲,即CPU可以访问显缓冲中的每一位,但是VESA 1.2卡只能允许CPU一次访问64K的地址空间。FrameBuffer设备驱动
11、基于如下两个文件:1linux/include/linux/fb.h 2linux/drivers/video/fbmem.c下面分析这两个文件。1、fb.h几乎主要的构造都是在这个中文件定义的。这些构造包括:1fb_var_screeninfo这个构造描绘了显示卡的特性:struct fb_var_screeninfo_u32 xres;/*visible resolution*/_u32 yres;_u32 xres_virtual;/*virtual resolution*/_u32 yres_virtual;_u32 xoffset;/*offset from virtual to v
12、isible resolution*/_u32 yoffset;_u32 bits_per_pixel;/*guess what*/_u32 grayscale;/*!=0 Gray levels instead of colors*/struct fb_bitfield red;/*bitfield in fb mem if true color,*/struct fb_bitfield green;/*else only length is significant*/struct fb_bitfield blue;struct fb_bitfield transp;/*transparen
13、cy*/_u32 nonstd;/*!=0 Non standard pixel format*/_u32 activate;/*see FB_ACTIVATE_*/_u32 height;/*height of picture in mm*/_u32 width;/*width of picture in mm*/_u32 accel_flags;/*acceleration flagshints*/*Timing:All values in pixclocks,except pixclockof course*/_u32 pixclock;/*pixel clock in pspico s
14、econds*/_u32 left_margin;/*time from sync to picture*/_u32 right_margin;/*time from picture to sync*/_u32 upper_margin;/*time from sync to picture*/_u32 lower_margin;_u32 hsync_len;/*length of horizontal sync*/_u32 vsync_len;/*length of vertical sync*/_u32 sync;/*see FB_SYNC_*/_u32 vmode;/*see FB_VM
15、ODE_*/_u32 reserved6;/*Reserved for future compatibility*/;2fb_fix_screeninfon这个构造在显卡被设定形式后创立,它描绘显示卡的属性,并且系统运行时不能被修改;比方FrameBuffer内存的起始地址。它依赖于被设定的形式,当一个形式被设定后,内存信息由显示卡硬件给出,内存的位置等信息就不可以修改。struct fb_fix_screeninfochar id16;/*identification string eg"TT Builtin"*/unsigned long smem_start;/*St
16、art of frame buffer mem*/*physical address*/_u32 smem_len;/*Length of frame buffer mem*/_u32 type;/*see FB_TYPE_*/_u32 type_aux;/*Interleave for interleaved Planes*/_u32 visual;/*see FB_VISUAL_*/_u16 xpanstep;/*zero if no hardware panning*/_u16 ypanstep;/*zero if no hardware panning*/_u16 ywrapstep;
17、/*zero if no hardware ywrap*/_u32 line_length;/*length of aline in bytes*/unsigned long mmio_start;/*Start of Memory Mapped I/O*/*physical address*/_u32 mmio_len;/*Length of Memory Mapped I/O*/_u32 accel;/*Type of acceleration available*/_u16 reserved3;/*Reserved for future compatibility*/;3fb_cmap描
18、绘设备无关的颜色映射信息。可以通过FBIOGETCMAP和FBIOPUTCMAP对应的ioctl操作设定或获取颜色映射信息.struct fb_cmap_u32 start;/*First entry*/_u32 len;/*Number of entries*/_u16*red;/*Red values*/_u16*green;_u16*blue;_u16*transp;/*transparency,can be NULL*/;4fb_info定义当显卡的当前状态;fb_info构造仅在内核中可见,在这个构造中有一个fb_ops指针,指向驱动设备工作所需的函数集。struct fb_info
19、char modename40;/*default video mode*/kdev_t node;int flags;int open;/*Has this been open already?*/#define FBINFO_FLAG_MODULE 1/*Low-level driver is amodule*/struct fb_var_screeninfo var;/*Current var*/struct fb_fix_screeninfo fix;/*Current fix*/struct fb_monspecs monspecs;/*Current Monitor specs*/
20、struct fb_cmap cmap;/*Current cmap*/struct fb_ops*fbops;char*screen_base;/*Virtual address*/struct display*disp;/*initial display variable*/struct vc_data*display_fg;/*Console visible on this display*/char fontname40;/*default font name*/devfs_handle_t devfs_handle;/*Devfs handle for new name*/devfs
21、_handle_t devfs_lhandle;/*Devfs handle for compat.symlink*/int*changevarint;/*tell console var has changed*/int*switch_conint,struct fb_info*;/*tell fb to switch consoles*/int*updatevarint,struct fb_info*;/*tell fb to update the vars*/void*blankint,struct fb_info*;/*tell fb tounblank the screen*/*ar
22、g=0:unblank*/*arg 0:VESA levelarg-1*/void*pseudo_palette;/*Fake palette of 16 colors and the cursor's color for non palette mode*/*From here on everything is device dependent*/void*par;5struct fb_ops用户应用可以使用ioctl系统调用来操作设备,这个构造就是用一支持ioctl的这些操作的。struct fb_ops/*open/release and usage marking*/struc
23、t module*owner;int*fb_openstruct fb_info*info,int user;int*fb_releasestruct fb_info*info,int user;/*get non settable parameters*/int*fb_get_fixstruct fb_fix_screeninfo*fix,int con,struct fb_info*info;/*get settable parameters*/int*fb_get_varstruct fb_var_screeninfo*var,int con,struct fb_info*info;/*
24、set settable parameters*/int*fb_set_varstruct fb_var_screeninfo*var,int con,struct fb_info*info;/*get colormap*/int*fb_get_cmapstruct fb_cmap*cmap,int kspc,int con,struct fb_info*info;/*set colormap*/int*fb_set_cmapstruct fb_cmap*cmap,int kspc,int con,struct fb_info*info;/*pan displayoptional*/int*f
25、b_pan_displaystruct fb_var_screeninfo*var,int con,struct fb_info*info;/*perform fb specific ioctloptional*/int*fb_ioctlstruct inode*inode,struct file*file,unsigned int cmd,unsigned long arg,int con,struct fb_info*info;/*perform fb specific mmap*/int*fb_mmapstruct fb_info*info,struct file*file,struct
26、 vm_area_struct*vma;/*switch to/from raster image mode*/int*fb_rasterimgstruct fb_info*info,int start;6structure map struct fb_info_gen|struct fb_info|fb_var_screeninfo|fb_fix_screeninfo|fb_cmap|modename40|fb_ops-|-ops on var|.|fb_open|fb_release|fb_ioctl|fb_mmap|struct fbgen_hwswitch-|-detect|encod
27、e_fix|encode_var|decode_fix|decode_var|get_var|set_var|getcolreg|setcolreg|pan_display|blank|set_disp编排有点困难,第一行的第一条竖线和下面的第一列竖线对齐,第一行的第二条竖线和下面的第二列竖线对齐就可以了这个构造fbgen_hwswitch抽象了硬件的操作.虽然它不是必需的,但有时候很有用.2、fbmem.c fbmem.c处于Framebuffer设备驱动技术的中心位置.它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己.
28、fbmem.c为所有支持FrameBuffer的设备驱动提供了通用的接口,防止重复工作.1全局变量struct fb_info*registered_fbFB_MAX;int num_registered_fb;这两变量记录了所有fb_info构造的实例,fb_info构造描绘显卡的当前状态,所有设备对应的fb_info构造都保存在这个数组中,当一个FrameBuffer设备驱动向系统注册自己时,其对应的fb_info构造就会添加到这个构造中,同时num_registered_fb为自动加1.static structconst char*name;int*initvoid;int*setup
29、void;fb_drivers _initdata=.;假设FrameBuffer设备被静态链接到内核,其对应的入口就会添加到这个表中;假设是动态加载的,即使用insmod/rmmod,就不需要关心这个表。static struct file_operations fb_ops=owner:THIS_MODULE,read:fb_read,write:fb_write,ioctl:fb_ioctl,mmap:fb_mmap,open:fb_open,release:fb_release;这是一个提供给应用程序的接口.2fbmem.c实现了如下函数.register_framebufferstr
30、uct fb_info*fb_info;unregister_framebufferstruct fb_info*fb_info;这两个是提供给下层FrameBuffer设备驱动的接口,设备驱动通过这两函数向系统注册或注销自己。几乎底层设备驱动所要做的所有事情就是填充fb_info构造然后向系统注册或注销它。二一个LCD显示芯片的驱动实例以Skeleton LCD控制器驱动为例,在LINUX中存有一个/fb/skeleton.c的skeleton的Framebuffer驱动程序,很简单,仅仅是填充了fb_info构造,并且注册/注销自己。设备驱动是向用户程序提供系统调用接口,所以我们需要实现底
31、层硬件操作并且定义file_operations构造来向系统提供系统调用接口,从而实现更有效的LCD控制器驱动程序。1在系统内存中分配显存在fbmem.c文件中可以看到,file_operations构造中的open和release操作不需底层支持,但read、write和mmap操作需要函数fb_get_fix的支持.因此需要重新实现函数fb_get_fix。另外还需要在系统内存中分配显存空间,大多数的LCD控制器都没有自己的显存空间,被分配的地址空间的起始地址与长度将会被填充到fb_fix_screeninfo构造的smem_start和smem_len的两个变量中.被分配的空间必须是物理
32、连续的。2实现fb_ops中的函数用户应用程序通过ioctl系统调用操作硬件,fb_ops中的函数就用于支持这些操作。注:fb_ops构造与file_operations构造不同,fb_ops是底层操作的抽象,而file_operations是提供给上层系统调用的接口,可以直接调用.ioctl系统调用在文件fbmem.c中实现,通过观察可以发现ioctl命令与fb_ops's中函数的关系:FBIOGET_VSCREENINFO fb_get_var FBIOPUT_VSCREENINFO fb_set_var FBIOGET_FSCREENINFO fb_get_fix FBIOPUT
33、CMAP fb_set_cmap FBIOGETCMAP fb_get_cmap FBIOPAN_DISPLAY fb_pan_display假设我们定义了fb_XXX_XXX方法,用户程序就可以使用FBIOXXXX宏的ioctl操作来操作硬件。文件linux/drivers/video/fbgen.c或者linux/drivers/video目录下的其它设备驱动是比较好的参考资料。在所有的这些函数中fb_set_var是最重要的,它用于设定显示卡的形式和其它属性,下面是函数fb_set_var的执行步骤:1检测是否必须设定形式2设定形式3设定颜色映射4根据以前的设定重新设置LCD控制器的各存
34、放器。第四步说明了底层操作到底放置在何处。在系统内存中分配显存后,显存的起始地址及长度将被设定到LCD控制器的各存放器中一般通过fb_set_var函数,显存中的内容将自动被LCD控制器输出到屏幕上。另一方面,用户程序通过函数mmap将显存映射到用户进程地址空间中,然后用户进程向映射空间发送的所有数据都将会被显示到LCD显示器上。三、FrameBuffer的应用一、一个使用FrameBuffer的例子1、FrameBuffer主要是根据VESA标准的实现的,所以只能实现最简单的功能。2、由于涉及内核的问题,FrameBuffer是不允许在系统起来后修改显示形式等一系列操作。好象很多人都想要这样
35、干,这是不被允许的,当然假设你自己写驱动的话,是可以实现的.3、对FrameBuffer的操作,会直接影响到本机的所有控制台的输出,包括XWIN的图形界面。好,如今可以让我们开场实现直接写屏:1、翻开一个FrameBuffer设备2、通过mmap调用把显卡的物理内存空间映射到用户空间3、直接写内存。/*File name:fbtools.h*/#ifndef _FBTOOLS_H_#define _FBTOOLS_H_#i nclude/a framebuffer device structure;typedef struct fbdevint fb;unsigned long fb_mem_
36、offset;unsigned long fb_mem;struct fb_fix_screeninfo fb_fix;struct fb_var_screeninfo fb_var;char dev20;FBDEV,*PFBDEV;/open&init aframe buffer/to use this function,/you must set FBDEV.dev="/dev/fb0"/or"/dev/fbX"/it's your frame fb_openPFBDEV pFbdev;/close aframe
37、 buffer int fb_closePFBDEV pFbdev;/get display depth int get_display_depthPFBDEV pFbdev;/full screen clear void fb_memsetvoid*addr,int c,size_t len;#endif/*File name:fbtools.c*/#i nclude#i nclude#i nclude#i nclude#i nclude#i nclude#i nclude#i nclude#i nclude"fbtools.h"#define TRUE 1#define
38、 FALSE 0#define MAXx,yxy?xy#define MINx,yx/open&init aframe buffer int fb_openPFBDEV pFbdevpFbdev-fb=openpFbdev-dev,O_RDWR;ifpFbdev-fbprintf"Error opening%s:%m.Check kernel confign",pFbdev-dev;return FALSE;if-1=ioctlpFbdev-fb,FBIOGET_VSCREENINFO,&pFbdev-fb_varprintf"ioctl FBIO
39、GET_VSCREENINFOn";return FALSE;if-1=ioctlpFbdev-fb,FBIOGET_FSCREENINFO,&pFbdev-fb_fixprintf"ioctl FBIOGET_FSCREENINFOn";return FALSE;/map physics address to virtual address pFbdev-fb_mem_offset=unsigned longpFbdev-fb_fix.smem_start&PAGE_MASK;pFbdev-fb_mem=unsigned long intmmap
40、NULL,pFbdev-fb_fix.smem_len+pFbdev-fb_mem_offset,PROT_READ|PROT_WRITE,MAP_SHARED,pFbdev-fb,0;if-1L=longpFbdev-fb_memprintf"mmap error!mem:%d offset:%dn",pFbdev-fb_mem,pFbdev-fb_mem_offset;return FALSE;return TRUE;/close frame buffer int fb_closePFBDEV pFbdevclosepFbdev-fb;pFbdev-fb=-1;/get
41、 display depth int get_display_depthPFBDEV pFbdev;ifpFbdev-fbprintf"fb device not open,open it firstn";return FALSE;return pFbdev-fb_var.bits_per_pixel;/full screen clear void fb_memsetvoid*addr,int c,size_t lenmemsetaddr,c,len;/use by test#define DEBUG#ifdef DEBUG mainFBDEV fbdev;memset&a
42、mp;fbdev,0,sizeofFBDEV;strcpyfbdev.dev,"/dev/fb0";iffb_open&fbdev=FALSEprintf"open frame buffer errorn";return;fb_memsetfbdev.fb_mem+fbdev.fb_mem_offset,0,fbdev.fb_fix.smem_len;fb_close&fbdev;二基于Linux核心的汉字显示的尝试我们以一个简单的例子来说明字符显示的过程。我们假设是在虚拟终端1/dev/tty1下运行一个如下的简单程序。mainputs
43、"hello,world.n";puts函数向缺省输出文件/dev/tty1发出写的系统调用write2。系统调用到linux核心里面对应的核心函数是console.c中的con_write,con_write最终会调用do_con_write。在do_con_write中负责把"hello,world.n"这个字符串放到tty1对应的缓冲区中去。do_con_write还负责处理控制字符和光标的位置。让我们来看一下do_con_write这个函数的声明。static int do_con_writestruct tty_struct*tty,int f
44、rom_user,const unsigned char*buf,int count其中tty是指向tty_struct构造的指针,这个构造里面存放着关于这个tty的所有信息请参照linux/include/linux/tty.h。Tty_struct构造中定义了通用或高层tty的属性例如宽度和高度等。在do_con_write函数中用到了tty_struct构造中的driver_data变量。driver_data是一个vt_struct指针。在vt_struct构造中包含这个tty的序列号我们正使用tty1,所以这个序号为1。Vt_struct构造中有一个vc构造的数组vc_cons,这个
45、数组就是各虚拟终端的私有数据。static int do_con_writestruct tty_struct*tty,int from_user,const unsigned char*buf,int countstruct vt_struct*vt=struct vt_struct*tty-driver_data;/我们用到了driver_data变量.currcons=vt-vc_num;file:/我们在这里的vc_nums就是1.要访问虚拟终端的私有数据,需使用vc_conscurrcons.d指针。这个指针指向的构造含有当前虚拟终端上光标的位置、缓冲区的起始地址、缓冲区大小等等。&
46、quot;hello,world.n"中的每一个字符都要经过conv_uni_to_pc这个函数转换成8位的显示字符。这要做的主要目的是使不同语言的国家能把16位的UniCode码映射到8位的显示字符集上,目前还是主要针对欧洲国家的语言,映射结果为8位,不包含对双字节double byte的范围。这种UNICODE到显示字符的映射关系可以由用户自行定义。在缺省的映射表上,会把中文的字符映射到其他的字符上,这是我们不希望看到也是不需要的。所以我们有两个选择1不进展conv_uni_to_pc的转换。2加载符合双字节处理的映射关系,即对非控制字符进展1对1的不变映射。我们自己定制的符合这
47、种映射关系的UNICODE码表是direct.uni。要想查看/装载当前系统的unicode映射表,可使外部命令loadunimap。经过conv_uni_to_pc转换之后,"hello,world.n"中的字符被一个一个地填写到tty1的缓冲区中。然后do_con_write调用下层的驱动,把缓冲区中的内容输出到显示器上也就相当于把缓冲区的内容拷贝到VGA显存中去。sw-con_putcsvc_conscurrcons.d,u16*draw_from,u16*draw_to-u16*draw_from,y,draw_x;之所以要调用底层驱动,是因为存在不同的显示设备,其
48、对应VGA显存的存取方式也不一样。上面的Sw-con_putcs就会调用到fbcon.c中的fbcon_putcs函数con_putcs是一个函数的指针,在Framebuffer形式下指向fbcon_putcs函数。也就是说在do_con_write函数中是直接调用了fbcon_putcs函数来进展字符的绘制。比方说在256色形式下,真正负责输出的函数是void fbcon_cfb8_putcsstruct vc_data*conp,struct display*p,const unsigned short*s,int count,int yy,int xx显示中文比方说我们试图输出一句中文p
49、utcs你好n;你好的内码为0xc4,0xe3,0xba,0xc3。这时候会怎么样呢,有一点可以肯定,"你好"肯定不会出如今屏幕上,国为核心中没有汉字字库,中文显示就是无米之炊了.1在负责字符显示的void fbcon_cfb8_putcs函数中,原有操作如下对于每个要显示的字符,依次从虚拟终端缓冲区中以WORD为单位读取低位字节是ASCII码,高8位是字符的属性,由于汉字是双字节编码方式,所以这种操作是不可能显示出汉字的,只能显示出xxxx_putcs是一个一个VGA字符.要解决的问题确保在do_con_write时unipc转换不会改变原有编码。一个很直接的实现方式就是
50、加载一个我们自己定制的UNICODE映射表,loadunimapdirect.uni,或者直接把direct.uni置为核心的缺省映射表。针对如上问题,我们要做的第一个尝试方案是如下。首先需要在核心中加载汉字字库,然后修改fbcon_cfb8_putcs函数,在fbcon_cfb8_putcs中一次读两个WORD,检查这两个WORD的低位字节是否能拼成一个汉字,假设发现能拼成一个汉字,就算出这个汉字在汉字字库中的偏移,然后把它当成一个16 x16的VGA字符来显示。试验的结果说明1可以输出汉字,但仍有许多不理想的地方,比方说,输出以半个汉字开场的一串汉字,那么这半个汉字后面的汉字都会是乱码。这是半个汉字的问题。2光标挪动会破坏汉字的显示。表现为,光标挪动过的汉
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 采购管理师知识考核的试题及答案
- 地区性图书管理员考试试题及答案
- 2024年育婴师考试综述试题及答案
- 2024年预算员职业灵感试题及答案
- 2025-2030中国高纯SiCl4行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国高端葡萄酒行业市场现状供需分析及投资评估规划分析研究报告
- 包装技术在物流中的重要性试题及答案
- 2025-2030中国高温超导电缆行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国高合金粉行业发展状况与前景方向分析研究报告
- 马工学中的跨部门协作策略试题及答案
- 2025年各地低空经济政策汇编
- 希沃白板5考题及答案
- 邢台2025年河北邢台市高层次人才引进1025人笔试历年参考题库附带答案详解
- 第三单元 圆柱与圆锥 单元测试(含答案)2024-2025学年六年级下册数学人教版
- XX乡镇履职事项清单表(1356项)
- 2021年同等学力申硕《临床医学》试题真题及答案
- 地铁保安服务投标方案(技术方案)
- 《企业研发费用税前加计扣除政策解读与应用课件》
- 2025年湖北国土资源职业学院单招职业技能测试题库及答案一套
- 七年级数学下册 第8章 单元测试卷(苏科版 2025年春)
- 2024年煤矿安全管理人员考试试题库(含答案)
评论
0/150
提交评论