进程同步与互斥

上传人:仙*** 文档编号:174548982 上传时间:2022-12-15 格式:PPT 页数:31 大小:216.52KB
收藏 版权申诉 举报 下载
进程同步与互斥_第1页
第1页 / 共31页
进程同步与互斥_第2页
第2页 / 共31页
进程同步与互斥_第3页
第3页 / 共31页
资源描述:

《进程同步与互斥》由会员分享,可在线阅读,更多相关《进程同步与互斥(31页珍藏版)》请在装配图网上搜索。

1、进程同步与互斥进程同步与互斥2022-12-152Linux提供下列提供下列3个有关信号量的系统调用函数:个有关信号量的系统调用函数:semget()semop()semctl()下面分别予以介绍。下面分别予以介绍。2022-12-1531.创建一个新的信号量集或获取一个已经存在的信号量集创建一个新的信号量集或获取一个已经存在的信号量集命令格式:命令格式:int semget(key_t key,int nsems,int semflg);返回值:返回值:正确返回:信号量集的标识符正确返回:信号量集的标识符错误返回:错误返回:-12022-12-1541.创建一个新的信号量集或获取一个已经存在

2、的信号量集创建一个新的信号量集或获取一个已经存在的信号量集参数说明:参数说明:key信号量集的信号量集的key值:值:使用使用IPC_PRIVATE,由系统产生,由系统产生key值并返回标识符,或者返回值并返回标识符,或者返回key值已存在的值已存在的信号量集的标识符。信号量集的标识符。key值不为值不为IPC_PRIVATE而是由用户指定一个非而是由用户指定一个非0整型数值,则对信号量集的打整型数值,则对信号量集的打开或存取操作依赖于开或存取操作依赖于semflag参数的取值。参数的取值。nsems指定打开或者新创建的信号量集将包含的信号量的数目;如果该指定打开或者新创建的信号量集将包含的信

3、号量的数目;如果该key值的值的信号量集已存在,而信号量集已存在,而semflg只指定了只指定了IPC_CREAT标志,那么参数标志,那么参数nsems必须与必须与原来的值一致,否则也会返回错误信息。该参数最大值在原来的值一致,否则也会返回错误信息。该参数最大值在linux/sem.h中被定义:中被定义:#define SEMMSL 250 /*=8 000*/semflg当当key值不为值不为IPC_PRIVATE:若只设置若只设置semflag的的IPC_CREAT位,则创建一个信号量集,如果该信号量集已位,则创建一个信号量集,如果该信号量集已经存在,则返回其标识符经存在,则返回其标识符若

4、设置若设置semflag的的IPC_CREAT|IPC_EXCL位,则创建一个新的信号量集,如果位,则创建一个新的信号量集,如果该该key值的信号量集已经存在则返回错误信息值的信号量集已经存在则返回错误信息只设置只设置IPC_EXCL位而不设置位而不设置IPC_CREAT位没有任何意义位没有任何意义。2022-12-1551.创建一个新的信号量集或获取一个已经存在的信号量集创建一个新的信号量集或获取一个已经存在的信号量集实验中,使用该调用创建一个只含一个信号量的信号量集,格式为:semid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);其中的IPC_PRIVATE可

5、以使用具体的整型数值取代。2022-12-1562.对信号量的对信号量的P、V操作操作命令格式:命令格式:int semop(int semid,struct sembuf*sops,unsigned nsops);返回值:返回值:正确返回:正确返回:0错误返回:错误返回:-1参数说明:参数说明:semid信号量集的标识符,由信号量集的标识符,由semget()得到。()得到。sops指向一个指向一个sembuf结构数组,该数组的每个元素对应一次信结构数组,该数组的每个元素对应一次信号量操作。号量操作。2022-12-1572.对信号量的对信号量的P、V操作操作其其sembuf数据结构如下:数

