程序间通讯方式

程序间通讯方式,第1张

程序通讯方式

用于程序间通讯(IPC)的四种不同技术: 1. 讯息传递(管道,FIFO,posix和system v讯息伫列) 2. 同步(互斥锁,条件变数,读写锁,档案和记录锁,Posix和System V讯号灯) 3. 共享记忆体区(匿名共享记忆体区,有名Posix共享记忆体区,有名System V共享记忆体区) 4. 过程呼叫(Solaris门,Sun RPC) 讯息伫列和过程呼叫往往单独使用,也就是说它们通常提供了自己的同步机制.相反,共享记忆体区通常需要由应用程式提供的某种同步形式才能正常工作.解决某个特定问题应使用哪种IPC不存在简单的判定,应该逐渐熟悉各种IPC形式提供的机制,然后根据特定应用的要求比较它们的特性. 必须考虑的四个前提: 1. 联网的还是非联网的.IPC适用于单台主机上的程序或执行绪间的.如果应用程式有可能分布到多台主机上,那就要考虑使用套接字代替IPC,从而简化以后向联网的应用程式转移的工作. 2. 可移植性. 3. 效能,在具体的开发环境下执行测试程式,比较几种IPC的效能差异. 4. 实时排程.如果需要这一特性,而且所用的系统也支援posix实时排程选项,那就考虑使用Posix的讯息传递和同步函式. 各种IPC之间的一些主要差异: 1. 管道和FIFO是位元组流,没有讯息边界.Posix讯息和System V讯息则有从传送者向接受者维护的记录边界(eg:TCP是没有记录边界的位元组流,UDP则提供具有记录边界的讯息). 2. 当有一个讯息放置到一个空伫列中时,Posix讯息伫列可向一个程序传送一个讯号,或者启动一个新的执行绪.System V则不提供类似的通知形式. 3. 管道和FIFO的资料位元组是先进先出的.Posix讯息和System V讯息具有由传送者赋予的优先顺序.从一个Posix讯息伫列读出时,首先返回的总是优先顺序最高的讯息.从一个System V讯息伫列读出时,读出者可以要求想没核要的任意优先顺序的讯息. 4. 在众多的讯息传递技术—管道,FIFO,Posix讯息伫列和System V讯息伫列—中,可从一个讯号处理程式中呼叫的函式只有read和write(适用于管道和FIFO). 比较不同形式的讯息传递时,我们感兴趣的有两种测量尺度: 1. 频宽(bandwidth):资料通过IPC通道转移的速度.为测量该值,我们从一个程序向另一个程序传送大量资料(几百万位元组).我们还给不同大小的I/O *** 作(例如管道和FIFO的write和read *** 作)测量该值,期待发现频宽随每个I/O *** 作的资料量的增长而增长返蚂的规律. 2. 延迟(latency):一个小的IPC讯息从一个程序到令一个程序再返回来所花的时间.我们测量的是只有一个1个位元组的讯息从一个程序到令一个程序再回来的时间(往返时间) 在现实世界中,频宽告诉我们大块资料通过一个IPC通道传送出去需花多长时间,然而IPC也用于传递小的控制资讯,系统处理这些小讯息所需的时间就由延迟提供.这两个数都很重要.

程序和执行绪的区别,程序间通讯方式有哪

程序间和执行绪间的协作区别:

程序互斥、同步的概念

程序互斥、同步的概念是并发程序下存在的概念,有了并发程序,就产生了资源的竞争与协作,从而就要通过程序的互斥、同步、通讯来解决资源的竞争与协作问题。

下面是根据《作业系统教程》3.1.4 中的介绍,整理的程序互斥、同步的概念。

在多道程式设计系统中,同一时刻可能有许多程序,这些程序之间存在两种基本关系:竞争关系和协作关系。

程序的互斥、同步、通讯都是基于这两种基本关系而存在的,为了解决程序间竞争关系(间接制约关系)而引入程序互斥;为了解决程序间松散的协作关系( 直接制约关系)而引入程序同步;为了解决程序间紧密的协作关系而引入程序通讯。

