限于篇幅,本文将主要讨论在同一计算机下的socket进程间通信
从概念上说,socket和管道没多大区别。但是从实现上来说,管道传递的是无结构的字节流,但是socket传递的是报文。
与V IPC相同,内核为socket设置的总入口为sys_socketcall()
sys_socketcall(int call, unsigned long *args)
之后会像V IPC一样检查所给的宏,然后调用相应的函数。
socket编程分为两种,一种是有连接的(带入TCP),一种是没有连接的(带入UDP)。这两者拥有的数据结构是不一样的,同时两者所调用的函数也是不一样的,为方便计,系统给出了同样的调用端口,下文将会详细说明。
创建套接字socket()
它的底层是sys_socket(),这个函数比较简单,主要是调用了两个函数,一个是create_socket创建套接字,还有一个是sock_map_fd()建立映射。
调用函数create_socket()创建了socket结构体并且分配了数据结构和inode结构,最后映射到文件里。这是属于特殊文件sockfs的文件,初始化的时候会调用函数安装这个文件系统。处理好了socket数据结构还要再创建创建一个sock数据结构。可能会有一些不理解:为什么还要弄一个sock结构?socket数据结构对应着特俗文件系统sockfs的文件,inode的有一个联合体,记录着20多种不同的文件系统。由于是联合体,对于空间来说就有一定限制,sock数据结构就是为了完善socket数据结构的,两者是一一对应的关系。sock结构是内核中经常要动态分配使用的,所以有一个全局的队列,通过slab机制来管理它的缓冲区。所以还要把sock挂到队列里。在创建sock的时候还规定了读写的缓冲区,默认是64k。
接下来调用函数sock_map_fd(),分配一个空闲的file并且确定了打开文件号fid,接下来分配了一个dentry指向inode,file的f_dentry