6、据结构如下:struct sembuf unsigned short sem_num;/*semaphore index in array*/shortsem_op;/*semaphore operation*/shortsem_flg;/*operation flags*/;其其中的参数含义如下所示:中的参数含义如下所示:2022-12-1582.对信号量的对信号量的P、V操作操作信号量的信号量的sem_num值标明它是信号量集的第几个元素,第一个信号量为值标明它是信号量集的第几个元素,第一个信号量为0,第二个,第二个为为1,依次类推。,依次类推。semop确定对确定对sem_num指定的信

7、号量采取何种操作,它可以为负数、正数和零。指定的信号量采取何种操作,它可以为负数、正数和零。如果如果sem_op为负数:则相当于为负数:则相当于P操作操作,从信号量的值中减去,从信号量的值中减去sem_op的绝对值:的绝对值:其差如果大于其差如果大于0,则表示该进程可以使用临界资源进入临界区;,则表示该进程可以使用临界资源进入临界区;其差如果小于其差如果小于0,在没有指定,在没有指定IPC_NOWAIT的情况下,该进程睡眠,并插入的情况下,该进程睡眠,并插入sem_queues等待队列尾部,直到请求的条件得到满足;如果指定了等待队列尾部,直到请求的条件得到满足;如果指定了IPC_NOWAIT,

8、则出错返回。则出错返回。如果如果sem_op为正数:此时相当于为正数:此时相当于V操作操作,把它的值加到信号量中,这也意味着该,把它的值加到信号量中,这也意味着该进程释放资源。如果是互斥则出临界区,释放临界资源。进程释放资源。如果是互斥则出临界区,释放临界资源。如果如果sem_op为为0:则该进程将睡眠直到信号量的值也为:则该进程将睡眠直到信号量的值也为0。系统会按顺序检查信号量等待队列系统会按顺序检查信号量等待队列(sem_pending)中的每一个成员,查看在当前信号量中的每一个成员,查看在当前信号量的状态下,其请求的操作是否可以成功,如果可以,则将它从等待队列中唤醒,并的状态下,其请求的

9、操作是否可以成功,如果可以,则将它从等待队列中唤醒,并插入到就绪队列中等待调度运行。插入到就绪队列中等待调度运行。sem_flg指明操作的执行模式,它有两个标志位:指明操作的执行模式,它有两个标志位:IPC_NOWAIT:指明以非阻塞方:指明以非阻塞方式操作信号量。式操作信号量。SEM_UNDO:指明内核为信号量操作保留恢复值指明内核为信号量操作保留恢复值nsops是第二个参数所指向的是第二个参数所指向的sembuf结构数组中元素的个数,结构数组中元素的个数,如果只有一个信号如果只有一个信号量量nsops值值为为1。2022-12-1592.对信号量的对信号量的P、V操作操作在实验中,使用该系

10、统调用实现在实验中,使用该系统调用实现P、V操作,使用格式为:操作,使用格式为:struct sembuf P,V;semop(semid,&P,1);/对信号量对信号量semid执行执行P操作操作semop(semid,&V,1);/对信号量对信号量semid执行执行V操作操作2022-12-15103信号量集的控制函数信号量集的控制函数命令格式:命令格式:int semctl(int semid,int semnum,int cmd,union semun arg);返回值:返回值:操作成功返回:操作成功返回:根据根据cmd的不同返回需要的值或的不同返回需要的值或0 错误返回:错误返回:-

11、12022-12-15113信号量集的控制函数信号量集的控制函数参数说明:参数说明:semid信号量集的标识符,由信号量集的标识符,由semget()得到;()得到;semnum指定指定semid信号量集的第几个信号量,信号量集的第几个信号量,在在撤消撤消信号量集时,此参数可以缺省信号量集时,此参数可以缺省;cmd用于指定操作类别:用于指定操作类别:SETVAL:置信号量:置信号量semval域值为域值为arg.val。IPC_RMID:删除指定信号量集。能够进行此项操作的:删除指定信号量集。能够进行此项操作的进程限于超级用户、进程限于超级用户、sem_perm.cuid或或sem_perm.

