嵌入式Linux应用程序开发(精品).ppt

上传人:hyn****60 文档编号:70941435 上传时间:2023-01-29 格式:PPT 页数:103 大小:1.54MB
返回 下载 相关 举报
嵌入式Linux应用程序开发(精品).ppt_第1页
第1页 / 共103页
嵌入式Linux应用程序开发(精品).ppt_第2页
第2页 / 共103页
点击查看更多>>
资源描述

《嵌入式Linux应用程序开发(精品).ppt》由会员分享,可在线阅读,更多相关《嵌入式Linux应用程序开发(精品).ppt(103页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、1嵌入式嵌入式Linux应用程序开发应用程序开发主讲人:方攀主讲人:方攀Email:Blog:2Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.嵌入式Linux应用程序开发嵌入式Linux应用程序开发及交叉编译:HelloWorld!嵌入式Linux内核模块开发:HelloModule!Linux环境下多进程及多线程编程3Copyright 2007 Prochip Electronics C

2、o,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.1.1Linux应用程序介绍在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是灵活运用C编译器.目前Linux下最常用的C语言编译器是GCC(GNUCompilerCollection),它是GNU项目中符合ANSIC标准的编译系统,能够编译用C、C+和ObjectC等语言编写的程序.GCC不仅功能非常强大,结构也异常灵活.最值得称道的一点就是它可以通过不同

3、的前端模块来支持各种语言,如Java、Fortran、Pascal、Modula-3和Ada等.开放自由和灵活是Linux的魅力所在,而这一点在GCC上的体现就是程序员通过它能够更好地控制整个编译过程.在使用GCC编译程序时,编译过程可以被细分为四个阶段:预处理(Pre-Processing)编译(Compiling)汇编(Assembling)链接(Linking)Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备.和其它常用的编译器一样,GCC

4、也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码GCC提供了30多条警告信息和三个警告级别,使用它们有助于增强程序的稳定性和可移植性此外,GCC还对标准的C和C+语言进行了大量的扩展,提高程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量.4Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.1.1应用程序起步编写源文件在/root/下建一个自己的目录#mkdirpr

5、oject#cdproject#vimhelloworld.c#includeintmain(void)printf(Welovearm,welovesep4020!n);return1;5Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.代码注意问题代码注意问题main函数的返回值应该是int类型;main函数在终止前没有调用“return1;”语句来结尾。6Copyright 2007 Pr

6、ochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.1.2编译helloworld.c(1)在pc机上编译能在pc机上运行的应用程序的方法#gcc-ohelloworld_pchelloworld.c(这个是用i386的gcc编译器编译的,所以只能在pc机的linux环境中运行)(2)在pc机上编译能在sep4020板子上运行的应用程序的方法#arm-linux-gcc-ohelloworld_armhelloworld.c(这个

7、是用arm的交叉gcc编译器编译的,所以可以下载到板子上运行)7Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.1.3运行helloworld程序(1)在pc机上运行i386的程序rootlocalhostcode#./helloworld_pcWelovearm,welovesep4020!(2)在开发板上运行应用程序将应用程序helloworld_arm拷贝到/nfs/demo文件夹下ro

8、otlocalhostcode#cphelloworld_arm/nfs/demo/#cddemo/demo#./helloworld_armWelovearm,welovesep4020!8Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.2.1编写HelloModule源代码前面我们介绍了一个简单的Linux程序HelloWorld,它是运行于用户态的应用程序,现在我们再介绍一个运行于内核态

9、的HelloModule程序,它其实是一个最简单的驱动程序模块。我们将HelloModule的源代码放置于/root/project/module目录,名称为hellomodule.c,内容如下:9Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.#include#includeMODULE_LICENSE(GPL);staticint_initsep4020_hello_module_init

