展望2011

《unix环境高级编程》通读学习笔记(六)(第15、16章)

上一篇 / 下一篇  2007-08-04 18:08:13 / 个人分类:unix环境高级编程的学习记录

15高级进程间通信51Testing软件测试网 s:N9?)r3te

15.1引言51Testing软件测试网O/\^a+]]

本章介绍某些高级的IPC以及它们的应用方法,包括:流管道和命名流管道。使用51Testing软件测试网7Ksr+Y+c1_ P

这些机制,可以在进程间传送打开文件描述符。在分别为每一个客户进程提供一个通道的系统中,这些通信机制使客户进程能与精灵服务进程会合。51Testing软件测试网#YR5tEo L

 51Testing软件测试网EA X5X9VY ?{

15.2流管道

4H#VCWxo)~3A0

流管道是一个双向(全双工)管道。单个流管道就能向父、子进程提供双向的数据流。图15-1显示了观察流管道的两种方式。它与图14-1的唯一区别是双向箭头连线,因为流管道是全双工的。51Testing软件测试网+[5Q!K&c,Z!AK?R

 51Testing软件测试网2Jus&wch4ZT

15.3传送文件描述符

7ke[nO a0

在进程间传送打开文件描述符的能力非常有用。用此可以对客户机/服务器应用进行不同的设计。它允许一个进程(一般是服务器)处理与打开一个文件有关的所有操作以及向调用进程返回一描述符,该描述符可被用于以后的所有I/O函数。打开文件或设备的所有细节对客户而言都是透明的。

qK(ql]&X ^8k0

   当从一个进程向另一个进程传送一打开文件描述符时,我们想要发送进程和接收进程共享同一文件表项。图15-4显示了所希望的安排。51Testing软件测试网X8l\4I5fXBHBr9|

本章使用的三个函数以发送和接收文件描述符。

6Mgas!ZQ(DQ2U5g9v#B0

-------------------------------------------------------------------------------------------------------------------

ew fO)\0

#include "ourhdr.h"

2|,Yw-](o v'F#E0

int send_fd(intspipefd, int filedes);

TCDAm z+r0

int send_err(int spipefd, int status, const char *errmsg);51Testing软件测试网OXSXM6i2z N

                                    两个函数返回:若成功则为0,若出错则为-1

)n7nk N2O0

int recv_fd(intspipefd, ssize_t (*userfunc)(int, const void *, size_t));51Testing软件测试网Y5I} q-hz#K

                                    返回:若成功则为文件描述符,若出错则<0

7hO X FiA|0

-------------------------------------------------------------------------------------------------------------------

S Z4G|i&~$X0

 51Testing软件测试网Z)[ h7N$?s

    当一个进程(通常是服务器)希望将一个描述符传送给另一个进程时,它调用send_fdsend_err。等待接收描述符的进程(客户机)调用recv_fd

8EFj6Am5`0

   send_fd经由流管道spipefd发送描述符filedessend_err经由流管道spipefd发送errmsgstatus字节。status的值应在-1~-255之间.

+j;Q Eac`+c-i0

客户机调用recv_fd接收一描述符。如果一切正常(发送者调用了send_fd),则作为函数值返回非负描述符。否则,返回值是由send_err发送的status.51Testing软件测试网3h1}I,V fod%I,cK

15.3.1 SVR4

j'e7^)| Td*hEDzP0

SVR4之下,文件描述符用两个ioctl命令在一流管道中交换,这两个命令是:I_SENDFDI_RECVFD51Testing软件测试网e?7`u9tH

15.3.2 4.3BSD

]x&T9Jr%d p/v#x8B"D0

   为了交换文件描述符,调用sendmsg(2)recvmsg(2)函数。这两个函数的参数中都有一个指向msghdr的指针,该结构包含了所有关于要发送和接收消息的信息。

}h Lvd0

15.3.3 4.3+BSD

5d1v|1M,k(y0

4.3BSD Reno开始,更改了msghdr结构的定义。在以前版本中被称之为“存取权”的最后两个元素改称为“辅助数据”。另外,在该结构结束处增加了一个新成员msg_flags

/C jF!XT.?0

 51Testing软件测试网t8N,G HoW!z

15.4 open服务器第1

4hO1O.?8Q[#mK&|0

目前,使用文件描述符传送技术开发了一个open服务器:它是一个可执行程序,由一个进程执行以打开一个或多个文件。该服务器不是将文件送回调用进程,而是送回一个打开文件描述符。用IPC交换最小量的信息—从客户机到服务器传送文件名和打开方式,而从服务器到客户机返回描述符。文件内容则不需用IPC传送。51Testing软件测试网:CRD6X%u @KB

   客户机创建一流管道,然后调用forkexec以调用服务器。客户机经流管道发送请求,服务器经管道回送响应。51Testing软件测试网`$d X^:aMo9\)\

 

