Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1707154
  • 博文数量: 607
  • 博客积分: 10031
  • 博客等级: 上将
  • 技术积分: 6633
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-30 17:41
文章分类

全部博文(607)

文章存档

2011年(2)

2010年(15)

2009年(58)

2008年(172)

2007年(211)

2006年(149)

我的朋友

分类: BSD

2009-07-23 17:55:19

进程间通信

1. 管道 (pipe) 的限制

    UNIX 管道要求所有的通信进程都源自一个共同的父进程。因此,管道的使用造成了一些系统在设计上采用了有些不自然的结构。

 

2.naive/sophisticated process

    所谓一个单纯进程 (navie process) 就是仅靠从标准输入文件中读数据和向标准输出文件写数据来完成工作的进程。

而一个成熟的进程 (sophisticated process) 则了解和掌握了操作系统提供的更多接口,并且它能用掌握的这些信息完成自己的工作。

 

3.IPC 在设计上应支持的特性

    透明性: IPC 应该和这些通信进程是否在同一台机器上没有关系。

    高效性

    兼容性:现有的单纯进程应该无需改动便可以在分布式环境里使用。

 

4. 通信语义与属性

    通信的语义包括:可靠数据传输的代价 (cost), 支持组播 (multicast) 传输,以及能够传送访问权限或能力等等。

其属性有:

  1. 数据的有序传送

  2. 数据的无重复发送

  3. 数据的可靠传送

  4. 面向连接的通信

  5. 信息分界的保存

  6. 对带外消息的支持

 

    带外 (out-of-band) 消息是在正常传入流 ( 即带内数据 ) 之外发送给接收方的消息。通常是在紧急或异常情况下发送它。

 

5. 常用套接口

    1> 数据报套接口 (datagram socket) 提供了一个不可靠的,无连接数据包通信模型;

    2> 流套接口 (stream socket) 提供了一个可靠的,面向连接的字节流模型,支持带外数据发送;

    3> 有序数据包套接口 (sequenced packet socket) 提供了一个有序,可靠,无重复的机遇连接的通信模型。

 

    连接是一种由协议使用的机制,协议用它来避免在每个发送的数据包上都带套接口标识。两端都各自保留状态信息。另一方面,无连接的同学要求在每一次传送时都带上源和目的地址。

 

6. 使用套接口

UNP 才是关于 socket 的最佳参考资料)

 

创建套接口

int sock, domain = AF_INET, type = SOCK_STREAM, protocol = 0;

sock = socket(domain, type, protocol);

 

初始化一个连接

int error;

int sock; /* Previously created by a socket() call. */

struct sockaddr_in rmtaddr; /* Assigned by the program. */

int rmtaddrlen = sizeof (struct sockaddr_in);

error =

connect(sock, (struct sockaddr *)&rmtaddr, rmtaddrlen);

 

客户端就到吃为止了,而服务器端则需把一个地址同一个套接口绑定

int error;

int sock;

struct sockaddr_in addr;

int addrlen = sizeof (struct sockaddr_in);

error =

bind(sock, (struct sockaddr*)&localaddr, localaddrlen);

 

监听套接口

int error, sock, backlog;

error = listen(sock, backlog);

 

接受传入的连接

int newsock, sock;

struct sockaddr_in clientaddr;

int clientaddrlen = sizeof(struct sockaddr_in);

newsock =

accept(sock, (struct sockaddr *)&clientaddr, clientaddrlen);

 

在套接口上发送和接受数据的例程

Routine

Connected

Disconnected

Address Info

read

Y

N

N

readv

Y

N

N

write

Y

N

N

writev

Y

N

N

recv

Y

Y

N

send

Y

Y

N

recvmsg

Y

Y

Y

sendmsg

Y

Y

Y

 

Sendmsg recvmsg 还可以传递有特殊解释的辅助数据或者控制信息

 

    IPC 覆盖在连网机制上,应用程序的数据流通过套接口层到达网 络层,反之亦然。套接口层所需的状态完全封装在它自己的里面,而所有与协议有关的状态都保存在专门支持该协议的辅助数据结构中。而存储传输数据的责任则从 套接口层下放到网络层。始终坚持这原则有助于简化存储管理的细节。

 

套接口层支持的例程