10、(void)printk(Hello,sep4020moduleisinstalled!n);return0;staticvoid_exitsep4020_hello_module_cleanup(void)printk(Good-bye,sep4020modulewasremoved!n);module_init(sep4020_hello_module_init);module_exit(sep4020_hello_module_cleanup);10Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to b

11、e reproduced by any means without prior written consent.2.2编译HelloModule源代码由于这个模块是加到嵌入式linux的内核中的,所以它肯定会用到许多嵌入式linux源码的头文件的,我们的嵌入式linux的内核源码位置在/linux-3.2/下面,这中间的链接过程非常复杂,为了不让我们手动输入编译指令,一般编译2.6版本的驱动模块需要把驱动代码加入内核代码树,并做相应的配置,如下步骤Step1:把刚才的源码文件拷贝到/linux-3.2/drivers/char/sep4020_char目录下Step2:编辑配置/linux-3

12、.2/drivers/char/sep4020_char的Kconfig文件,加入驱动选项(注意tristate前面有tab键)configSEP4020_HELLOMODULEtristatesep4020hellomoduledriver使之在makemenuconfig的时候出现;11Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.12Copyright 2007 Prochip Ele

13、ctronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.Step3:修改Makefile文件,在其中加入:obj-$(CONFIG_SEP4020_HELLOMODULE)+=hellomodule.oStep4:这时回到/linux-3.2源代码根目录位置,执行makemodules13Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced

14、by any means without prior written consent.2.3把HelloModule下载到开发板并安装使用 14Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.3 Linux进程程编程程3.1Linux进程的概念3.2Linux下的进程启动3.3进程控制编程3.4守护进程编程3.5进程间通信15Copyright 2007 Prochip Electronics

15、 Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.3.1Linux进程的概念(1)进程是一个独立的可调度的活动;(2)进程是一个抽象实体,当它执行某个任务时,将要分配和释放各种资源(P.Denning);(3)进程是可以并行执行的计算部分。以上进程的概念都不相同,但其本质是一样的。它指出了进程是一个程序的一次执行的过程。它和程序是有本质区别的,程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念;而进程是一个动态的概念,它是程序执行的过程,包括

16、了动态创建、调度和消亡的整个过程。它是程序执行和资源管理的最小单位。16Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.进程控制块进程控制块(1)进程是Linux系统的基本调度单位,那么从系统的角度看如何描述并表示它的变化呢?进程标识符:当一个进程产生时,系统都会为它分配一个标识符;进程所占的内存区域:每个进程执行时都需要占用一定的内存区域,此区域用于保存该进程所运行的程序代码和使用的程序变量

17、。每一个进程所占用的内存是相互独立的,因此改变一个进程所占内存中数据的任何改动,都只对该进程产生影响,不会影响到其它进程的顺利执行;文件描述符:当一个进程在执行时,它需要使用一些相关的文件描述符。文件描述符描述了被打开文件的信息,不同的进程打开同一个文件时,所使用的文件描述符是不同的。一个进程文件描述符的改变并不会对其它的进程打开同一个文件的描述符产生任何影响;17Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior writte

18、n consent.进程控制块进程控制块(2)安全信息:一个进程的安全信息包括用户识别号和组识别号;进程环境:一个进程的运行环境包括环境变量和启动该进程的程序调用的命令行;信号处理:一个进程有时需要用信号同其它进程进行通信。进程可以发送和接收信号,并对其作出相应处理;资源安排:进程是调度系统资源的基本单位。当多个进程同时运行时,linux系统内核安排不同进程轮流使用系统的各种资源;18Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without pr

19、ior written consent.进程控制块进程控制块(3)同步处理:多个程序之间同步运行的实现,也是通过进程来完成的。这将会使用到诸如共享内存、文件锁定等方法。进程状态:在一个进程存在期间,每一时刻进程都处在一定的状态,包括运行、等待被调度或睡眠状态。19Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.进程结构体描述进程结构体描述20Copyright 2007 Prochip Ele

