/********************************************************************************************************* ** 函数名称: aio_suspend ** 功能描述: 等待指定的一个或多个异步 I/O 请求操作完成 ** 输 入 : list aio 请求控制块数组 (如果其中有 NULL, 程序将忽略) ** nent 数组元素个数 ** timeout 超时时间 ** 输 出 : ERROR or OK ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API int aio_suspend (const struct aiocb * const list[], int nent, const struct timespec *timeout) { AIO_WAIT_CHAIN *paiowc; struct aiowait *paiowait; ULONG ulTimeout; BOOL bNeedWait = LW_FALSE; int iWait = 0; /* paiowait 下标 */ int iCnt; /* list 下标 */ int iRet = ERROR_NONE; #ifdef __SYLIXOS_KERNEL if (__PROC_GET_PID_CUR() != 0) { /* 需要使用外部库提供的 aio */ errno = ENOSYS; return (PX_ERROR); } #endif /* __SYLIXOS_KERNEL */ __THREAD_CANCEL_POINT(); /* 测试取消点 */ if ((nent <= 0) || (list == LW_NULL)) { errno = EINVAL; return (PX_ERROR); } if (timeout == LW_NULL) { /* 永久等待 */ ulTimeout = LW_OPTION_WAIT_INFINITE; } else { ulTimeout = __timespecToTick(timeout); } paiowc = __aioCreateWaitChain(nent, LW_TRUE); /* 创建等待队列 */ if (paiowc == LW_NULL) { errno = ENOMEM; /* should be EAGAIN ? */ return (PX_ERROR); } paiowait = paiowc->aiowc_paiowait; API_SemaphoreMPend(_G_aioqueue.aioq_mutex, LW_OPTION_WAIT_INFINITE); for (iCnt = 0; iCnt < nent; iCnt++) { if (list[iCnt]) { if (list[iCnt]->aio_req.aioreq_error == EINPROGRESS) { /* 必须为正在处理状态 */ paiowait[iWait].aiowt_pcond = &paiowc->aiowc_cond; paiowait[iWait].aiowt_pcnt = LW_NULL; paiowait[iWait].aiowt_psigevent = LW_NULL; paiowait[iWait].aiowt_paiowc = LW_NULL; /* 不需要代理线程释放 */ iRet = __aioAttachWait(list[iCnt], &paiowait[iWait]); if (iRet != ERROR_NONE) { errno = EINVAL; break; } _List_Line_Add_Tail(&paiowait[iWait].aiowt_line, &paiowc->aiowc_pline); /* 加入 wait 链表 */ iWait++; bNeedWait = LW_TRUE; /* 有 wait 链表节点连接, */ } else { break; } } } if (iRet != ERROR_NONE) { /* __aioAttachWait 失败 */ __aioDeleteWaitChain(paiowc); API_SemaphoreMPost(_G_aioqueue.aioq_mutex); errno = EINVAL; return (PX_ERROR); } if ((iCnt == nent) && bNeedWait) { /* 是否需要等待 */ API_ThreadCleanupPush(__aioWaitCleanup, paiowc); iRet = (INT)API_ThreadCondWait(&paiowc->aiowc_cond, _G_aioqueue.aioq_mutex, ulTimeout); API_ThreadCleanupPop(LW_FALSE); /* 这里已经锁定 _G_aioqueue */ /* 不能运行 __aioWaitCleanup */ __aioDeleteWaitChain(paiowc); if (iRet != ERROR_NONE) { API_SemaphoreMPost(_G_aioqueue.aioq_mutex); errno = EAGAIN; return (PX_ERROR); } } else { /* 不需要等待 */ __aioDeleteWaitChain(paiowc); } API_SemaphoreMPost(_G_aioqueue.aioq_mutex); return (iRet); }
/********************************************************************************************************* ** 函数名称: __tshellFsCmdXmodems ** 功能描述: 系统命令 "xmodems" ** 输 入 : iArgC 参数个数 ** ppcArgV 参数表 ** 输 出 : 0 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT __tshellFsCmdXmodems (INT iArgC, PCHAR ppcArgV[]) { INT i; INT j; BOOL bIsEot = LW_FALSE; BOOL bStart = LW_FALSE; INT iFile; INT iRetVal; UCHAR ucRead; UCHAR ucTemp[__LW_XMODEM_PACKET_LEN] = {__LW_XMODEM_SOH}; UCHAR ucSeq = 1; UCHAR ucChkSum; ssize_t sstRecvNum; ssize_t sstReadNum; fd_set fdsetRead; struct timeval timevalTO = {__LW_XMODEM_TIMEOUT, 0}; if (iArgC != 2) { fprintf(stderr, "argments error!\n"); return (-ERROR_TSHELL_EPARAM); } iFile = open(ppcArgV[1], O_RDONLY); if (iFile < 0) { fprintf(stderr, "can not open source file!\n"); return (-ERROR_TSHELL_EPARAM); } API_ThreadCleanupPush(__tshellXmodemCleanup, (PVOID)iFile); /* 加入清除函数 */ ioctl(STD_IN, FIOSETOPTIONS, OPT_RAW); /* 将标准文件改为 raw 模式 */ ioctl(STD_OUT, FIOSETOPTIONS, OPT_RAW); /* 将标准文件改为 raw 模式 */ /* * 构建第一个数据包 */ sstReadNum = read(iFile, &ucTemp[3], __LW_XMODEM_DATA_LEN); if (sstReadNum <= 0) { __LW_XMODEM_SEND_CMD(__LW_XMODEM_EOT); /* 传输结束 */ API_ThreadCleanupPop(LW_TRUE); printf("0 bytes read from source file!\n"); return (-ERROR_TSHELL_EPARAM); } for (j = (INT)sstReadNum; j < __LW_XMODEM_DATA_LEN; j++) { /* 补全数据 */ ucTemp[j + 3] = __LW_XMODEM_PAD; } ucTemp[1] = (UCHAR)(ucSeq); /* 序列号 */ ucTemp[2] = (UCHAR)(~ucSeq); ucChkSum = 0; for (j = 3; j < (__LW_XMODEM_DATA_LEN + 3); j++) { ucChkSum = (UCHAR)(ucChkSum + ucTemp[j]); /* 计算校验和 */ } ucTemp[__LW_XMODEM_DATA_LEN + 3] = ucChkSum; /* * 开始循环发送文件 */ FD_ZERO(&fdsetRead); /* * 超时次数默认为 30 次 */ for (i = 0; i < 30; i++) { FD_SET(STD_IN, &fdsetRead); iRetVal = select(1, &fdsetRead, LW_NULL, LW_NULL, &timevalTO); /* 等待可读 */ if (iRetVal != 1) { if (bIsEot) { if (bStart) { write(STD_OUT, ucTemp, __LW_XMODEM_PACKET_LEN); /* 重发数据 */ } } else { __LW_XMODEM_SEND_CMD(__LW_XMODEM_EOT); /* 重新结束 */ } continue; /* 接收超时 */ } i = 0; /* 重置超时次数 */ sstRecvNum = read(STD_IN, &ucRead, 1); if (sstRecvNum <= 0) { API_ThreadCleanupPop(LW_TRUE); fprintf(stderr, "standard in device error!\n"); return (PX_ERROR); } if (ucRead == __LW_XMODEM_CAN) { /* 接收结束 */ break; } else if (ucRead == __LW_XMODEM_NAK) { /* 需要重发 */ write(STD_OUT, ucTemp, __LW_XMODEM_PACKET_LEN); bStart = LW_TRUE; } else if (ucRead == __LW_XMODEM_ACK) { ucSeq++; if (ucSeq > 255) { ucSeq = 1; } bStart = LW_TRUE; if (bIsEot) { break; /* 发送结束 */ } else { sstReadNum = read(iFile, &ucTemp[3], __LW_XMODEM_DATA_LEN); if (sstReadNum <= 0) { bIsEot = LW_TRUE; __LW_XMODEM_SEND_CMD(__LW_XMODEM_EOT); /* 发送结束 */ } else { /* * 补全数据 */ for (j = (INT)sstReadNum; j < __LW_XMODEM_DATA_LEN; j++) { ucTemp[j + 3] = __LW_XMODEM_PAD; } ucTemp[1] = (UCHAR)(ucSeq); /* 序列号 */ ucTemp[2] = (UCHAR)(~ucSeq); ucChkSum = 0; for (j = 3; j < (__LW_XMODEM_DATA_LEN + 3); j++) { ucChkSum = (UCHAR)(ucChkSum + ucTemp[j]); /* 计算校验和 */ } ucTemp[__LW_XMODEM_DATA_LEN + 3] = ucChkSum; write(STD_OUT, ucTemp, __LW_XMODEM_PACKET_LEN); /* 发送数据 */ } } } } API_ThreadCleanupPop(LW_TRUE); return (ERROR_NONE); }
/********************************************************************************************************* ** 函数名称: API_INetPing6 ** 功能描述: internet ipv6 ping ** 输 入 : pinaddr 目标 ip 地址. ** iTimes 次数 ** iDataSize 数据大小 ** iTimeout 超时时间 ** pcNetif 网络接口名 (NULL 表示自动确定接口) ** 输 出 : ERROR ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API INT API_INetPing6 (struct in6_addr *pin6addr, INT iTimes, INT iDataSize, INT iTimeout, CPCHAR pcNetif) { CHAR cInetAddr[INET6_ADDRSTRLEN]; /* IP 地址缓存 */ REGISTER INT iSock; INT i; UINT16 usSeqRecv = 0; ULONG ulTime1; ULONG ulTime2; INT iSuc = 0; INT iHLRecv; struct sockaddr_in6 sockaddrin6To; REGISTER ULONG ulTimeMax = 0; REGISTER ULONG ulTimeMin = 0xFFFFFFFF; REGISTER ULONG ulTimeAvr = 0; if ((iDataSize >= (64 * LW_CFG_KB_SIZE)) || (iDataSize < 0)) { /* 0 - 64KB */ _ErrorHandle(EINVAL); return (PX_ERROR); } sockaddrin6To.sin6_len = sizeof(struct sockaddr_in6); sockaddrin6To.sin6_family = AF_INET6; sockaddrin6To.sin6_addr = *pin6addr; iSock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); /* 必须原子运行到 push */ if (iSock < 0) { return (PX_ERROR); } API_ThreadCleanupPush(__inetPing6Cleanup, (PVOID)iSock); /* 加入清除函数 */ setsockopt(iSock, SOL_SOCKET, SO_RCVTIMEO, &iTimeout, sizeof(INT)); connect(iSock, (struct sockaddr *)&sockaddrin6To, sizeof(struct sockaddr_in6)); /* 设定目标 */ printf("Pinging %s\n\n", inet6_ntoa_r(*pin6addr, cInetAddr, sizeof(cInetAddr))); for (i = 0; ;) { if (__inetPing6Send(iSock, pin6addr, iDataSize, pcNetif, &usSeqRecv) < 0) { /* 发送 icmp 数据包 */ fprintf(stderr, "error : %s.\n", lib_strerror(errno)); i++; if (i >= iTimes) { break; } API_TimeSSleep(1); /* 等待 1 S */ continue; } else { i++; /* 发送次数 ++ */ } ulTime1 = API_TimeGet(); if (__inetPing6Recv(iSock, usSeqRecv, &iHLRecv) < 0) { /* 接收 icmp 数据包 */ printf("Request time out.\n"); /* timeout */ if (i >= iTimes) { break; /* ping 结束 */ } } else { ulTime2 = API_TimeGet(); ulTime2 = (ulTime2 >= ulTime1) ? (ulTime2 - ulTime1) : ((__ARCH_ULONG_MAX - ulTime1) + ulTime2 + 1); ulTime2 = ((ulTime2 * 1000) / LW_TICK_HZ); /* 转为毫秒数 */ printf("Reply from %s: bytes=%d time=%ldms hoplim=%d\n", inet6_ntoa_r(*pin6addr, cInetAddr, sizeof(cInetAddr)), iDataSize, ulTime2, iHLRecv); iSuc++; ulTimeAvr += ulTime2; ulTimeMax = (ulTimeMax > ulTime2) ? ulTimeMax : ulTime2; ulTimeMin = (ulTimeMin < ulTime2) ? ulTimeMin : ulTime2; if (i >= iTimes) { break; /* ping 结束 */ } else { API_TimeSSleep(1); /* 等待 1 S */ } } } API_ThreadCleanupPop(LW_TRUE); /* ping 清除 */ /* * 打印总结信息 */ printf("\nPing statistics for %s:\n", inet6_ntoa_r(*pin6addr, cInetAddr, sizeof(cInetAddr))); printf(" Packets: Send = %d, Received = %d, Lost = %d(%d%% loss),\n", iTimes, iSuc, (iTimes - iSuc), (((iTimes - iSuc) * 100) / iTimes)); if (iSuc == 0) { /* 没有一次成功 */ return (PX_ERROR); } ulTimeAvr = ulTimeAvr / iSuc; printf("Approximate round trip times in milli-seconds:\n"); printf(" Minimum = %ldms, Maximum = %ldms, Average = %ldms\r\n\r\n", ulTimeMin, ulTimeMax, ulTimeAvr); return (ERROR_NONE); }
/********************************************************************************************************* ** 函数名称: __tshellFsCmdXmodemr ** 功能描述: 系统命令 "xmodemr" ** 输 入 : iArgC 参数个数 ** ppcArgV 参数表 ** 输 出 : 0 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT __tshellFsCmdXmodemr (INT iArgC, PCHAR ppcArgV[]) { INT i; INT j; INT iFile; INT iRetVal; UCHAR ucTemp[__LW_XMODEM_PACKET_LEN]; UCHAR ucSeq = 1; UCHAR ucChkSum; ssize_t sstRecvNum; ssize_t sstWriteNum; size_t stTotalNum = 0; fd_set fdsetRead; struct timeval timevalTO = {__LW_XMODEM_TIMEOUT, 0}; if (iArgC != 2) { fprintf(stderr, "argments error!\n"); return (-ERROR_TSHELL_EPARAM); } /* * 检测文件是否存在 */ iFile = open(ppcArgV[1], O_RDONLY); if (iFile >= 0) { close(iFile); /* 关闭文件 */ __re_select: printf("destination file is exist, overwrite? (Y/N)\n"); read(0, ucTemp, __LW_XMODEM_DATA_LEN); if ((ucTemp[0] == 'N') || (ucTemp[0] == 'n')) { /* 不覆盖 */ return (ERROR_NONE); } else if ((ucTemp[0] != 'Y') && (ucTemp[0] != 'y')) { /* 选择错误 */ goto __re_select; } } iFile = open(ppcArgV[1], (O_WRONLY | O_CREAT | O_TRUNC), 0666); /* 创建文件 */ if (iFile < 0) { fprintf(stderr, "can not open destination file!\n"); return (-ERROR_TSHELL_EPARAM); } API_ThreadCleanupPush(__tshellXmodemCleanup, (PVOID)iFile); /* 加入清除函数 */ ioctl(STD_IN, FIOSETOPTIONS, OPT_RAW); /* 将标准文件改为 raw 模式 */ ioctl(STD_OUT, FIOSETOPTIONS, OPT_RAW); /* 将标准文件改为 raw 模式 */ __LW_XMODEM_SEND_CMD(__LW_XMODEM_NAK); /* 启动接收 */ FD_ZERO(&fdsetRead); /* * 超时次数默认为 20 次 */ for (i = 0; i < 20; i++) { FD_SET(STD_IN, &fdsetRead); iRetVal = select(1, &fdsetRead, LW_NULL, LW_NULL, &timevalTO); /* 等待可读 */ if (iRetVal != 1) { stTotalNum = 0; /* 清除已接收的数据 */ __LW_XMODEM_SEND_CMD(__LW_XMODEM_NAK); /* 重新请求接收数据包 */ continue; /* 接收超时 */ } i = 0; /* 重置超时次数 */ sstRecvNum = read(STD_IN, &ucTemp[stTotalNum], __LW_XMODEM_PACKET_LEN - stTotalNum); if (sstRecvNum <= 0) { API_ThreadCleanupPop(LW_TRUE); fprintf(stderr, "standard in device error!\n"); return (PX_ERROR); } if (ucTemp[0] == __LW_XMODEM_EOT) { /* 接收结束 */ __LW_XMODEM_SEND_CMD(__LW_XMODEM_ACK); break; } stTotalNum += (size_t)sstRecvNum; if (stTotalNum < __LW_XMODEM_PACKET_LEN) { /* 数据包不完整 */ continue; } else { stTotalNum = 0; /* 已经接到一个完整的数据包 */ } /* * 开始判断数据包正确性 */ if (ucTemp[1] != ucSeq) { /* 序列号是否错误 */ if (ucTemp[1] == (ucSeq - 1)) { __LW_XMODEM_SEND_CMD(__LW_XMODEM_ACK); /* 需要下一包数据 */ } else { __LW_XMODEM_SEND_CMD(__LW_XMODEM_CAN); /* 结束通信 */ API_ThreadCleanupPop(LW_TRUE); fprintf(stderr, "sequence number error!\n"); return (PX_ERROR); } continue; } if (~ucTemp[1] == ucTemp[2]) { /* 序列号校验错误 */ __LW_XMODEM_SEND_CMD(__LW_XMODEM_NAK); continue; } ucChkSum = 0; for (j = 3; j < (__LW_XMODEM_DATA_LEN + 3); j++) { ucChkSum = (UCHAR)(ucChkSum + ucTemp[j]); /* 计算校验和 */ } if (ucTemp[__LW_XMODEM_DATA_LEN + 3] != ucChkSum) { /* 校验错误 */ __LW_XMODEM_SEND_CMD(__LW_XMODEM_NAK); continue; } /* * 将数据写入目标文件 */ sstWriteNum = write(iFile, &ucTemp[3], __LW_XMODEM_DATA_LEN); if (sstWriteNum != __LW_XMODEM_DATA_LEN) { INT iErrNo = errno; __LW_XMODEM_SEND_CMD(__LW_XMODEM_CAN); /* 结束通信 */ API_ThreadCleanupPop(LW_TRUE); fprintf(stderr, "write file error %s!\n", lib_strerror(iErrNo)); return (PX_ERROR); } ucSeq++; __LW_XMODEM_SEND_CMD(__LW_XMODEM_ACK); /* 需要下一包数据 */ } API_ThreadCleanupPop(LW_TRUE); return (ERROR_NONE); }