l2@*d%f0G:M0

15.5客户机-服务器连接函数51Testing软件测试网mEVjt2F A

  对于相关进程(例如,父进程和子进程)之间的IPC,流管道非常有用。前节所述的open51Testing软件测试网+o \9q [ h}

服务器使用未命名的流管道能从子进程向父进程传送文件描述符。但是当处理无关进程时(例如,若服务器是一精灵进程),则需要使用有名的流管道。51Testing软件测试网G ~Z9|z

  服务器创建一名字公开的流管道的一端,然后客户机连接至该端。另外,每次一个新客户机连至服务器的命名流管道时,就在客户机和服务器之间创建一条全新的流管道。SVR44.3+BSD都支持这种形式的IPC。本节将开发三个函数,客户机-服务器可以使用这些函数以建立上述针对每个客户机的连接。51Testing软件测试网6OG.O9?0W |*r^M$g

--------------------------------------------------------------------------------------------------------------------51Testing软件测试网[!L8T| S

#include "ourhdr.h"51Testing软件测试网#b pYc)G4M)F'j2Y,Pe G

int serv_listen(const char *name);51Testing软件测试网 _ECN*C M

                           返回:若成功则返回为文件描述符,若出错则<0

:GX|r)O0

-------------------------------------------------------------------------------------------------------------------

*P5R\}G@gd0

   首先,一个服务器应当宣布,它愿意听取客户机在一个众所周知名字上的连接,该名字是在文件系统中的一个路径名。为此调用serv_listen,其参数name是服务器的众所周知名字。客户机希望与服务器连接时使用此名字。该函数的返回值是命名流管道服务器端的文件描述符。51Testing软件测试网G9JyI2q8[r,`

   一旦服务器已调用serv_listen,它将调用serv_accept等待客户连接到达。

&n c2{6Aa*F"ch(jg0

---------------------------------------------------------------------------------------------------------------------

Ippkd q!Fu4\c0

#include "ourhdr.h"51Testing软件测试网P9bb&h0n |3`l:\w

int serv_accept(int listenfd, uid_t *uidptr);

&olR@_)y)s{0

                        返回:若成功则返回为文件描述符,若出错则<0

1Q%R5W*Otk|%z0

--------------------------------------------------------------------------------------------------------------------51Testing软件测试网3jk#Ws H ^x

   listenfdserv_listen返回的描述符。在客户机连接到服务器众所周知的名字上之前,此函数并不返回。当客户机连接至服务器时,自动创建一条全新的流管道,其新描述符作为该函数的值返回。另外,客户机的有效用户ID通过指针uidptr存储。51Testing软件测试网~\]N(K4mk? e

   客户机为与服务器连接只需调用cli_conn函数。

"Qv[:K.B6Xu0

------------------------------------------------------------------------------------------------------------------51Testing软件测试网K&U#?|f*Ue

#include "ourhdr.h"51Testing软件测试网3w(k)MNv T v

int cli_conn(const char * name);

%w)A3\Vs+Rp5Sux0

                              返回:若成功则返回为文件描述符,若出错则<0

P2A#o*rj h0

-------------------------------------------------------------------------------------------------------------------51Testing软件测试网$Y,ToDm]0T

