Yuan's profileSpringsun is sunny :)PhotosBlogListsMore ![]() | Help |
|
|
September 29 FAQ: Solaris系统下安装Perl模块可能出现的问题
在Solaris中安装Perl模块总是遇到一些问题,下面就说一下如何来解决常见的问题的。
FAQ1.
FAQ2. Could not fetch authors/01mailrc.txt.gz 说明CPAN没有找到可以下载模块的网络地址。
FAQ3.
FAQ4. 这是因为Perl默认情况下认为编译器是cc,其实cc只是个脚本文件。Solaris有两类编译器Sun Studio和gcc。
FAQ5. September 30 HIGHLY RELIABLE AND SECURE SYSTEMS [ZZ]HIGHLY RELIABLE AND SECURE SYSTEMSThis section lists operating systems designed with very high reliability or security as a principal goal. Some of these systems are designed to control specialized architectures which include features to support this goal.
From http://www.csee.wvu.edu/~jdm/classes/cs258/OScat/reliable.html June 26 FreeBSD 5.2 进程间通信机制的实现 [原创] - 3
3. 网络输入/输出概述根据网络的四个层次,用户数据是从用户态进程通过调用socket系统调用,依次往低层传递的,最后到达网络底层发送出去,或者,从网络底层上接收数据,依次向高层传递,并到达用户程序。网络通信的输入/输出流程如图 10所示。
图 10 网络输入/输出流程 下面以UDP数据包的发送和接收为例,简要说明网络的输入/输出过程。 3.1. 输入(1) 在socket层将目标socket地址结构复制到一个mbuf中,并把数据复制到mbuf链中后,调用与此socket描述符对应的协议层,如调用UDP输出例程,并将指向mbuf的指针被作为参数。该例程要在数据的前面添加一个IP首部和一个UDP首部,然后将这些mbuf传递给IP输出例程。 (2) IP输出例程要填写IP首部中剩余的字段,包括IP检验和;确定数据报应发到哪个输出接口(这是IP路由功能);必要时,对IP报文分片;以及调用接口输出函数。 (3) 以太网输出函数的可以把32位IP地址转换成相应的48位以太网地址。然后以太网输出例程把一个14字节的以太网首部添加到链表的第一个mbuf中,紧接在IP首部的前面。 (4) 之后此mbuf链表被加到此接口的输出队列队尾。如果接口不忙,接口的“开始输出”例程立即被调用。若接口忙,在它处理完输出队列中的其他缓存后,它的输出例程会处理队列中的这个新mbuf。 (5) 当接口处理它输出队列中的一个mbuf时,它把数据复制到它的传输缓存中,并且开始输出。一旦数据从mbuf链表被复制到设备传输缓存, mbuf链表就被以太网设备驱动程序释放。mbuf被放回到内核的自由缓存池中。
3.2. 输出(1) 收到完成中断,以太网设备驱动程序开始接收一个输入分组,把数据从设备读到一个mbuf链表中。通过以太网帧中的类型字段来确定哪个协议层来接收此分组。如标识为IP数据报,就把mbuf加入到IP输入队列中。另外,会产生一个软中断来执行IP输入例程。这样,这个设备中断处理就完成了。 (2) IP输入例程处理收到的每个IP数据报。验证IP首部检验和,处理IP选项,验证数据报被传递到正确的主机(通过比较数据报的目标IP地址与主机IP地址),并当系统被配置为一个路由器,且数据报被表注为其他的IP地址时,转发此数据报。如果IP数据报到达它的最终目标,调用IP首部中标识的协议的输入例程: ICMP,IGMP,TCP或UDP。在例子中,调用UDP输入例程去处理UDP数据报。 (3) UDP输入例程验证UDP首部中的各字段(长度与可选的检验和),然后确定是否一个进程应该接收此数据报。根据端口号,通过协议控制块pcb,找到相应的socket,并将收到的mbuf追加到这个socket的接收队列。然后唤醒接收进程。 (4) 接收进程被唤醒。内核把UDP层追加到socket接收队列中的数据(接收的数据报)从mbuf复制到应用程序的缓存中。 FreeBSD 5.2 进程间通信机制的实现 [原创] - 2.22.2. mbuf的分配和释放mbuf分配请求是通过调用m_get(), m_gethdr() 或者等价的宏MGET和MGETHDR来实现的。m_gethdr会使用数据包头来初始化mbuf。 使用宏MCLGET 将一个mbuf cluster添加到一个mbuf上。 释放mbuf资源: m_free()释放一个mbuf, m_freem()释放一个mbuf链. 当引用了mbuf簇的一个mbuf被释放时,该簇的引用计数就会减一。当mbuf簇的引用计数为0时,就会将它们放到适当的CPU队列上。
2.3. mbuf的实用程序m_copym()从一个mbuf链的逻辑偏移开始逐字节拷贝,可以拷贝mbuf链的所有或部分内容。如果mbuf与一个mbuf簇相关,就只会引用相同的数据,而不是拷贝数据,同时增加cluster的引用计数(MEXT_ADD_REF);否则,与mbuf簇无关,就会拷贝数据部分。 m_copydata()功能类似,但只是从一个mbuf链将数据拷贝到调用程序所提供的缓冲区。该缓冲区不是一个mbuf,或者链,而是由传统的C指针指向的一个内存空白区域。 m_adj()通过指定特定数目的字节,从前开始削减,以调整mbuf链中的数据。但是不会拷贝数据。从m指向的mbuf中移走len字节的数据。如果len是正数,则所操作的是紧排在这个mbuf的开始的len字节数据;否则是紧排在这个mbuf的尾部的len绝对值字节数据。m_adj()纯粹是操作mbuf结构体中的偏移和长度字段。 mtod()宏使用指向mbuf头部的一个指针和一种数据类型作参数,根据指定类型,返回指向缓冲区中数据的指针。 dtom()相反,将指向一个mbuf数据区中某个位置的指针x转换成一个指向这个mbuf(不是mbuf链的头部)的起始的指针。具体是通过截取一段mbuf大小的数据地址来实现的。只有当mbuf中存在数据时该函数才会起作用。
/*- * Macros for type conversion: * mtod(m, t) -- Convert mbuf pointer to data pointer of correct type. * dtom(x) -- Convert data pointer within mbuf to mbuf pointer (XXX). */ #define mtod(m, t) ((t)((m)->m_data)) #define dtom(x) ((struct mbuf *)((intptr_t)(x) & ~(MSIZE-1)))
m_pullup()重新调整mbuf链,让一定数量的字节能够驻留在mbuf(而不是外部存储器)中的一个连续数据区中。该操作用于像协议头一样的对象,它们是连续的,并能看作是一个正常的数据结构体。当该客体被释放时,dtom能够工作。如果有空闲空间,m_pullup()将会增加连续区域的大小,一直到到达协议头部的最大值,以避免将来被调用到。 M_PREPEND() 宏调整mbuf链以便预先准备一定字节数目的数据。若可能的话,会马上准备好空间,但有可能会在链的开始处分配其他的mbuf。这是因为不同的mbuf簇可能会引用cluster中不同的部分,所以当前还不能够在一个mbuf簇中预先准备数据。 /* * Arrange to prepend space of size plen to mbuf m. * If a new mbuf must be allocated, how specifies whether to wait. * If the allocation fails, the original mbuf chain is freed and m is * set to NULL. */ #define M_PREPEND(m, plen, how)
关于mbuf中一些常见宏的总结,如表格 1所示。
表格 1 mbuf中常见的宏
关于mbuf的一些常用函数的总结,如表格 2所示。
表格 2 mbuf常用的函数
FreeBSD 5.2 进程间通信机制的实现 [原创] - 2.1mbuf的标记从逻辑上可以分为两类:一类描述mbuf的使用,另一类描述存储在一个Mbuf链中的对象。描述mbuf的标记说明mbuf是否引用外部存储器(M_EXT),另外一组头部字段是否存在(M_PKTHDR),mbuf是记录的最后一部分(M_EOR)。通常,一个数据包应该存储在一个mbuf链中,并将该链的第一个mbuf的标记置为M_PKTHDR。描述数据包的mbuf的标记应该设置在第一个mbuf上,包括广播标记(M_BCAST)或者组播标记(M_MCAST)。后面这些标记指明传输的数据包可以以广播或组播的方式发送,或者接收到的数据包是以这种方式发送过来的。 如果一个mbuf被设置了M_PKTHDR标记,说明在该mbuf的标准头部以后便是另外一组头部字段。这些附加的信息导致mbuf的数据区从234byte减少到210byte。数据包的头部,如图11.4所示,它只用于链的第一个mbuf上,包括的字段有:指向接收到数据包的接口的指针rcvif,数据包的总长度len,与数据包的校验计算有关的两个字段csum_flags和sum_data,指向一个数据包tag的队列的指针tags。
图 6 标记为M_PKTHDR的mbuf /* * Record/packet header in first mbuf of chain; valid only if M_PKTHDR is set. */ struct pkthdr { struct ifnet *rcvif; /* rcv interface */ int len; /* total packet length */ /* variables for ip and tcp reassembly */ void *header; /* pointer to packet header */ /* variables for hardware checksum */ int csum_flags; /* flags regarding checksum */ int csum_data; /* data field used by csum routines */ SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */ }; 注:注意每个mbuf的成员m_len与分组首部中的成员m_pkthdr.len的区别。前者说明从数据指针处开始算起mbuf中有效数据的字节数。后者是链表中所有mbuf的m_len的和。
使用外部存储器的mbuf标记了M_EXT。此时,就会有一个不同的头部区域覆盖掉mbuf的内部数据区域。该头部的字段描述了外部存储器的信息,如缓冲区的开始位置和大小,见图11.5。字段ext_free指向释放缓冲区的程序,理论上讲可以使用mbuf映射各种类型的缓冲区。但是,在当前的实现中,并没有用到释放函数,假设外部存储器是标准的mbuf簇。一个mbuf可以有一个数据包头部并有外部存储器,在这种情况下,mbuf标准的头部后面会跟着数据包的头部,然后是外部存储器的头部。
图 7 标记为M_EXT的mbuf
/* * Description of external storage mapped into mbuf; valid only if M_EXT is set. */ struct m_ext { caddr_t ext_buf; /* start of buffer */ void (*ext_free) /* free routine if not the usual */ (void *, void *); void *ext_args; /* optional argument pointer */ u_int ext_size; /* size of buffer, for ext_free */ volatile u_int *ref_cnt; /* pointer to ref count info */ int ext_type; /* type of external storage */ };
一个mbuf可以引用mbuf簇,这种方式使得网络代码中的不同实体可以引用相同的数据,而无需memory-to-memory的拷贝。当需要数据块的多个拷贝时,可以从多个mbuf引用同一个mbuf簇。为mbuf簇使用了一个引用计数的全局数组。 根据m_flags的值不同,mbuf可以分为四种不同的类型,即当flag分别为0、M_PKTHDR、M_EXT以及同时为M_PKTHDR和M_EXT。mbuf的内容分别如下图所示:
图 8 根据m_flags 不同而分类的四种mbuf
其中黑色部分表示为没有使用到的缓冲区域。
根据前面的论述,将mbuf链和队列,以及m_flags为不同值时的情况结合一下,我们可以得到如图 9所示的mbuf的一种链接情况。
图 9 mbuf链和队列的综合
FreeBSD 5.2 进程间通信机制的实现 [原创] - 2.1
2. 缓存管理mbuf2.1. mbuf的结构网络协议对内核的存储器管理能力提出了很多要求。这些要求包括能方便地操作可变长缓存,能在缓存头部和尾部添加数据(如低层封装来自高层的数据),能从缓存中移去数据(如,当数据分组向上经过协议栈时要去掉首部),并能尽量减少为这些操作所做的数据复制。内核中的存储器管理管理直接关系到网络协议的性能。 FreeBSD内核中使用的主要存储器缓存是mbuf(sys/mbuf.h),它是网络通信涉及的主要数据结构,所以有必要先清楚该结构的内容。mbuf是“memory buffer”的缩写,它的主要用途是保存在进程和网络接口间互相传递的用户数据,也用于保存其他各种数据:源与目标地址、套接字选项等。参考[2]的第2章和[3]。
/* * Header present at the beginning of every mbuf. */ struct m_hdr { struct mbuf *mh_next; /* next buffer in chain */ struct mbuf *mh_nextpkt; /* next chain in queue/record */ caddr_t mh_data; /* location of data */ int mh_len; /* amount of data in this mbuf */ int mh_flags; /* flags; see below */ short mh_type; /* type of data in this mbuf */ };
#define MSIZE 256 /* size of an mbuf */ #define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */
/* * The core of the mbuf object along with some shortcut defines for * practical purposes. */ struct mbuf { struct m_hdr m_hdr; union { struct { struct pkthdr MH_pkthdr; /* M_PKTHDR set */ union { struct m_ext MH_ext; /* M_EXT set */ char MH_databuf[MHLEN]; } MH_dat; } MH; char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ } M_dat; }; #define m_next m_hdr.mh_next #define m_len m_hdr.mh_len #define m_data m_hdr.mh_data #define m_type m_hdr.mh_type #define m_flags m_hdr.mh_flags #define m_nextpkt m_hdr.mh_nextpkt #define m_act m_nextpkt #define m_pkthdr M_dat.MH.MH_pkthdr #define m_ext M_dat.MH.MH_dat.MH_ext #define m_pktdat M_dat.MH.MH_dat.MH_databuf #define m_dat M_dat.M_databuf
所有的mbuf都包含一个固定的头部结构体m_hdr,一个mbuf包含的数据空间只有234个字节 (MSIZE - sizeof(struct m_hdr)= 256 – 22 = 234)。所有结构的大小都是为32位处理器而设计的。
图 3 缓冲mbuf的数据结构
在FreeBSD中,mbuf的大小是固定的(MSIZE),为256 个字节。当网络应用程序传输的数据大小超过mbuf的大小时,就会使用一组链接(chained)在一起的mbuf。Mbuf的确切数目依赖于定义的阈值(一般为900byte)。当应用程序的数据大小超过该数值后,就会将第一个mbuf链接到一个更大的外部内存缓冲区中,该缓冲区也称为cluster或者mcl,其大小由宏MCLBYTES定义,根据系统体系结构不同而不同,一般为2K,即2048个字节。下图说明了mbuf链的一种可能的情形。
图 4 mbuf链的一种可能情形
注: mbuf的数量可以通过sysctl的kern.ipc.nmbclusters参数进行调整。通过增加mbuf的值,可以避免出现“All mbuf clusters exhausted”的问题。每个cluster(簇)大概有2K的内存,当nmbclusters=1024时表示保留2M内核内存作为网络缓冲区。 这样便可以简单地计算出需要多少内存。如有一个web服务器最多可以有1000个并发连接,每个连接消耗16K接收和发送缓冲区,即大概需要32MB的网络缓冲区。一个比较粗糙的方法是乘以2,所以32MBx2/2K = 64MB/2K = 32768。在此情况下,需要设置nmbclusters为32768。但只有在开机时设定该sysctl参数,开机后便无法使用该参数,所以需要在/boot/loader.conf文件中加入一行: kern.ipc.nmbclusters=32768 netstat(1)的-m选项可以用来查看网络缓存的使用情况。
数据要么存储在内部数据区中要么存储在外部mbuf簇中,从不会同时存在于两个区域中。为了访问存储的数据,在mbuf中使用了一个数据指针m_data。除了数据指针以外,还用到了长度字段m_len,该字段说明从数据指针处开始算起有效数据的字节数。通过这两个字段,程序就可以从mbuf开始或结尾处有效地截取数据。若在mbuf的开始处删除数据,指针就会增加,长度减少。若从mbuf的结尾处删除数据,长度减少,但指针不变。当空间可用时,可以从两端的任一段添加数据。 多个mbuf可以链接在一起以容纳任意大小的数据。可以通过字段m_next链接mbuf。以这种方式链接起来的mbuf链被看作为一个对象。例如,通信协议可以使用一个mbuf链(chain)来构建数据包。另外一个字段m_nextpkt,将从mbuf链中构建而来的对象再链接成对象列表(list)。也就是说,通过字段m_next链接起来的一组mbuf叫做一个mbuf链(chain),使用字段m_nextpkt链接起来的mbuf链被称为一个队列(queue)。见图 5所示。
图 5 mbuf链和队列
m_type表示存储在mbuf中的数据的类型。需要这个字段的原因是,因为一个mbuf除了用来存放要发送或接收的用户数据以外,还可以存储各种不同的数据结构。MT_DATA说明mbuf中存储的是动态分配的数据,MT_SONAME说明存储的是socket名字。 June 25 FreeBSD 5.2 进程间通信机制的实现 [原创] - 11. 网络概述1.1. 概述网络子系统提供了一个通用框架,在此框架中可以实现各种网络服务。所提供的设施主要包括: l 对socket层的结构化接口,从而可以开发与网络无关的应用软件 l 用于传输和接收数据的、对硬件设备的一致性接口 l 对与网络无关的、消息路由的支持 l 缓存管理
1.2. 内部结构内核中,网络子系统逻辑上分为三层,分别完成以下任务: l 进程间数据传输 l 网络间寻址和消息路由 l 传输介质的支持 前两层由实现通信协议的模块组成,第三层的软件通常包括协议子层,以及一个或多个网络设备驱动,与硬件相关的。这三层分别称为传输层、网络层、网络接口或者链路层。以常见的TCP/IP协议为例,网络层次结构如图 1所示。网络子系统提供了套接字机制,套接字成为用户层应用程序与内核网络通信之间的接口。所以,在考察整个网络系统的实现机制时,必须将套接字考虑在内,所以如图 2所示,将整个网络部分重新划分为套接字层、传输层、网络层和网络接口或链路层。同时,我们也可以将传输层和网络层共同称为网络协议层,它的实现是与硬件设备无关的。本报告从顶层的套接字层到底层的链路层,主要介绍用户数据是如何发送到网络中,和从网络中接收数据的整个过程。
图 1 网络层次结构 1.3. 数据流动数据通过一个网络节点时,实际上只遵循有4种路径: l Inbound: 目的地是用户层应用程序. l Outbound: 从用户层程序到网络. l Forward: 无论是桥接还是路由到该节点的数据包,都被发送给另外一个网络或主机。 l Error: 包是否已经到达,需要网络子系统本身能够发回一个响应,且不需要用户层应用程序的参与。 数据包向上流动的实例如图 2所示。
图 2 数据包向上流动的实例 FreeBSD 5.2 进程间通信机制的实现 [原创] - 005年写的一篇FreeBSD下的《 网络代码阅读分析报告》。也别发了霉,拿出来给大家共享一下吧。陆陆续续的贴一贴吧。
0. 前言本报告的目的是熟悉FreeBSD中进程间通信IPC(Interprocess Communication)机制的实现,特别是远程网络通信。了解网络子系统中的主要数据结构和各网络层次之间的接口,理清内核函数之间的相互调用关系,从而把握网络子系统的整体框架和实现脉络。 报告的主要内容是介绍FreeBSD 5.2中的进程间通信IPC(Interprocess Communication)机制的内核实现。由于当前FreeBSD系统主要支持两类进程间通信机制。第一类System V IPC,适用于单机,包括信号量(semaphores), 消息队列(message queues)和共享内存(shared memory);第二类是套接字socket,它可以用于两台以及同一台机器之间的进程相互通信,为网络通信提供了统一的通信API。而本报告的重点是介绍通过socket所实现的进程间远程通信。 报告首先概述了网络子系统的整体结构和与网络缓存管理相关的重要数据结构mbuf,然后详细介绍了socket相关的系统调用和内核数据结构及实现,再讲述内核中各个网络层次之间的接口和关键数据结构,详细描述了数据包是如何从系统调用开始发送到网络底层,以及如何从网络底层接收到用户态的。此后,又简单介绍了网络其他功能,如路由、原始socket、带外数据(OOB)和ARP协议等的实现。最后简单介绍本地进程间通信System V IPC的三种机制。 主要涉及“The Design and Implementation of the FreeBSD Operating System”[1]一文中的第11和12章,以及13章中的关键部分。
行文约定: 代码和数据结构使用格式如“struct mbuf”表示,其所出现在的源文件名称使用格式如“sys/mbuf.h”表示。
|
|
|