12、uid。2022-12-15123信号量集的控制函数信号量集的控制函数实验中使用该系统调用实现以下功能:实验中使用该系统调用实现以下功能:为信号量赋初值,格式为:为信号量赋初值,格式为:union semun arg;arg.val=初值初值;semctl(semid,0,SETVAL,arg);其中其中0表示第表示第0个信号量,个信号量,arg的值由的值由arg.val决定,所以必须事先为决定,所以必须事先为arg.val赋值。赋值。撤消信号量集,格式为:撤消信号量集,格式为:semctl(semid,IPC_RMID,0);上述系统调用使用下列上述系统调用使用下列头函数:头函数:#incl

13、ude#include2022-12-1513信号量及其信号量及其P、V操作的实现操作的实现信号量及其信号量及其P、V操作的实现方式归纳如下:操作的实现方式归纳如下:1 定义信号量标识符:定义信号量标识符:int semid;如果有如果有n个信号量,则需要分别定义个信号量,则需要分别定义n个不同的信号量标识符。个不同的信号量标识符。2 定义信号量数据结构定义信号量数据结构定义定义P、V操作所用的数据结构:操作所用的数据结构:struct sembuf P,V;定义给信号量赋初值的参数数据结构:定义给信号量赋初值的参数数据结构:union semun arg;3 申请只有一个信号量的信号量集申请

14、只有一个信号量的信号量集semid=semget(IPC_PRIVITE,1,IPC_0666);其中,第一个参数:其中,第一个参数:IPC_PRIVATE由系统产生由系统产生key值,也可以由用户使用值,也可以由用户使用具体的整型数值作为具体的整型数值作为key值指定;第二个参数表示信号量集中只有一个值指定;第二个参数表示信号量集中只有一个信号量;操作权限取决于最后一个参数,信号量;操作权限取决于最后一个参数,0666表示任意用户可读可写,表示任意用户可读可写,只设置只设置semflag的的IPC_CREAT位,则创建一个信号量集,如果该信号量位,则创建一个信号量集,如果该信号量集已经存在,

15、则返回其标识符。集已经存在,则返回其标识符。4 分别对每个信号量分别对每个信号量semid赋初值赋初值arg.val=初值初值;semctl(semid,0,SETVAL,arg);2022-12-1514信号量及其信号量及其P、V操作的实现操作的实现5.定义信号量的定义信号量的P操作(供所有信号量的操作(供所有信号量的P操作使用)操作使用)P.sem_num=0;P.sem_op=-1;/*-1表示表示P操作时对信号量减操作时对信号量减1*/P.sem_flg=SEM_UNDO;6.定义信号量的定义信号量的V操作(供所有信号量的操作(供所有信号量的V操作使用)操作使用)V.sem_num=0

16、;V.sem_op=1;/*1表示表示V操作时对信号量加操作时对信号量加1*/V.sem_flg=SEM_UNDO;7.对信号量对信号量semid执行执行P操作:操作:semop(semid,&P,1);8.对信号量对信号量semid执行执行V操作:操作:semop(semid,&V,1);9.撤消信号量:撤消信号量:semctl(semid,IPC_RMID,0);因为信号量不是普通变量,对它赋初值只能通过系统调用函数因为信号量不是普通变量,对它赋初值只能通过系统调用函数semctl(semid,0,SETVAL,arg)进行进行,其值的修改只能通过其值的修改只能通过P、V操作,而不能操作,

17、而不能使用普通的赋值语句。使用普通的赋值语句。因此其初值和信号量的因此其初值和信号量的P、V操作需要事先定义好以后,然后才能在进程中执行操作需要事先定义好以后,然后才能在进程中执行P、V操作。操作。2022-12-1515 应用举例应用举例1.利用信号量实现进程互斥利用信号量实现进程互斥例例4-9 设有父子设有父子2个进程共享一个临界资源,每个进程循环进入该临界个进程共享一个临界资源,每个进程循环进入该临界区区3次:父进程每次进入临界区后显示次:父进程每次进入临界区后显示“prnt in”,出临界区则显示,出临界区则显示“prnt out”;子进程每次进入临界区后显示;子进程每次进入临界区后显