第一种是竞争关系

系统中的多个程序之间彼此无关,它们并不知道其他程序的存在,并且也不受其他程序执行的影响。例如,批处理系统中建立的多个使用者程序, 分时系统中建立的多个终端程序。由于这些程序共用了一套计算机系统资源,因而, 必然要出现多个程序竞争资源的问题。当多个程序竞争共享硬装置、储存器、处理器 和档案等资源时,作业系统必须协调好程序对资枯世掘源的争用。

资源竞争出现了两个控制问题:一个是死锁 (deadlock )问题,一组程序如果都获得了部分资源,还想要得到其他程序所占有的资源,最终所有的程序将陷入死锁。另一个是饥饿(starvation )问题,这是指这样一种情况:一个程序由于其他程序总是优先于它而被无限期拖延。

作业系统需要保证诸程序能互斥地访问临界资源,既要解决饥饿问题,又要解决死锁问题。

程序的互斥(mutual exclusion )是解决程序间竞争关系( 间接制约关系) 的手段。 程序互斥指若干个程序要使用同一共享资源时,任何时刻最多允许一个程序去使用,其他要使用该资源的程序必须等待,直到占有资源的程序释放该资源。

第二种是协作关系

某些程序为完成同一任务需要分工协作,由于合作的每一个程序都是独立地以不可预知的速度推进,这就需要相互协作的程序在某些协调点上协 调各自的工作。当合作程序中的一个到达协调点后,在尚未得到其伙伴程序发来的讯息或讯号之前应阻塞自己,直到其他合作程序发来协调讯号或讯息后方被唤醒并继续执行。这种协作程序之间相互等待对方讯息或讯号的协调关系称为程序同步。

程序间的协作可以是双方不知道对方名字的间接协作,例如,通过共享访问一个缓冲区进行松散式协作;也可以是双方知道对方名字,直接通过通讯机制进行紧密协作。允许程序协同工作有利于共享资讯、有利于加快计算速度、有利于实现模组化程式设计。

程序的同步(Synchronization)是解决程序间协作关系( 直接制约关系) 的手段。程序同步指两个以上程序基于某个条件来协调它们的活动。一个程序的执行依赖于另一

个协作程序的讯息或讯号,当一个程序没有得到来自于另一个程序的讯息或讯号时则需等待,直到讯息或讯号到达才被唤醒。

不难看出,程序互斥关系是一种特殊的程序同步关系,即逐次使用互斥共享资源,也是对程序使用资源次序上的一种协调。

列举linux程序间通讯方式,linux pthread执行绪同步的方式有哪些

程序间通讯程序间通讯就是不同程序之间传播或交换资讯,程序的使用者空间是互相独立的,程序之间可以利用系统空间交换资讯。 管道(pipe)管道是一种半双工的通讯方式,资料只能单向流动。如果要进行双工通讯,需要建立两个管道。 管道只能在具有亲...

要传输大约1MB的资料,应该用哪种程序间通讯方式最佳

Simpson and Sons

54 Madison Street

Sydney, Australia.

7th November 2008

Dear Person-in-charge,

Re: Amendments of L/C No. 5058

We are writing to amend L/C No. 5058 of 3,000 dozens of Poplin Shirts as follows:

1) The beneficiary pany should be Pacific Trading Co., Ltd as opposed to Oriental Trading Co., Ltd.

2) The credit terms should be cash on delivery instead of 60 days credit terms.

3) The trade term or price term should be CFRC3 Marseilles in instead of CFR Marseilles.

4) The total transaction amount should be USD 300,000.00 and not GBP 300,000.00.

We apologized for any inconvenience caused. Please kindly make the following amendments as soon as possible and do not hesitate to contact me at xxx-xxxx-xxxx should you required further information.

Thank you.

Yours truly,

XXX

程序间同步是程序间通讯吗