使用上述三个函数,就可编写服务器精灵进程,它可以管理任一数量的客户机。51Testing软件测试网(Rfk l1r[;Ny$l? GA

15.5.1 SVR4

N\f"[3Umvq'm0

SVR4提供装配的流以及一个名为connld的流处理模块,用其可以提供与服务器有唯一连接的命名流管道。

B2L5b"S~0

首先,服务器创建一未命名流管道,并将流处理模块connld压入一端。图15-5显示了这一处理结果。然后,使压入connld的一端具有一路径名。SVR4提供fattach函数实现这一点。任一进程(例如客户机)打开此路径名就引用该管道的命名端。51Testing软件测试网B'qZ~K8L z#iUOTr

15.5.2 4.3+BSD51Testing软件测试网C`UvL lR.r-Wg

4.3+BSD之下,为了用UNIX域套接口连接客户机和服务器,需要有一套不同的操作函数。

L$};c KO`(ipy3o0

 51Testing软件测试网7I9_cX2m3~Y o

15.6 open服务器第251Testing软件测试网(f9W:bD Kti

   15.4节中,客户机调用forkexec构造了一个open服务器,它说明了如何从子程序向父程序传送文件描述符。本节将开发一个精灵进程样式的open服务器。一个服务器处理所有客户机的请求。在客户机和服务器之间仍将使用上一节说明的三个函数:serv_listenserv_acceptcli_conn。本节所述的客户机类似于15.4节中的客户机。51Testing软件测试网+q4G%~{N;EP

 

_z]dJtAP;x0

16数据库函数库

wv4gO(k ~y$nTq(ip0

16.1引言51Testing软件测试网wy#_3F!v8jWP

80年代早期,UNIX环境被认为不适合运行多用户数据库系统。早期的系统,如V7,因为没有提供任何形式的IPC机制(除了半双工管道),也没有提供任何形式的记录锁机制,所以确实不适合运行多用户数据库。新一些的系统,象SVR44.3+BSD,则为运行可靠的、多用户的数据库系统提供了一个适合的环境。

:w.qDHJ8e0

本章将设计一个简单的、多用户数据库的函数库。通过此函数库提供的C语言函数,其他程序可以访问数据库中的记录。我们感兴趣的是一个数据库函数库与UNIX的接口,以及这些接口与前面各章节的关系。

)a:W$}M%PQ0

 51Testing软件测试网 a{)FIp tg

16.2历史

GPC9_K2g0

 

e2UQqD0

16.3函数库51Testing软件测试网2| v#r E-`U,o

本节将定义数据库函数库的C语言接口,下一节再讨论其实现。51Testing软件测试网9t+{m&cl

当打开一个数据库时,通过返回值得到一个DB结构的指针。我们将用此指针作为参数来调用以后的数据库函数。

t'es3v[q|'s0

----------------------------------------------------------------------------------------------------------------------

r![jN#g1^0

#include "db.h"51Testing软件测试网 P._ t:Q9E8Q]]'v1W @J5|

DB    *db_open(const char *pathname, int oflag, int mode);51Testing软件测试网P+J3W]W

                           返回:若成功则为DB结构的指针,若失败则为NULL

_8]/Yo2U3s&N0

void  db_close(DB *db);51Testing软件测试网gb^7u'U|

---------------------------------------------------------------------------------------------------------------------51Testing软件测试网/M"l1O t'hl

   当不再使用数据库时,调用db_close来关闭数据库。db_close将关闭索引文件和数据文件,并释放数据库使用过程中分配的所有用于内部缓冲的存储空间。51Testing软件测试网3f+Lr r6OMo\3b

当向数据库中加入一条新的记录时,必须提供一个此记录的关键字,以及与此关键字相联系的数据。我们的实现要求关键字必须是唯一的。

my Q/Uo"`l0

---------------------------------------------------------------------------------------------------------------------51Testing软件测试网,^ WBi MW(FpU

#include "db.h"

,o%MQR%ewqE O.]0

int db_store(DB *db,const char *key, const char *data, int flag);

-],qXJL0e0

                               返回:若成功则为0,若错误则为非0(见下)51Testing软件测试网`$D@M-u(G

----------------------------------------------------------------------------------------------------------------------51Testing软件测试网5J:P&W l0mX;h r7Lb

通过提供关键字key可以从数据库中取出一条记录。

Wg2@pq!b0

---------------------------------------------------------------------------------------------------------------------

8Jo'pF M8D/R Yn0

#include "db.h"

8k f.qN$P+V:h%S|;L*M0

char *db_fetch(DBdb*,const char *key,);

l"XDvm%R%r U0

                返回:若成功则为指向数据的指针,若记录没有找到则为NULL

k th;X+\I^]"Wj&i0

----------------------------------------------------------------------------------------------------------------------

2{\4b7r)Q'Yc'e6E8M0

通过提供关键字key,也可以从数据库中删除一条记录。

Yv1R3rA0

----------------------------------------------------------------------------------------------------------------------51Testing软件测试网GtE%W2Tb

#include "db.h"51Testing软件测试网_ `0\$K:ZM/R.y#x

int db_delete(DBdb*,const char *key);51Testing软件测试网8@g Sx~-Zf Uz

                               返回:若成功则为0,若记录没有找到则为-151Testing软件测试网g6hb3O^2n

----------------------------------------------------------------------------------------------------------------------

LG(DtM$z&t%F0

   除了通过关键字访问数据库外,也可以一条一条记录地访问数据库。因此,首先调用51Testing软件测试网X J%O:v%F pKA%?

db_rewind回到数据库的第一条记录,再调用db_nextrec顺序地读每个记录。51Testing软件测试网"E!UwGg%C

----------------------------------------------------------------------------------------------------------------------51Testing软件测试网?"A-v6d6zT5O

#include "db.h"51Testing软件测试网%dT-km9N4nai$xO

void db_rewind(DBdb*)51Testing软件测试网6G.C]}^"`e!bHG

char *db_nextrec(DBdb*, char*key);51Testing软件测试网V8Ox5L(WJ8~7k

          返回:若成功则返回指向数据的指针,若到达数据库的尾端则为NULL

j"HC,o a6|cuW0

----------------------------------------------------------------------------------------------------------------------51Testing软件测试网Xu[VBv

这七个函数提供了数据库函数库的接口。接下来介绍实现。

m"Vf7b7]+wdV0

 51Testing软件测试网+E7CO4i,w

16.4实现概述51Testing软件测试网%O&L { [1e G1~~

  大多数数据库访问的函数库使用两个文件来存储信息:一个索引文件和一个数据文件。索引文件包括索引值(关键字)和一个指向数据文件中对应数据记录的指针。有许多技术可用来组织索引文件以提高按关键字查询的速度和效率,散列表和B+树是两种常用的技术。我们采用固定大小的散列表来组织索引文件结构,并采用链表法解决散列冲突。51Testing软件测试网!a8q)]5Ih.l)KO*m3]b

  16-1是数据库实现的基本结构。索引文件由三部分组成:空闲链表指针、散列表和索引记录。51Testing软件测试网;z-[f&Zu(U_

 51Testing软件测试网g3} IP2j

16.5集中式或非集中式

*g1ASM;ez4SY0

   当有多个进程访问数据库时,有两种方法可实现库函数:

?CB[kl0

   (1)集中式由一个进程作为数据库管理者,所有的数据库访问工作由此进程完成。库函数通过IPC机制与此中心进程进行联系。

Vd#j0~Z-xX&g1a0

   (2)非集中式每个库函数独立申请并发控制(加锁),然后调用它自己的I/O函数。51Testing软件测试网6_L-J f5i0k

使用这两种技术的数据库都有。UNIX系统中的潮流是使用非集中式方法。如果有适当的加锁函数,因为避免使用了IPC,那么非集中式方法一般要快一些。图16-2描绘了集中式方法的操作。51Testing软件测试网 W]._PG B

集中式的优点是能够根据需要来对操作模式进行控制。51Testing软件测试网+T_m{qI

16-3描绘了非集中式方法,本章的实现就是采用这种方法。使用库函数访问数据库的用户进程是平等的,它们通过使用记录锁机制来实现并发控制。51Testing软件测试网 C:c m7DMN&Y

 

_vl b:mX0

16.6并发

9h4[9s O1xt5e3E0

由于很多系统的实现都采用两个文件(一个索引文件和一个数据文件)的方法,所以我们也使用这种方法,这要求我们能够控制对两个文件的加锁。有很多方法可用来对两个文件进行加锁。51Testing软件测试网$KUZ%f3^m u6k&V,n

16.6.1粗锁51Testing软件测试网M&j*l{P"jI"sH

最简单的加锁方法是将这两个文件中的一个作为锁,并要求调用者在对数据库进行操作前必须获得这个锁。我们将这称为粗锁(coarse locking)。51Testing软件测试网h/K ~n;N

粗锁的问题是它限制了最大程度的并发。用粗锁时,当一个进程向一条散列链中加一条记录时,其他进程无法访问另一条散列链上的记录。

.x/K5MH'm"c%h0

16.6.2细锁51Testing软件测试网Fyr-W&qT3?

   下面用称为细锁(fine locking)的方法来加强粗锁以提高并发度。我们要求一个读进程或写进程在操作一条记录前必须先获得此记录所在散列链的读锁或写锁。允许对一条散列链同时可以有多个读进程,而只能有一个写进程。

h&g o3[IisH8w0

16.7源码51Testing软件测试网F X-ZQ/iQX C

 

0Wv~$hwe(S0

16.8性能51Testing软件测试网 tJ!w9F_/h

16.8.1单进程的结果51Testing软件测试网4BQP E PF \

16.8.2多进程的结果

4@XI6jgn4pt1r0

 

Mvy%p f0

TAG:

 

评分:0

我来说两句

Open Toolbar