18、示“chld in”出临界区则显出临界区则显示示“chld out”。观察运行结果,应该是一个进程出来后另一个才能。观察运行结果,应该是一个进程出来后另一个才能进去。进去。分析:分析:对临界区设置互斥信号量对临界区设置互斥信号量mutex,其内部标识为,其内部标识为mutexid,初值为,初值为1。程序中使用睡眠延时程序中使用睡眠延时1秒来模拟进入临界区前和进入后所执行的程序。秒来模拟进入临界区前和进入后所执行的程序。2022-12-1516程序清单:文件名程序清单:文件名sem.c#include#include#include#include#includeint mutexid;/定义信

19、号量标识定义信号量标识int main()int chld,i,j;/*定义数据结构定义数据结构*/struct sembuf P,V;union semun arg;/*创建只含有一个互斥信号量元素的信号量集创建只含有一个互斥信号量元素的信号量集*/mutexid=semget(IPC_PRIVATE,1,0666|IPC_CREAT);/*为信号量赋初值为信号量赋初值*/arg.val=1;if(semctl(mutexid,0,SETVAL,arg)=-1)perror(semctl setval error);2022-12-1517 /*定义定义P、V操作操作*/P.sem_num=

20、0;P.sem_op=-1;P.sem_flg=SEM_UNDO;V.sem_num=0;V.sem_op=1;V.sem_flg=SEM_UNDO;while(chld=fork()=-1);/创建子进程创建子进程if(chld0)/父进程返回父进程返回i=1;while(i=3)/循环循环3次次sleep(1);semop(mutexid,&P,1);/进入临界区前执行进入临界区前执行P操作操作printf(prnt inn);sleep(1);printf(prnt outn);semop(mutexid,&V,1);/出临界区执行出临界区执行V操作操作i+;wait(0);/等待子进程

21、终止等待子进程终止semctl(mutexid,IPC_RMID,0);/撤消信号量撤消信号量exit(0);2022-12-1518else/子进程返回子进程返回j=1;while(j=3)/循环循环3次次sleep(1);semop(mutexid,&P,1);/进入临界区前执行进入临界区前执行P操作操作printf(chld inn);sleep(1);printf(chld outn);semop(mutexid,&V,1);/出临界区执行出临界区执行V操作操作j+;exit(0);/子进程终止子进程终止2022-12-1519编译连接及运行结果:编译连接及运行结果:2022-12-1

22、520利用信号量实现进程同步利用信号量实现进程同步例例4-10 父进程创建一个子进程,父子进程共享一个存储区,子进程向共享存储父进程创建一个子进程,父子进程共享一个存储区,子进程向共享存储区中以覆盖方式写信息,父进程从该共享存储区中读信息并显示信息。父子区中以覆盖方式写信息,父进程从该共享存储区中读信息并显示信息。父子进程轮流读写,即子进程写一个信息到共享内存中,父进程从中读该信息输进程轮流读写,即子进程写一个信息到共享内存中,父进程从中读该信息输出;然后子进程再写第出;然后子进程再写第2个信息,父进程再读出第个信息,父进程再读出第2个信息输出,如图个信息输出,如图4 6所所示。当信息为示。当

23、信息为“end”时读写进程结束。时读写进程结束。父进程父进程子进程子进程单缓冲区单缓冲区图图4 6 单缓冲区同步问题单缓冲区同步问题2022-12-1521利用信号量实现进程同步利用信号量实现进程同步同步分析:同步分析:这是一个单缓冲区同步问题,在第这是一个单缓冲区同步问题,在第3章中已经讨论过这类问题的同步算章中已经讨论过这类问题的同步算法,读写缓冲区的两个进程之间只需要同步不需要互斥,请参阅法,读写缓冲区的两个进程之间只需要同步不需要互斥,请参阅3.3.6节中的节中的单缓冲区同步问题单缓冲区同步问题。同步算法:同步算法:子进程执行条件为单缓冲区有空,设信号量子进程执行条件为单缓冲区有空,设