管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系程序间的通讯,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系程序间的通讯讯号(Signal):讯号是比较复杂的通讯方式,用于通知接受程序有某种事件发生,除了用于程序间通讯外,程序还可以传送讯号给程序本身linux除了支援Unix早期讯号语义函式sigal外,还支援语义符合Posix.1标准的讯号函式sigaction(实际上,该函式是基于BSD的,BSD为了实现可靠讯号机制,又能够统一对外介面,用sigaction函式重新实现了signal函式)报文(Message)伫列(讯息伫列):讯息伫列是讯息的连结表,包括Posix讯息伫列system V讯息伫列。有足够许可权的程序可以向伫列中新增讯息,被赋予读许可权的程序则可以读走伫列中的讯息。讯息伫列克服了讯号承载资讯量少,管道只能承载无格式位元组流以及缓冲区大小受限等缺点。 共享记忆体:使得多个程序可以访问同一块记忆体空间,是最快的可用IPC形式。是针对其他通讯机制执行效率较低而设计的。往往与其它通讯机制,如讯号量结合使用,来达到程序间的同步及互斥。 讯号量(semaphore):主要作为程序间以及同一程序不同执行绪之间的同步手段。 套介面(Socket):更为一般的程序间通讯机制,可用于不同机器之间的程序间通讯。

程序间通讯方式中一般公司用的最多的是哪几个?做嵌入式的

pipe, fifo, 讯息伫列,共享记忆体这些传统的程序间通讯方式公司一般都不用,虽然共享记忆体可能快一点点,但是带来的维护开销等是很大的,公司一般会用socket也就是网路通讯的方式,或者是用资料库,程序1写资料库,程序2去读。我说的是linux系统。

python程序间通讯怎么理解

在2.6才开始使用

multiprocessing 是一个使用方法类似threading模组的程序模组。允许程式设计师做并行开发。并且可以在UNIX和Windows下执行。

通过建立一个Process 型别并且通过呼叫call()方法spawn一个程序。

一个比较简单的例子:

#!/usr/bin/env python

from multiprocessing import Process

import time

def f(name):

time.sleep(1)

print 'hello ',name

print os.getppid() #取得父程序ID

print os.getpid() #取得程序ID

process_list = []

if __name__ == '__main__':

for i in range(10):

p = Process(target=f,args=(i,))

p.start()

process_list.append(p)

for j in process_list:

j.join()

程序间通讯:

有两种主要的方式:Queue、Pipe

1- Queue类几乎就是Queue.Queue的复制,示例:

#!/usr/bin/env python

from multiprocessing import Process,Queue

import time

def f(name):

time.sleep(1)

q.put(['hello'+str(name)])

process_list = []

q = Queue()

if __name__ == '__main__':

for i in range(10):

p = Process(target=f,args=(i,))

p.start()

process_list.append(p)

for j in process_list:

j.join()

for i in range(10):

print q.get()

2- Pipe 管道

#!/usr/bin/env python

from multiprocessing import Process,Pipe

import time

import os

def f(conn,name):

time.sleep(1)

conn.send(['hello'+str(name)])

print os.getppid(),'-----------',os.getpid()

process_list = []

parent_conn,child_conn = Pipe()

if __name__ == '__main__':

for i in range(10):

p = Process(target=f,args=(child_conn,i))

p.start()

process_list.append(p)

for j in process_list:

j.join()

for p in range(10):

print parent_conn.recv()

Pipe()返回两个连线类,代表两个方向。如果两个程序在管道的两边同时读或同时写,会有可能造成corruption.

程序间同步

multiprocessing contains equivalents of all the synchronization primitives from threading.

例如,可以加一个锁,以使某一时刻只有一个程序print

#!/usr/bin/env python

from multiprocessing import Process,Lock

import time

import os

def f(name):

lock.acquire()

time.sleep(1)

print 'hello--'+str(name)

print os.getppid(),'-----------',os.getpid()

lock.release()

process_list = []

lock = Lock()

if __name__ == '__main__':

for i in range(10):

p = Process(target=f,args=(i,))

p.start()

process_list.append(p)

for j in process_list:

j.join()

程序间共享状态 Sharing state beeen processes

当然尽最大可能防止使用共享状态,但最终有可能会使用到.

