[LWIP学习]--SylixOS AF_UNIX socket套接字分析
2017-09-04 14:46
381 查看
UNIX 域套接字是一种高级的 IPC 机制,这种形式的 IPC 可以在同一计算机系统上运行的两个进程之间进行通信。虽然因特网域套接字可用于同一目的,但 UNIX 域套接字的效率更高。 UNIX 域套接字仅仅复制数据,并不执行协议处理,因此,无需添加或者删除网络报头,无需计算校验和,无需产生序列号,无需发送确认报文等。
SylixOS 中的 UNIX 域套接字提供流( SOCK_STREAM)、数据报( SOCK_DGRAM)和连续数据报( SOCK_SEQPACKET)三种接口。
UNIX 域数据报服务是可靠的,既不会丢失报文也不会传递出错。 UNIX 域套接字就像是套接字和管道的混合,可以使用它们面向网络的域套接字接口或者使用 socketpair 函数来创建一对无命名的、相互连接的UNIX 域套接字。
下面分析一下UNIX 域套接字的源码。
1.首先分析socket函数:
socket函数中首先会对参数进行分析,UNIX套接字指支持AF_UNIX、SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET等参数。
确认传入的参数无误后,创建af_unix控制块(其中创建了各自的二进制信号量),最后将af_unix控制块加入全局_G_plineAfUnix链表。(所有创建的UNIX 域套接字控制块都在该链表中)
2.接着分析一下bind函数。因为应用于IPC,所以UNIX 域套接字不需要IP和端口,取而代之的是文件路径来表示“网络地址”。
在bind函数中会检索各个节点的文件路径,若文件路径已存在,bind失败。
3.UNIX 域套接字发送函数。
通过__AF_UNIX_WWRITE宏,阻塞等待二进制信号量,直到读端执行__unixUpdateWriter函数。
4.UNIX 域套接字接收函数
通过__AF_UNIX_WREAD宏,阻塞等待二进制信号量,直到写端执行__unixUpdateReader函数。
SylixOS 中的 UNIX 域套接字提供流( SOCK_STREAM)、数据报( SOCK_DGRAM)和连续数据报( SOCK_SEQPACKET)三种接口。
UNIX 域数据报服务是可靠的,既不会丢失报文也不会传递出错。 UNIX 域套接字就像是套接字和管道的混合,可以使用它们面向网络的域套接字接口或者使用 socketpair 函数来创建一对无命名的、相互连接的UNIX 域套接字。
下面分析一下UNIX 域套接字的源码。
1.首先分析socket函数:
socket函数中首先会对参数进行分析,UNIX套接字指支持AF_UNIX、SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET等参数。
AF_UNIX_T *unix_socket (INT iDomain, INT iType, INT iProtocol) { if (iDomain != AF_UNIX) { return (LW_NULL); } if ((iType != SOCK_STREAM) && (iType != SOCK_DGRAM) && (iType != SOCK_SEQPACKET)) { return (LW_NULL); } pafunix = __unixCreate(iType); if (pafunix == LW_NULL) { _ErrorHandle(ENOMEM); } ... }
确认传入的参数无误后,创建af_unix控制块(其中创建了各自的二进制信号量),最后将af_unix控制块加入全局_G_plineAfUnix链表。(所有创建的UNIX 域套接字控制块都在该链表中)
static AF_UNIX_T *__unixCreate (INT iType) { ... pafunix = (AF_UNIX_T *)__SHEAP_ALLOC(sizeof(AF_UNIX_T)); ... pafunix->UNIX_hCanRead = API_SemaphoreBCreate("unix_rlock", LW_FALSE, LW_OPTION_OBJECT_GLOBAL, LW_NULL); ... _List_Line_Add_Ahead(&pafunix->UNIX_lineManage, &_G_plineAfUnix); ... }
2.接着分析一下bind函数。因为应用于IPC,所以UNIX 域套接字不需要IP和端口,取而代之的是文件路径来表示“网络地址”。
在bind函数中会检索各个节点的文件路径,若文件路径已存在,bind失败。
INT unix_bind (AF_UNIX_T *pafunix, const struct sockaddr *name, socklen_t namelen) { ... lib_strncpy(cPath, paddrun->sun_path, iPathLen); ... /* 创建 socket 文件 */ iFd = open(cPath, O_CREAT | O_RDWR, __AF_UNIX_DEF_FLAG | S_IFSOCK); .... /* 获得完整路径 */ API_IosFdGetName(iFd, cPath, MAX_FILENAME_LENGTH); ... /* 查询各节点是否存在该路径 */ pafunixFind = __unixFind(cPath, iSockType, (iSockType == SOCK_DGRAM) ? LW_FALSE : LW_TRUE); ... /* 若路径不存在,添加 */ lib_strcpy(pafunix->UNIX_cFile, cPath); ... close(iFd); }
3.UNIX 域套接字发送函数。
通过__AF_UNIX_WWRITE宏,阻塞等待二进制信号量,直到读端执行__unixUpdateWriter函数。
static ssize_t unix_sendto2 (AF_UNIX_T *pafunix, const void *data, size_t size, const void *data_ex, socklen_t size_ex, int flags, const struct sockaddr *to, socklen_t tolen) { ... INT i = 0; /* 总发送次数 */ UINT uiTimes = size >> __AF_UNIX_PIPE_BUF_SHIFT;/* 循环次数 */ UINT uiLeft = size & (__AF_UNIX_PIPE_BUF - 1); /* 最后一次数量 */ ... do { ... __try_send: if (__unixCanWrite(pafunixRecver)) { /* 可以发送 */ if (i < uiTimes) { /* 可以发送 */ sstWriteNum = __unixSendtoMsg(pafunix, pafunixRecver, pcSendMem, __AF_UNIX_PIPE_BUF, data_ex, size_ex, flags); ... i++; /* 发送次数++ */ bNeedUpdateReader = LW_TRUE; /* 需要通知读端 */ goto __try_send; /* 重新尝试发送数据 */ } else { /* 最后一次发送 */ sstWriteNum = __unixSendtoMsg(pafunix, pafunixRecver, pcSendMem, uiLeft, data_ex, size_ex, flags); ... break; /* 发送完毕 */ } } if (bNeedUpdateReader) { bNeedUpdateReader = LW_FALSE; __unixUpdateReader(pafunixRecver, ERROR_NONE); /* update remote reader */ } ... ulError = __AF_UNIX_WWRITE(pafunixRecver); /* 等待可写 */ ... } while (1); if (bNeedUpdateReader) { __unixUpdateReader(pafunixRecver, ERROR_NONE); /* update remote reader */ } ... }
4.UNIX 域套接字接收函数
通过__AF_UNIX_WREAD宏,阻塞等待二进制信号量,直到写端执行__unixUpdateReader函数。
static ssize_t unix_recvfrom2 (AF_UNIX_T *pafunix, void *mem, size_t len, void *mem_ex, socklen_t *plen_ex, int flags, struct sockaddr *from, socklen_t *fromlen) { ... do { ... if (__unixCanRead(pafunix, flags, len)) { /* 可以接收 */ __recv_more: /* 从缓冲区取一个消息 */ sstReadNum = __unixRecvfromMsg(pafunix, (PVOID)pcRecvMem, (size_t)(len - sstTotal), mem_ex, plen_ex, flags, (struct sockaddr_un *)from, fromlen); pcRecvMem += sstReadNum; sstTotal += sstReadNum; ... break; /* 跳出接收循环 */ } else if ((__AF_UNIX_TYPE(pafunix) == SOCK_STREAM) || (__AF_UNIX_TYPE(pafunix) == SOCK_SEQPACKET)) { return (PX_ERROR); } ... ulError = __AF_UNIX_WREAD(pafunix); /* 等待数据 */ } while (1); ... __unixUpdateWriter(pafunix, ERROR_NONE); /* update writer */ ... }
相关文章推荐
- [LWIP学习]--SylixOS AF_PACKET socket套接字分析
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 非阻塞的Socket通信Poll模型(多路复用), 实用Socket通信模板
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 非阻塞的Socket通信EPoll模型(多路复用), 实用Socket通信模板
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 简单TCP Socket 通信
- [LWIP学习]--LWIP网络通信流程(物理层,链路层,网络层,传输层,socket套接字,应用层通信流程汇总)
- UNIX环境编程--------原始套接字学习笔记-----Linux原始套接字实现分析
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 简单UDP Socket 通信
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 非阻塞的Socket通信Select模型(多路复用), 实用Socket通信模板。
- unix环境编程学习笔记---------套接字------socket------客户端
- ndk学习16: unix domain socket
- Linux网络编程之socket:unix域套接字编程与socketpair函数
- UC_SOCKET套接字学习小结
- LWIP socket层与协议栈层交互过程分析
- 黑马程序员<.net学习---Socket套接字>
- LWIP UDP socket编程 可以指定本地端口号及发送长度不能太长问题分析
- QT类学习系列(4)- 01*-对QUdpSocket中的过程分析
- unix学习笔记------套接字-----王保明老师的笔记
- linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数
- UNIX域套接字——UNIX domain socket(DGRAM)
- Unix域套接字(Unix Domain Socket)介绍