24、信号量empty,初值为,初值为1;父进程执行条件为单缓冲区有数,设信号量父进程执行条件为单缓冲区有数,设信号量full,初值为,初值为0;上述信号量可以由父进程定义、申请、初始化,然后由父子进程共享使上述信号量可以由父进程定义、申请、初始化,然后由父子进程共享使用,子进程结束后由父进程撤消。用,子进程结束后由父进程撤消。共享内存设计:共享内存设计:父子进程共享一个内存区,可以由父进程申请、附接,然后由父子进程父子进程共享一个内存区,可以由父进程申请、附接,然后由父子进程共享使用,子进程结束后由父进程撤消。共享使用,子进程结束后由父进程撤消。2022-12-1522程序清单,文件名为程序清单,

25、文件名为sem2.c:#include#include#include#include#include#include#include/*定义信号量内部标识定义信号量内部标识*/int emptyid;int fullid;main()int chld,i,j;/*定义信号量数据结构定义信号量数据结构*/struct sembuf P,V;union semun arg;/*定义共享内存定义共享内存*/int shmid;char*viraddr;char bufferBUFSIZ;2022-12-1523 /*创建信号量并初始化创建信号量并初始化*/emptyid=semget(IPC_PR

26、IVATE,1,IPC_CREAT|0666);fullid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);arg.val=1;if(semctl(emptyid,0,SETVAL,arg)=-1)perror(semctl setval error);arg.val=0;if(semctl(fullid,0,SETVAL,arg)=-1)perror(semctl setval error);/*定义定义P、V操作操作*/P.sem_num=0;P.sem_op=-1;P.sem_flg=SEM_UNDO;V.sem_num=0;V.sem_op=1;V.sem_

27、flg=SEM_UNDO;/*创建并附接共享内存创建并附接共享内存*/shmid=shmget(IPC_PRIVATE,BUFSIZ,0666|IPC_CREAT);viraddr=(char*)shmat(shmid,0,0);2022-12-1524while(chld=fork()=-1);/创建子进程创建子进程if(chld0)/父进程返回读信息并输出父进程返回读信息并输出 while(1)semop(fullid,&P,1);/对对fullid执行执行P操作操作printf(Your message is:n%s,viraddr);semop(emptyid,&V,1);/对对emp

28、tyid执行执行V操作操作if(strncmp(viraddr,end,3)=0)break;wait(0);/等待子进程终止等待子进程终止shmdt(viraddr);/断开附接的共享内存断开附接的共享内存shmctl(shmid,IPC_RMID,0);/撤消共享内存和信号量集撤消共享内存和信号量集semctl(emptyid,IPC_RMID,0);semctl(fullid,IPC_RMID,0);printf(Parent ok!n);exit(0);2022-12-1525else/子进程返回写信息到共享内存子进程返回写信息到共享内存while(1)semop(emptyid,&P

29、,1);/对对emptyid执行执行P操作操作puts(Enter your text:);fgets(buffer,BUFSIZ,stdin);/键盘输入信息键盘输入信息strcpy(viraddr,buffer);/写信息到共享内存中(覆盖方式)写信息到共享内存中(覆盖方式)semop(fullid,&V,1);/对对fullid执行执行V操作操作if(strncmp(viraddr,end,3)=0)sleep(1);/睡眠睡眠1秒,等待父进程将秒,等待父进程将end取走取走break;printf(Child ok!n);exit(0);2022-12-1526运行结果:运行结果:由结

30、果可以看出,子进程写到单缓冲区中的信息,父进程都依次取出由结果可以看出,子进程写到单缓冲区中的信息,父进程都依次取出并输出了。并输出了。2022-12-1527利用信号量实现进程同步利用信号量实现进程同步例例4-11 设父进程创建一个子进程作为生产者,创建两个子进程作为消设父进程创建一个子进程作为生产者,创建两个子进程作为消费者,这三个子进程使用一个共享内存,该共享内存定义为具有费者,这三个子进程使用一个共享内存,该共享内存定义为具有5个个变量的数组,每个变量表示一个缓冲区,缓冲区号为变量的数组,每个变量表示一个缓冲区,缓冲区号为04。生产者进。生产者进程依次往缓冲区程依次往缓冲区04中写中写