20、ctronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.进程的标识进程的标识进程的标识:进程号、父进程号、父进程组号、会话号、会话首领号都是用于从不同的侧面来描述进程的身份测试进程号的代码:/*process.c*/#include#include#includeintmain()/*获得当前进程的进程ID和其父进程ID*/printf(ThePIDofthisprocessis%dn,getpid();printf(ThePPIDofthisproc

21、essis%dn,getppid();return1;21Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.进程状态进程状态一个进程在其生存期内,可处于一组不同的状态下,称为进程状态运行状态(TASK_RUNNING)当进程正在被CPU执行,或已经准备就绪随时可由调度程序执行,则称该进程为处于运行状态(running)。进程可以在内核态运行,也可以在用户态运行;可中断睡眠状态(TASK_INTE

22、RRUPTIBLE)当进程处于可中断等待状态时,系统不会调度该进行执行。当系统产生一个中断或者释放了进程正在等待的资源,或者进程收到一个信号,都可以唤醒进程转换到就绪状态(运行状态);22Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.不可中断睡眠状态(TASK_UNINTERRUPTIBLE)与可中断睡眠状态类似。但处于该状态的进程只有被使用wake_up()函数明确唤醒时才能转换到可运行的

23、就绪状态。暂停状态(TASK_STOPPED)当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可运行状态。僵死状态(TASK_ZOMBIE)当进程已停止运行,但其父进程还没有询问其状态时,则称该进程处于僵死状态。23Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.24Copyright 2007 Proch

24、ip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.Linux下进程的模式和类型下进程的模式和类型在Linux系统中,进程的执行模式划分为用户模式和内核模式。如果当前运行的是用户程序、应用程序或者内核之外的系统程序,那么对应进程就在用户模式下运行;如果在用户程序执行过程中出现系统调用或者发生中断事件,那么就要运行操作系统(即核心)程序,进程模式就变成内核模式。在内核模式下运行的进程可以执行机器的特权指令,而且此时该进程的运行不受用户的干

25、扰,即使是root用户也不能干扰内核模式下进程的运行。用户进程既可以在用户模式下运行,也可以在内核模式下运行,25Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.3.2 Linux下的进程启动下的进程启动 Linux下启动一个进程有两种主要途径:手工启动和调度启动。手动启动是由用户输入命令直接启动进程,而调度启动是指系统根据用户的设置自行启动进程。(1)手工启动,又可分为前台启动和后台启动。前

26、台启动,如“ls-l”;后台启动往往是在该进程非常耗时,且用户也不急着需要结果的时候启动的,如“tftpgrtcpip.rar192.168.0.2&”(2)调度启动,系统需要进行一些比较费时而且占用资源的维护工作,如at和cron26Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.3.3 进程控制编程进程控制编程(1)fork()(2)exec函数族(3)exit和_exit(4)wait和

27、waitpid27Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.(1)fork()()fork函数用于从已存在进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。这两个分别带回它们各自的返回值,其中父进程的返回值是子进程的进程号,而子进程则返回0。因此,可以通过返回值来判定该进程是父进程还是子进程。fork()函数头文件:#include格式:pid_tfork();返回值:0:子进

28、程子进程ID(大于0的整数):父进程1:出错28Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.子进程是父进程的拷贝,它具有和父进程相同的代码段,但是它具有自己的数据段和堆栈段。子进程将从父进程获得绝大部分属性,但也会更改部分属性的值,要更改的属性为:进程ID进程组ID(更改为父进程ID)SESSIONID(为子进程的运行时间记录)所打开文件及文件的偏移量(父进程对文件的锁定)29Copyri

29、ght 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent./*fork.c*/#include#include#include#include int main(void)pid_t result;/*调用调用fork函数,其返回值为函数,其返回值为result*/result=fork();/*通过通过result的值来判断的值来判断fork函数的返回情况,首先进行出错处理函数的返回情况,首先进行出错处理*/if