Routine

Function

socreate()

create a new socket

sobind()

bind a name to a socket

solisten()

mark a socket as listening for connection requests

soclose()

close a socket

soabort()

abort connection on a socket

soaccept()

accept a pending connection on a socket

soconnect()

initiate a connection to another socket

soconnect2()

create a connection between two sockets

sodisconnect()

initiate a disconnect on a connected socket

sosend()

send data

soreceive()

receive data

soshutdown()

shut down data transmission or reception

sosetopt()

set the value of a socket option

sogetopt()

get the value of a socket option

 

7. IPC 和网络协议对内存管理模式的要求

  1. 需要内存的可能是想通信协议数据包这样长度不定的结构。

  2. 数据包和其他数据对象必须在等待发送和接受时排成队列。

 

8.mbuf

    mbuf 即内存缓冲区 (memory buffer) ,它的大小随着它所保存的内容不同而变化。所有的 mbuf 都包含一个大小固定的 m_hdr 结构,这个结构记录了各种有关 mbuf 的信息位。一个只含数据的 mbuf 234 字节的空间 (mbuf 总长 256 字节,减去 mbuf [m_hdr] 22 字节 )

 

    把一则消息的内容向上传递给更高层的处理模块之前,协议要例行地剥去此消息前后的协议信息;而在向下传递消息时,又要加上协议信息。

 

    由 m_next 链接器阿里的一个 mbuf 结构的集合称为一个链;而由 m_nextpkt 链接起来的若干个 mbuf 链则被称为一个队列。

 

mbuf 除了 m_hdr 外还可以只用标志指定第二组数据包头

Memory-buffer (mbuf) data structure with M_PKTHDR

 

Memory-buffer (mbuf) data structure with external storage

 

9.mbuf 的数据域长度固定不可变的原因

  1. 长度固定使得内存的碎片化降至最低

  2. 要求通信协议频繁地在已有的数据区前后添加协议头,对数据区进行分割,或者是从一个数据区的开始或末尾截取数据。 Mbuf 在设计必须能够在热和可能的时候无需重新分配或复制内存,就可以处理这样的变化。

  3. 如果 mbuf 打大小不固定的话,一些相关函数的执行开销将会大得多。

 

10. 为了支持 SMP mbuf 的改进

    每个 CPU 都有自己的存放 mbuf mbuf 簇的链表。还有一个通用的 mbuf mbuf 簇的链表,当每个 CPU 自己的链表使用完了,就要尝试从那个通用链表分配内存,而当每个 CPU 自己的链表都有足够空间了,就要把内存释放回该通用链表。

 

11.socket 与通信域的相关数据结构

    1> 系统支持的套接口类型

Name

Type

Properties

SOCK_STREAM

stream

reliable, sequenced, data transfer; may support out-of-band data

SOCK_DGRAM

datagram

unreliable, unsequenced, data transfer, with message boundaries preserved

SOCK_SEQPACKET

sequenced packet

reliable, sequenced, data transfer, with message boundaries preserved

SOCK_RAW

raw

direct access to the underlying communication protocols

 

    2>domain 结构

其中 dom_family 项去确定了通信域所使用的地址族

Name

Description

AF_LOCAL

(AF_UNIX) local communication

AF_INET

Internet (TCP/IP)

AF_INET6

Internet Version 6 (TCP/IPv6)

AF_NS

Xerox Network System (XNS) architecture

AF_ISO

OSI network protocols

AF_CCITT

CCITT protocols, e.g., X.25

AF_SNA

IBM System Network Architecture (SNA)

AF_DLI

direct link interface

AF_LAT

local-area-network terminal interface

AF_APPLETALK

AppleTalk network

AF_ROUTE

communication with kernel routing layer

AF_LINK

raw link-layer access

AF_IPX

Novell Internet protocol

 

    3>socket 结构

Socket 包含的信息有关它们的类型,使用的支持协议以及它们的状态。

State

Description

SS_NOFDREF

no file-table reference

SS_ISCONNECTED

connected to a peer

SS_ISCONNECTING

in process of connecting to peer

SS_ISDISCONNECTING

in process of disconnecting from peer

SS_CANTSENDMORE

cannot send more data to peer

SS_CANTRCVMORE

cannot receive more data from peer