31、10个数据个数据110,两个读进程依次从缓冲区,两个读进程依次从缓冲区04中轮流取出这中轮流取出这10个数据。使用信号量实现进程读写缓冲区的同个数据。使用信号量实现进程读写缓冲区的同步和互斥。步和互斥。生产者消费者同步问题生产者消费者同步问题消费者消费者A进程进程消费者消费者B进程进程生产者进程生产者进程013242022-12-1528利用信号量实现进程同步利用信号量实现进程同步分析:分析:需要创建需要创建3个子进程:生产者、消费者个子进程:生产者、消费者A、消费者、消费者B;需要使用需要使用3个信号量:个信号量:empty、full、mutex,分别表示缓,分别表示缓冲区是否有空、是否有数

32、和互斥信号量,其初值分别为:冲区是否有空、是否有数和互斥信号量,其初值分别为:5,0,1;需要需要2个共享内存:个共享内存:array和和get,分别表示多缓冲区数组,分别表示多缓冲区数组变量变量array 04、和消费者读缓冲区号的计数、和消费者读缓冲区号的计数get,get计数由两个消费者进程共享,由于生产者只有一个没,所计数由两个消费者进程共享,由于生产者只有一个没,所以写缓冲区号的计数以写缓冲区号的计数set不需要使用共享内存。不需要使用共享内存。2022-12-1529算法:算法:创建共享存储区创建共享存储区array,get;附接共享存储区到进程空间;附接共享存储区到进程空间;共享

33、存储区赋初值;共享存储区赋初值;创建信号量创建信号量empty并初始化;并初始化;创建信号量创建信号量full并初始化;并初始化;创建信号量创建信号量mutex并初始化;并初始化;创建生产者子进程;创建生产者子进程;如果生产者子进程返回:如果生产者子进程返回:for(i=0;i10,i+)P(empty);P(mutex););写数据到共享存储区;写数据到共享存储区;缓冲区计数缓冲区计数set+;V(mutex););V(full);exit(0);如果父进程返回:如果父进程返回:创建消费者创建消费者A子进程;子进程;如果消费者如果消费者A进程返回:进程返回:for(i=0;i10,i+)P(

34、full);P(mutex););从共享存储区中取数据;从共享存储区中取数据;缓冲区计数缓冲区计数(*get)+;V(mutex););V(empty);exit(0);如果父进程返回:如果父进程返回:创建消费者创建消费者B子进程;子进程;如果消费者如果消费者B进程返回:进程返回:2022-12-1530算法:算法:for(i=0;i10,i+)P(full);P(mutex););从共享存储区中取数据;从共享存储区中取数据;缓冲区计数缓冲区计数(*get)+;V(mutex););V(empty);exit(0);程序清单:程序清单:semshm.doc如果父进程返回:如果父进程返回:wai

35、t(0);wait(0);wait(0);断开断开2个共享存储区;个共享存储区;撤消撤消2个共享存储区;个共享存储区;撤消撤消3个信号量;个信号量;exit(0);2022-12-1531编译连接并执行后的输出结果如下:编译连接并执行后的输出结果如下:由运行结果可以看出,生产者进程分别往缓冲区由运行结果可以看出,生产者进程分别往缓冲区04中送了中送了10次产品,次产品,消费者进程消费者进程A和和B轮流从缓冲区轮流从缓冲区04中取走产品,并实现了中取走产品,并实现了3个进程之个进程之间的同步和互斥,即实现了生产者进程送了产品后消费者进程才取走间的同步和互斥,即实现了生产者进程送了产品后消费者进程才取走产品,并且一次只有一个进程进入缓冲区。产品,并且一次只有一个进程进入缓冲区。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


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