30、(result=-1)perror(fork);exit;/*返回值为返回值为0代表子进程代表子进程*/else if(result=0)printf(The return value is%dnIn child process!nMy PID is%dn,result,getpid();/*返回值大于返回值大于0代表父进程代表父进程*/else printf(The return value is%dnIn father process!nMy PID is%dn,result,getpid();return 1;30Copyright 2007 Prochip Electronics Co

31、,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.编译源文件编译源文件fork.c并在板子上运行并在板子上运行先在上位机编译源文件:进入/nfs/project目录下rootlocalhostproject#arm-linux-gcc-oforkfork.c将可执行程序下载到目标板上,运行结果如下所示:31Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced

32、 by any means without prior written consent.(2)exec函数族函数族exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新的进程替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行的脚本文件。在Linux中使用exec函数族主要有两种情况:(1)当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用任何exec函数族让自己重生;(2)如果一个进程想执行另一个程序,

33、那么它就可以调用fork函数新建一个进程,然后调用任何一个exec,这样看起来就好像通过执行应用程序而产生了一个新进程。(这种情况非常普遍)32Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.exec函数族有下列函数族有下列6个函数:个函数:#includeintexecl(constchar*path,constchar*arg,.);intexeclp(constchar*file,con

34、stchar*arg,.);intexecle(constchar*path,constchar*arg,char*constenvp);intexecv(constchar*path,char*constargv);intexecvp(constchar*file,char*constargv);intexecve(constchar*path,char*constargv,char*constenvp);33Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any me

35、ans without prior written consent.Execlp实例实例/*execlp.c*/#include#include#includeintmain()if(fork()=0)/*调用execlp函数,这里相当于调用了“ps”命令*/if(execlp(ps,ps,NULL)0)perror(execlperror!);将源码文件execlp.c保存到/nfs/project目录下并交叉编译:rootlocalhostproject#arm-linux-gcc-oexeclpexeclp.c34Copyright 2007 Prochip Electronics Co

36、,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.Execlp运行运行在该程序中,首先使用fork函数新建一个子进程,然后在子进程里使用execlp函数。读者可以看到,这里的参数列表就是在shell中使用的命令名和选项。并且当使用文件名的方式进行查找时,系统会在默认的环境变量PATH中寻找该可执行文件。读者可将编译后的结果下载到目标板上,运行结果如下所示:35Copyright 2007 Prochip Electronics Co,ltd.All Rights Re

37、served.Not to be reproduced by any means without prior written consent.Execle实例/*execle.c*/#include#include#includeintmain()/*命令参数列表,必须以NULL结尾*/char*envp=PATH:=/tmp:$PATH,NULL;if(fork()=0)/*调用execle函数,注意这里也要指出env的完整路径*/if(execle(/usr/bin/env,env,NULL,envp)0)perror(execleerror!);return1;将源码文件execlp.c

38、保存到/nfs/project目录下并交叉编译:rootlocalhostproject#arm-linux-gcc-oexecleexecle.c36Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.Execle运行运行37Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by

39、any means without prior written consent.exec函数族使用注意点函数族使用注意点在使用exec函数族时,一定要加上错误判断语句。因为exec很容易执行失败,其中最常见的原因有:找不到文件或路径,此时errno被设置为ENOENT;数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT;没有对应可执行文件的运行权限,此时errno被设置为EACCES。38Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any m

40、eans without prior written consent.(3)exit和和_exit39Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.终止进程函数终止进程函数形式一:#includevoidexit(intstatus);说明:exit()函数是标准C中提供的函数。它用来终止正在运行的程序,将关闭所有被该文件打开的文件描述符形式二:#includevoid_exit(intst

41、atus)说明:_exit()函数也可用于结束一个进程,与exit函数不同的是,调用_exit()是为了关闭一些linux特有的退出句柄。40Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.终止进程函数终止进程函数形式三:#includeintatexit(void(*function)(void);说明:atexit函数在结束一个程序后,调用一个不带参数同时也没有返回值的函数。该函数名由fu