SS_RCVATMARK

at out-of-band mark on input

SS_ISCONFIRMING

peer awaiting connection confirmation

SS_NBIO

nonblocking I/O

SS_ASYNC

asynchronous I/O notification

SS_INCOMP

connection is incomplete and not yet accepted

SS_COMP

connection is complete but not yet accepted

SS_ISDISCONNECTED

socket is disconnected from peer

 

    用来接受传入连接请求的套接口有两个与连接请求相关的套接口队列。由 so_incomp 字段开头的套接口链表代表了一个由连接组成的队列,必须在协议层完成这些连接后才能将它们返回。 so_comp 字段开头的则是一个准备返回给监听进程的套接口链表。

 

4> 套接口地址

 

 

12. 高位线、低位线

    为了避免耗尽资源,对于在一个套接口数据缓冲区中排队的数据字节数,也就是数据所能使用的存储空间量,套接口都给它们设置了上界。这个高位线 (high watermark) 由协议进行初始化,当然一个应用程序也可以改变这个值,但它不能超过系统最大值 ( 通常是 256KB) 。网络协议能够检查高位线,并将这个值用于流控策略。在每个套接口数据缓冲区中还有一个低位线 (low watermark) 。低位线是满足一次数据接收请求所需要的最少字节数,应用程序可以通过它控制数据流。

 

13. 建立连接

    进程对接期间套接口的状态转换图

Socket state transitions during process rendezvous

 

在套接口上排队以等待 accept() 调用的链接

 

    在连接建立的过程中,套接口的状态有套接口层和支持协议层联合管理。一个协议永远不会直接改变套接口的状态值;为促进模块化,所有的改变都由替代套接口 例程来执行。这些例程按照指示改变套接口的状态,并通知任何处于等待中的进程。支持协议层从来不直接使用同步或信号机制。异步检查出的错误被传递到一个套 接口的 so_error 项中。

 

14. 传送 / 接收数据

    套接口层主要的工作就是发送和接收数据。必须注意,除了可以选择加记录边界之外,套接口层本身明确不允许在通过套接口传输或接收的数据上施加任何结构。在整个 IPC 中,对任何数据的解释或者结构化在逻辑上都独立于通信域的实现。

    对于那些要保证数据可靠传递的套接口来说,协议通常要在套接口的发送队列里保留所有要发送数据的一个副本,直到接收方确认收到这些数据为止。那些不保证数据一定发送到的协议则通常从 sosend 中接受数据,然后将其直接发往目的地,不保存任何副本。但是 sosend() 自己并不区分可靠与不可靠传输。

    在接受数据缓冲中出现的数据组织通常有 3 中情况:分别针对流,数据报以及有序数据包的套接口。在一般情况下,接收数据缓冲区是按照消息链表的方式来组织的。

Data queueing for datagram socket

 

15. 关闭套接口

    1> 对可靠协议的 close 隐含的语义

    当一个承诺可靠传送数据的套接口在关闭时还有排队等待发送的数据,或者还有等待确认收到的数据,套接口就必须为了 close 调用, ( 可能无限次地 ) 尝试发送这些数据,以保证套接口承诺的可靠传递数据的语义。如果套接口为了使 close 调用成功完成而丢弃数据的话,它就违背了关于可靠传递数据的承诺。根据 close 隐含语义,丢弃数据就可能导致这些进程在网络环境中的工作不可靠。然而,如果一直到所有的数据都被成功发送后才关闭套接口,那么,在有些通信域中, close 调用可能永远不会结束。

 

    2> 关闭套接口时其状态转换图

 

 

16. 本地 IPC

本地 IPC 的用户级 API

Subsystem

Create

Control

Communicate

semaphores

semget

semctl

semop

message queues

msgget

mesgctl

msgrcv, msgsnd

shared memory

shmget

shmctl, shmdt

n/a

 

消息队列天生就是半双工的,在通信端点之间传递的消息里带有一个类型和一个数据区。

 

    对于共享内存,当进程用完共享内存的时候,它就使用系统调用 shmdt 把共享内存从它的进程空间中剥离。这个例程不会释放共享内存,因为其他进程可能还在使用它,但是它会解除调用它的进程对虚拟内存的映射。

阅读(921) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~