1-共享记忆体

可以通过使用Value或者Array把资料储存在一个共享的记忆体表中

#!/usr/bin/env python

from multiprocessing import Process,Value,Array

import time

import os

def f(n,a,name):

time.sleep(1)

n.value = name * name

for i in range(len(a)):

a[i] = -i

process_list = []

if __name__ == '__main__':

num = Value('d',0.0)

arr = Array('i',range(10))

for i in range(10):

p = Process(target=f,args=(num,arr,i))

p.start()

process_list.append(p)

for j in process_list:

j.join()

print num.value

print arr[:]

输出:

jimin@Jimin:~/projects$ python pp.py

81.0

[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

'd'和'i'引数是num和arr用来设定型别,d表示一个双精浮点型别,i表示一个带符号的整型。

更加灵活的共享记忆体可以使用multiprocessing.sharectypes模组

Server process

Manager()返回一个manager型别,控制一个server process,可以允许其它程序通过代理复制一些python objects

支援list,dict,Namespace,Lock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value,Array

例如:

#!/usr/bin/env python

from multiprocessing import Process,Manager

import time

import os

def f(d,name):

time.sleep(1)

d[name] = name * name

print d

process_list = []

if __name__ == '__main__':

manager = Manager()

d = manager.dict()

for i in range(10):

p = Process(target=f,args=(d,i))

p.start()

process_list.append(p)

for j in process_list:

j.join()

print d

输出结果:

{2: 4}

{2: 4, 3: 9}

{2: 4, 3: 9, 4: 16}

{1: 1, 2: 4, 3: 9, 4: 16}

{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36}

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 8: 64}

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64}

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

Server process managers比共享记忆体方法更加的灵活,一个单独的manager可以被同一网路的不同计算机的多个程序共享。

比共享记忆体更加的缓慢

使用工作池 Using a pool of workers

Pool类代表 a pool of worker processes.

It has methods which allows tasks to be offloaded to the worker processes in a few different ways.

c#多执行绪之间通讯方式有几种

多执行绪通讯的方法主要有以下三种: 1.全域性变数 程序中的执行绪间记忆体共享,这是比较常用的通讯方式和互动方式。 注:定义全域性变数时最好使用volatile来定义,以防编译器对此变数进行优化。 2.Message讯息机制 常用的Message通讯的介面主要有两个

windows程序间通讯和linux相同吗

# 管道( pipe ):管道是一种半双工的通讯方式,资料只能单向流动,而且只能在具有亲缘关系的程序间使用。程序的亲缘关系通常是指父子程序关系。 # 有名管道 (named pipe) : 有名管道也是半双工的通讯方式,但是它允许无亲缘关系程序间的通讯。