42、nction指针指向形式四:#includevoidabort(void);说明:abort()函数用来发送一个SIGABRT信号,这个信号将使当前进程终止。形式五:#includevoidassert(intexpression);说明:assert是一个宏。调用assert函数时,首先要计算表达式expression的值,如果为0,则调用abort()函数结束进程。41Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior wr

43、itten consent.Exit实例实例/*exit.c*/#include#include#includeintmain(void)pid_tpid;if(pid=fork()0)exit(0);elseif(pid=0)printf(gointochildprocess!n);printf(childprocessPID:%d,getpid();exit(0);elseprintf(gointoparentprocess!n);printf(ParentprocessPID:%4d,getpid();_exit(0);return0;42Copyright 2007 Prochip E

44、lectronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.Exit运行运行将源码文件execlp.c保存到/nfs/project目录下并交叉编译:rootlocalhostproject#arm-linux-gcc-oexecleexecle.c将板子启动Linux,并挂载网络文件系统,然后进入/project目录下面,运行exit实例:43Copyright 2007 Prochip Electronics Co,ltd.All Rights R

45、eserved.Not to be reproduced by any means without prior written consent.(4)wait和和waitpidwait函数是用于使父进程(也就是调用wait的进程)阻塞,直到一个子进程结束或者该进程接到了一个指定的信号为止。如果该父进程没有子进程或者他的子进程已经结束,则wait就会立即返回。waitpid的作用和wait一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait功能,也能支持作业控制。实际上wait函数只是waitpid函数的一个特例,在Linux内部实现wait函数时直接调用

46、的就是waitpid函数。44Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.wait函数调用形式:#include#includepid_twait(int*status)这里的status是一个整型指针,是该子进程退出时的状态status若为空,则代表任意状态结束的子进程status若不为空,则代表指定状态结束的子进程另外,子进程的结束状态可由Linux中一些特定的宏来测定成功的话返回子进

47、程的进程号,失败则返回-145Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.waitpid函数调用形式:#include#includepid_twaitpid(pid_tpid,int*stat_loc,intoptions);作用:waitpid等待指定的子进程直到子进程返回,如果pid为正值则等待指定的进程(pid);如果为0则等待任何一个组ID和调用者的组ID相同的进程;为-1时等同

48、于wait调用;小于-1时等待任何一个组ID等于pid绝对值的进程。参数含义:stat_loc和wait的意义一样;options可以决定父进程的状态,可以取下面两个值:WNOHANG:当没有子进程存在时,父进程立即返回;WUNTACHED:当子进程结束时waitpid返回,但是子进程的退出状态不可得到.46Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent./*waitpid.c*/#inclu

49、de#include#include#include#includeintmain()pid_tpc,pr;pc=fork();if(pc0)exit(0);(1)创建子进程,父进程退出)创建子进程,父进程退出51Copyright 2007 Prochip Electronics Co,ltd.All Rights Reserved.Not to be reproduced by any means without prior written consent.(2)在子进程中创建新会话在子进程中创建新会话(setsid函数)函数)这个步骤是创建守护进程中最重要的一步进程组:进程组是一个或多个

50、进程的集合。进程组由进程组ID来惟一标识。除了进程号(PID)之外,进程组ID也一个进程的必备属性。每个进程组都有一个组长进程,其组长进程的进程号等于进程组ID。且该进程ID不会因组长进程的退出而受到影响。会话期:会话组是一个或多个进程组的集合。通常,一个会话开始于用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。setsid函数作用setsid函数用于创建一个新的会话,并担任该会话组的组长。调用setsid有下面的3个作用:让进程摆脱原会话的控制。让进程摆脱原进程组的控制。让进程摆脱原控制终端的控制。52Copyright 2007 Prochip Electronic

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 生活常识

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