发信人: liangvy() 
整理人: hahalee(1999-06-29 12:02:55), 站内信件
 | 
 
 
[ Lenn<[email protected]>版权所有,不得书面出版 ]
  2。4进程通信     (socket和network interface)
          网络协议和路由选择的过程中,为选择合适的网络接口,一般进程没必要对 网络接口进行明确指示。所以,网络卡就不和文件系统的名字对应,而是在核心内部 的struct ifnet(@net/if.h)进行对应。用命令ifconfig和netstat -i就可以看到各个 网卡的struct ifnet的参数。         unix中,进程通信和网络介入的通信的场合,使用network interface。进行 通信的进程,根据socket()的系统调用,把socket作为通信手段。这个时候,需要指 定协议族,通信类型,具体的协议等。综合起来,有如下的参数:
  int socket( int domain,         //protocal family             int type,           //通信形式             int protocal        //具体的协议           )
  根据protocal family可以推算出可以通信的范围,同时,可以控制通信类型和具体的 协议。通信类型有如下的四个种类。
  .SOCK_STREAM         基于连接的传输,具有可靠性,可以保证通信的发送接收顺序的双向通信路。     但不限制数据的传输顺序的紧急数据发送情况也有可能。发送数据和接受数据的     的间隔不一定。比如一次发送10个byte,可能一次接受完毕,但发送100个byte,     可能一次接受完毕,也可能分两次接收。
  .SOCK_DREAM         可靠性比较低。不是基于连接传输。每次的发送数据长度是有限制的。
  .SOCK_SEQPACKET         基于连接的传输,具有可靠性,可以保证通信的发送接收顺序的双向通信路。     和.SOCK_STREAM不同的地方是,发送数据和接受数据的间隔一定,每次的发送长度     也是限制的。
  .SOCK_RAW         核心内部的network protocal和interface的控制中使用。
          通信类型受制于具体的协议。freebsd协议族有如下的一些: --------------------------------------------------------------------------- 协议族                  通信类型                定义模块 PF_ROUTE                SOCK_RAW                net/rtsock.c PF_APPLETALK            SOCK_DGRAM              netatalk/at_proto.c PF_INET                 SOCK_DGRAM              netinet/in_proto.c                         SOCK_STREAM                         SOCK_RAW PF_IPX                  SOCK_DRAM               netipx/ipx_proto.c                         SOCK_STREAM                         SOCK_SEQACKET                         SOCK_RAW PF_KEY                  SOCK_RAW                netkey/key.c PF_NS                   SOCK_DGRAM              netns/ns_proto.c                         SOCK_STREAM                         SOCK_SEQACKET                         SOCK_RAW PF_LOCAL                SOCK_STREAM             kern/uipc_proto.c                         SOCK_DGRAM --------------------------------------------------------------------------
  这些协议族由各个struct domain里定义。在这里面,当前的协议族里可能利用的通信 类型可以在struct protosw里找到。protocal family的登记可以把宏DOMAIN_SET()设 定的信息通过函数domaininit()(@kern/uipc_domain.c)读到kernel的初始化中。
          由系统调用socket()取得的socket,在进程里可以象文件柄一样的进行操作。 适当的设置后,可以使用read()/write()调用。由open()取得的文件柄对应read()/ write()/ioctl()/select()/close()处理可以使用vn_read()/vn_write()/vn_ioctl() /vn_select()/vn_close()进行相应替换,对socket的处理则是soo_read()/soo_write ()/soo)ioctl()/soo_select()/soo_close()(@kern/sys_socket.c)进行取代。对应于 socket的struct protosw的子过程则在任何地方都可以进行处理。还有可以用send() /sendto()/sendmsg()进行发送,recv()/resvfrom()/recvmsg()进行接收。
          socket是绑定在通信路上的,所以,如果不规定通信对象的端子,就不能进行 实际的通信操作。也就是说,必须指定对象和自己的socket的地址。这个和protocal  family不大一样,它由struct sockaddr_XXX指定。但是对socket指定地址的系统调用 对每个socket family并没有统一性,系统调用层次的地址在struct sockaddr(@sys/ socket.h)里面包含。这样,就可以区别它的成员sa_family里各个 struct sockaddr_XXX 了。         s = socket(PF_INET,SOCK_DGRAM,0)取得的socket由band()进行address的设 定后,         sendto(s,msg,mlen,sockaddr_to,tolen)         里的 message msg向sockaddr_to的地址送去,kernel内则顺序进行如下的操 作处理。
          1.系统调用sendto()的处理过程sendto()(@kern/uipc_syscalls.c)就是,得     到参数后在调用sendit()(@kern/uipc_syscalls.c).         2.sendit()先从参数得到发送的地址,再调用sosend()     (@kern/uipc_socket.c).         3.sosend()从struct uio取得发送数据,然后向struct mbuf变换。建立socket     时候所指定address family/protocal的处理过程把     so_proto->pr_usrreqs->pru_send调出来。在这里调用了udp_userreq()(@netinet/     udp_usrreq.c)。         4.udp_usrreq()是PRU_SEND处理,它调用了udp_output()。         5.udp_output是UDP包的分组变换,它调用ip_output()(@netinet/ip_output)。         6.ip_output()的功能是从发送ip地址开始,选择network interface的子过程。     如果是ethernet,则调用ether_output()(@net/if_ethersubr.c)。还有IP firewall     的处理也在这里进行。         7.ether_output()则由发送ip地址取得ethernet的地址。进行ethernet打包,     调用在network interface里设定的子过程if_start。再对network card进行io。
  (下章开始介绍如何编写驱动程序) Lenn <[email protected]>
  --
  Lenn  Tel:    0755-3913403(H) E-mail: [email protected] Oicq: Lenn 28663
  ※ 来源:.网易 BBS bbs.netease.com.[FROM: www2.dt.sanyo.co.jp]
  | 
 
 
 |