应用程序之间的数据交换(互相通讯)一直是困扰广大程序员的难题,尽管已经出现了各式各样的解决方案,但迄今为止没有哪一种方案是完美无缺的。因此,只有学习并了解了它们的优缺点后,才能在特定的情况下选择最佳方案,以满足最终的要求。1、共享在硬盘上建立一个瞎没纯文件,一个应用程序往该文件里写数据(可以不关闭文件,但必须刷新缓冲区),另一个应用程序以共享方式打开这个文件并读取其中的内容,这便是最简单的一种数据交换方式。对于网络用户而言,只要两台终端上安装的都是Win311 For Workgroup或Windows 95(或NT),则只要设置一下目录共享,映射成网络驱动器,同样可以简单地实现数据交换。但它的缺点也是显而易见的:只能采取轮询的方式获得最新数据(效率低下),网络映射的驱动器绝对不能变动或取消(可靠性差),所以这是一种“低级”的通讯方式。2、DDE每个Windows程序员都不会对DDE(动态数据交换)感到陌生,它是最早的基于Windows的数据交换方法,有三种方式可供选择:冷连接、温连接和热连接。一般都是由客户端向服务器端发出连接申请,并且必须指明服务器端的名字和标题。在连接建立后,数据可以双向流动。典型的例子如抓图软件SnagIt,它提供了DDE接口,能够让其它应用程序来控制它。DDE是完全向后兼容的,从16位平台转到32位,源代码几乎不用修改。DDE还察旦有网络功能。使用过Win311 For Workgroup的人大概都还记得,它自带一个非常吸引人的小程序“Chat”,能使两台计算机通过网络实时交谈,这在当时几乎是一项创举。可是很少有人知道“Chat”使用的是一种特殊的DDE,即NetDDE。它的基本工作原理仍然是DDE,但它能使一台计算机向在同一个网络中的另一台终端发消息,而不像普通DDE 只能局限在同一台机器上。与其它的数据交换方式相比,DDE已不够先进,而且Microsoft也不再积极支持DDE,所以它的前景不被看好。3、WM_COPYDATAWindows消息WM_COPYDATA功能强大,知之者却甚少。它的确切定义是:一个应用程序向另一个应用程序传递数据时所发出的消息。众所周知,Windows 在很大程度上依赖于消息机制,那么我们为什么不把数据放在消息中一起发送出去呢?这样,我们只要调用SendMessage(),以对方窗体的句柄作为第一个参数,以含有指向实际数据的指针结构的地址作为第二个参数,就可以把整个数据块当作消息发向另一个应用程序。也许有的程序员会说,一个自定义的消息同样可以完成这样的工作。他只说对了一半。自定义消息的确可以发送到其它的应用程序上去,但其原始数据所在的内存区只有在发送过程中才是合法的,若在其它模块中存取该内存区就会导致“Access Violation”。而使用WM_COPYDATA 则不存在这个问题,因为Windows 本身会替你处理这一切。深入钻研下去,你会发现它其实是先创建了一个文件映射的对象,将发送方的原始数据先拷贝至映射文件,然后再在接收方对这个映射文件打开一个“视图”磨咐。WM_COPYDATA 的不足之处在于:必须要有一个窗体来接收消息和数据(缺乏灵活性),数据在使用之前先得拷贝到一个映射文件(浪费资源)。4、NetBIOS从80年代开始,NetBIOS就是开发Client/Server类程序的标准接口。而当时其它的解决方案几乎都是从UNIX系统上发展而来的。当然,对于今天的用户而言,NetBIOS已不是唯一的选择,他们可以从各种方案中择优选取。在Windows 95和NT平台上,可以通过API函数Netbios()来调用NetBIOS功能。NetBIOS兼容以下几种低层协议:NetBEUI协议(NBF)、NWLink NetBIOS(NWNBlink)、NetBIOS over TCP/IP(NetBT)。NetBIOS的优点是速度较快,缺点是可靠性较差。5、标准的Sockets和WinSockSockets是15年前在UNIX系统上提出来的,一开始主要是用于本地通讯,但很快就应用在Client/Server体系上了。它的内核很简单:你可以将一个Socket看作是一个双向的节点,一个应用程序可以通过它先与另一个程序建立连接(建立在一个双方都认可的端上,以便于区分同时运行的几个通讯线程),然后就可以彼此交换数据了。微软公司在其基础上创建了WinSock,专门用于Windows接口,与Socket完全兼容。近年来基于TCP/IP协议的网络大行其道,Socket也随之获得了更加广泛的应用。如今,Sockets已在Internet上获得了最广泛的应用,主要是因为它的可移植性好:Socket应用程序无论在任何平台间都能互相进行通讯(不管是PC机还是Macintosh,也不管是Windows平台还是UNIX平台)。而最新推出的WinSock 2.0,已不仅仅只基于TCP/IP协议,还可基于其它几种传输协议(如IPX)。Socket的缺陷是它工作在通讯的低层,所以实现起来较为复杂(如果是Win 95或NT平台,则不存在这个问题,微软公司提供了相应的控件)。但是,如果要在多个平台间互相通讯,则Socket是不二之选。6、Mailslot和PipeMailslot和Pipe有很多相同点,即都是高层的、基于内存的通讯系统。Mailslot由Server端创建,代码如下: myMailslot = CreateMailslot(pSlotName, 0, MAILSLOT_WAIT_FOREVER, NULL)然后,Client端就可以像打开文件一样打开这个Mailslot,再通过API函数WriteFile()来将数据写入到消息队列中。与此相类似,Pipe也是由Server端创建的,代码如下:pipe = CreateNamedPipe(pPipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE |PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE,BUFSIZE, 20000, NULL)接着,Client端就可以通过一般的文件API读写数据,代码如下:pipe = CreateFile(pPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0,NULL)success = WriteFile(pipe, pMessage, strlen(pMessage) + 1, &bytesWritten, NULL)Pipe分两种,即命名Pipe和匿名Pipe。匿名Pipe是以句柄而不是以名字来进行标识的,因而也就限制了它只能在同一台机器上通讯,而不能应用于网络。命名Pipe则提供了以名字来进行标识,所以能在网络上的其它任何地方打开它。需要注意的是:命名Pipe只能在 Win NT而不是Win 95上创建(即Server端),Client端则可以是任意平台。Pipe既可以单向通讯也可以双向通讯,Mailslot则只能单向通讯。Client端可以发送消息给mailslot,但不能接收消息;如果你想要接收消息,则只能创建一个新的mailslot。但mailslot有一个很大的优点:它支持数据广播。也就是说,若Client端发送一条消息,则整个网络中的同名对象都能收到。这是因为mailslot的名字的作用域只是在本台机器上,所以可在不同机器上创建同名的mailslot,当Client端发来消息时则每一台机上的mailslot都得到了该消息的一份拷贝,并在本机上作出相应的反应。Mailslot的最大缺陷是不可靠,因为它的数据是以数据报格式来传送的,网络错误或负荷过重都会导致数据丢失。Pipe则较为可靠,但它不能广播。所以,如果你不需要进行广播,则Pipe是更好的选择。选择Mailslot,则要对此后遇到的麻烦有充分的准备。7、剪贴板(Clipboard)大家对Windows的剪贴板应该不会感到陌生吧?它的出现就是为了实现应用程序间的互相数据交换。Windows提供了一系列的API函数来让应用程序安全地打开剪贴板,读写其中的数据。剪贴板的缺陷也是显而易见的:当有新的数据放在剪贴板上时,则先前的数据就会被冲掉,而在Windows中用到剪贴板的时候又实在太多了,所以这种方式用于程序间的通讯显然不够安全。8、COM和DCOM公共对象模式(COM)是一种协议,它建立了一个软件模块同另一个软件模块之间的连接,然后将其描述出来。当这种连接建立起来之后,则两个模块之间就可以通过称为“接口”的机制来进行通讯。COM可以用不同的语言(VB、VC、Delphi)进行编制,又能被其它语言编写的程序所使用,并且不用管通讯双方实际所处的位置(是在同一台机上,还是在同一个网络上的不同机上)。事实上,Internet上有大量的COM控件可供人们下载使用,其中有相当一部分就是用于应用程序间的相互通讯(甚至是Internet程序间的通讯),硬盘上能够看到的大量的.ocx文件其实就是一种COM。COM对象为外部调用提供了一个标准的界面,COM Client通过创建COM Server的一个实例获得指针,转向所需的函数定义处并执行相应的程序。讲得通俗一点,也就是先正确定义好COM对象的属性(Property),再执行相应的方法(Method)。DCOM(分布式公共对象模式)是COM在网络上的一种扩展,它通过把分布式对象间的通讯变成一个实体来实现通讯。COM如今被微软公司大力提倡,最著名的有OLE、ActiveX、DirectX和Win95、WinNT的外壳。由于微软公司目前在软件业处于霸主地位,所以COM很有可能成为将来的业界标准,其前途也较为看好。但COM的庞大也会使一些经验丰富的程序员望而却步,他们宁可自己多写一些代码以使整个程序更为简洁、有效而不愿使用COM。以上介绍的只是现今流行的一些通讯方法,它们各有各的优缺点,没有哪一种是万能的。因此,只有在合适的场合采用合适的方案,才是最好的解决办法。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12305183.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存