* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*
* The code snippet comes from Ascend project
*
* Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef __linux
#ifndef _MMPA_API_H_
#define _MMPA_API_H_
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifdef FUNC_VISIBILITY
#define MMPA_FUNC_VISIBILITY __attribute__((visibility("default")))
#else
#define MMPA_FUNC_VISIBILITY
#endif
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <signal.h>
#include <pthread.h>
#include <dirent.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <net/if.h>
#include <limits.h>
#include <stddef.h>
#include <dirent.h>
#include <linux/fs.h>
#include <linux/limits.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/shm.h>
#include <sys/un.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include "securec.h"
#include "mmpa_typedef_linux.h"
#include "mmpa_linux.h"
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define MMPA_CPUINFO_DEFAULT_SIZE 64
#define MMPA_CPUINFO_DOUBLE_SIZE 128
#define MMPA_CPUPROC_BUF_SIZE 256
#define MMPA_MAX_IF_SIZE 2048
#define MMPA_SECOND_TO_MSEC 1000
#define MMPA_MSEC_TO_USEC 1000
#define MMPA_MSEC_TO_NSEC 1000000
#define MMPA_SECOND_TO_NSEC 1000000000
#define MMPA_MAX_SLEEP_MILLSECOND_USING_USLEEP 1000
#define MMPA_MAX_SLEEP_MICROSECOND_USING_USLEEP 1000000
#define MMPA_MAX_PHYSICALCPU_COUNT 4096
#define MMPA_MIN_PHYSICALCPU_COUNT 1
#define ERRNO_MIN (-255)
struct CpuTypeTable {
char *key;
char *value;
};
enum {
MMPA_MAC_ADDR_FIRST_BYTE = 0,
MMPA_MAC_ADDR_SECOND_BYTE,
MMPA_MAC_ADDR_THIRD_BYTE,
MMPA_MAC_ADDR_FOURTH_BYTE,
MMPA_MAC_ADDR_FIFTH_BYTE,
MMPA_MAC_ADDR_SIXTH_BYTE
};
* 描述:对设备的I/O通道进行管理
* 参数: fd--指向设备驱动文件的文件资源描述符
* ioctl_code--ioctl的操作码
* bufPtr--指向数据的缓存, 里面包含的输入输出buf缓存由用户分配
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmIoctl(mmProcess fd, signed int ioctl_code, mmIoctlBuf *bufPtr)
{
if ((fd < MMPA_ZERO) || bufPtr == NULL || bufPtr->inbuf == NULL) {
return EN_INVALID_PARAM;
}
unsigned int request = (unsigned int)ioctl_code;
signed int ret = ioctl(fd, request, bufPtr->inbuf);
if (ret < ERRNO_MIN) {
return EIO;
} else if (ret < EN_OK) {
return EN_ERROR;
}
return ret;
}
* 描述:判断文件或者目录是否存在
* 参数: pathName -- 文件路径名
* 参数: mode -- 权限
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmAccess2(const char *pathName, signed int mode)
{
if (pathName == NULL) {
return EN_INVALID_PARAM;
}
signed int ret = access(pathName, mode);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:判断文件或者目录是否存在
* 参数: pathName -- 文件路径名
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmAccess(const char *pathName)
{
return mmAccess2(pathName, F_OK);
}
* 描述:把一个地址族中的特定地址赋给socket
* 参数: sockFd--socket描述字,通过mmSocket函数创建
* addr--一个指向要绑定给sockFd的协议地址
* addrLen--对应地址的长度
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmBind(mmSockHandle sockFd, const mmSockAddr* addr, mmSocklen_t addrLen)
{
if ((sockFd < MMPA_ZERO) || (addr == NULL) || (addrLen <= MMPA_ZERO)) {
return EN_INVALID_PARAM;
}
signed int ret = bind(sockFd, addr, addrLen);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:关闭打开的文件
* 参数: fd--指向打开文件的资源描述符
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmClose(signed int fd)
{
if (fd < MMPA_ZERO) {
return EN_INVALID_PARAM;
}
signed int ret = close(fd);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:关闭打开的文件或者设备驱动
* 参数: 打开的文件描述符fileId
* 返回值:执行成功返回EN_OK,执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mm_close_file(mmProcess fileId)
{
if (fileId < MMPA_ZERO) {
return EN_INVALID_PARAM;
}
signed int ret = close(fileId);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:关闭建立的socket连接
* 参数: sockFd--已打开或者建立连接的socket描述字
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mm_close_socket(mmSockHandle sockFd)
{
if (sockFd < MMPA_ZERO) {
return EN_INVALID_PARAM;
}
signed int ret = close(sockFd);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:用默认的属性创建线程
* 参数: threadHandle -- pthread_t类型的实例
* funcBlock --包含函数名和参数的结构体指针
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmCreateTask(mmThread *threadHandle, mmUserBlock_t *funcBlock)
{
if ((threadHandle == NULL) || (funcBlock == NULL) || (funcBlock->procFunc == NULL)) {
return EN_INVALID_PARAM;
}
signed int ret = pthread_create(threadHandle, NULL, funcBlock->procFunc, funcBlock->pulArg);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:创建带分离属性的线程, 不需要mmJoinTask等待线程结束
* 参数: threadHandle -- pthread_t类型的实例
* funcBlock --包含函数名和参数的结构体指针
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmCreateTaskWithDetach(mmThread *threadHandle, mmUserBlock_t *funcBlock)
{
if ((threadHandle == NULL) || (funcBlock == NULL) || (funcBlock->procFunc == NULL)) {
return EN_INVALID_PARAM;
}
pthread_attr_t attr;
(void)memset_s(&attr, sizeof(attr), 0, sizeof(attr));
signed int ret = pthread_attr_init(&attr);
if (ret != EN_OK) {
return EN_ERROR;
}
ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (ret != EN_OK) {
(void)pthread_attr_destroy(&attr);
return EN_ERROR;
}
ret = pthread_create(threadHandle, &attr, funcBlock->procFunc, funcBlock->pulArg);
(void)pthread_attr_destroy(&attr);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:mmCreateTaskWithThreadAttr内部使用,设置线程调度相关属性
* 参数: attr -- 线程属性结构体
* threadAttr -- 包含需要设置的线程属性类别和值
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline signed int LocalSetSchedAttr(pthread_attr_t *attr, const mmThreadAttr *threadAttr)
{
#ifndef __ANDROID__
if ((threadAttr->policyFlag == TRUE) || (threadAttr->priorityFlag == TRUE)) {
if (pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED) != EN_OK) {
return EN_ERROR;
}
}
#endif
if (threadAttr->policyFlag == TRUE) {
if (threadAttr->policy != MMPA_THREAD_SCHED_FIFO && threadAttr->policy != MMPA_THREAD_SCHED_OTHER &&
threadAttr->policy != MMPA_THREAD_SCHED_RR) {
return EN_INVALID_PARAM;
}
if (pthread_attr_setschedpolicy(attr, threadAttr->policy) != EN_OK) {
return EN_ERROR;
}
}
if (threadAttr->priorityFlag == TRUE) {
if ((threadAttr->priority < MMPA_MIN_THREAD_PIO) || (threadAttr->priority > MMPA_MAX_THREAD_PIO)) {
return EN_INVALID_PARAM;
}
struct sched_param param;
(void)memset_s(¶m, sizeof(param), 0, sizeof(param));
param.sched_priority = threadAttr->priority;
if (pthread_attr_setschedparam(attr, ¶m) != EN_OK) {
return EN_ERROR;
}
}
return EN_OK;
}
* 描述:mmCreateTaskWithThreadAttr内部使用,创建带属性的线程, 支持调度策略、优先级、线程栈大小属性设置
* 参数: attr -- 线程属性结构体
* threadAttr -- 包含需要设置的线程属性类别和值
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline signed int LocalSetThreadAttr(pthread_attr_t *attr, const mmThreadAttr *threadAttr)
{
signed int ret = LocalSetSchedAttr(attr, threadAttr);
if (ret != EN_OK) {
return ret;
}
if (threadAttr->stackFlag == TRUE) {
if (threadAttr->stackSize < MMPA_THREAD_MIN_STACK_SIZE) {
return EN_INVALID_PARAM;
}
if (pthread_attr_setstacksize(attr, threadAttr->stackSize) != EN_OK) {
return EN_ERROR;
}
}
if (threadAttr->detachFlag == TRUE) {
if (pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED) != EN_OK) {
return EN_ERROR;
}
}
return EN_OK;
}
* 描述:创建带属性的线程, 支持调度策略、优先级、线程栈大小、分离属性设置,除了分离属性,其他只在Linux下有效
* 参数: threadHandle -- pthread_t类型的实例
* funcBlock --包含函数名和参数的结构体指针
* threadAttr -- 包含需要设置的线程属性类别和值
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmCreateTaskWithThreadAttr(mmThread *threadHandle, const mmUserBlock_t *funcBlock,
const mmThreadAttr *threadAttr)
{
if ((threadHandle == NULL) || (funcBlock == NULL) ||
(funcBlock->procFunc == NULL) || (threadAttr == NULL)) {
return EN_INVALID_PARAM;
}
pthread_attr_t attr;
(void)memset_s(&attr, sizeof(attr), 0, sizeof(attr));
signed int ret = pthread_attr_init(&attr);
if (ret != EN_OK) {
return EN_ERROR;
}
ret = LocalSetThreadAttr(&attr, threadAttr);
if (ret != EN_OK) {
(void)pthread_attr_destroy(&attr);
return ret;
}
ret = pthread_create(threadHandle, &attr, funcBlock->procFunc, funcBlock->pulArg);
(void)pthread_attr_destroy(&attr);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:获取错误码
* 返回值:error code
*/
static inline MMPA_FUNC_VISIBILITY signed int mm_get_error_code(void)
{
signed int ret = (signed int)errno;
return ret;
}
* 描述:获取系统开机到现在经过的时间
* 返回值:执行成功返回类型mmTimespec结构的时间
*/
static inline MMPA_FUNC_VISIBILITY mmTimespec mmGetTickCount(void)
{
mmTimespec rts = {0};
struct timespec ts = {0};
(void)clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
rts.tv_sec = ts.tv_sec;
rts.tv_nsec = ts.tv_nsec;
return rts;
}
* 描述:获取当前系统时间和时区信息, windows不支持时区获取
* 参数:timeVal--当前系统时间, 不能为NULL
timeZone--当前系统设置的时区信息, 可以为NULL, 表示不需要获取时区信息
* 返回值:执行成功返回EN_OK, 失败返回EN_ERROR,入参错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmGetTimeOfDay(mmTimeval *timeVal, mmTimezone *timeZone)
{
if (timeVal == NULL) {
return EN_INVALID_PARAM;
}
signed int ret = gettimeofday((struct timeval *)timeVal, (struct timezone *)timeZone);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:监听socket
* 参数: sockFd--socket描述字,通过mmSocket函数创建
* backLog--相应socket可以排队的最大连接个数
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmListen(mmSockHandle sockFd, signed int backLog)
{
if ((sockFd < MMPA_ZERO) || (backLog <= MMPA_ZERO)) {
return EN_INVALID_PARAM;
}
signed int ret = listen(sockFd, backLog);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:把mutex锁删除
* 参数: mutex--指向mmMutex_t 指针
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmMutexDestroy(mmMutex_t *mutex)
{
if (mutex == NULL) {
return EN_INVALID_PARAM;
}
signed int ret = pthread_mutex_destroy(mutex);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:用默认属性初始化锁
* 参数: mutex --指向mmMutex_t 指针
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmMutexInit(mmMutex_t *mutex)
{
if (mutex == NULL) {
return EN_INVALID_PARAM;
}
signed int ret = pthread_mutex_init(mutex, NULL);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:把mutex锁住
* 参数: mutex --指向mmMutex_t 指针
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmMutexLock(mmMutex_t *mutex)
{
if (mutex == NULL) {
return EN_INVALID_PARAM;
}
signed int ret = pthread_mutex_lock(mutex);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:把mutex锁解锁
* 参数: mutex--指向mmMutex_t 指针
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmMutexUnLock(mmMutex_t *mutex)
{
if (mutex == NULL) {
return EN_INVALID_PARAM;
}
signed int ret = pthread_mutex_unlock(mutex);
if (ret != EN_OK) {
ret = EN_ERROR;
}
return ret;
}
* 描述:打开或者创建一个文件
* 参数: pathName--需要打开或者创建的文件路径名,由用户确保绝对路径
* flags--打开或者创建的文件标志位
* mode -- 打开或者创建的权限
* 返回值:执行成功返回对应打开的文件描述符, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmOpen2(const char *pathName, signed int flags, MODE mode)
{
char *out_path = NULL;
signed int fd = -1;
if ((pathName == NULL) || (flags < MMPA_ZERO) ||
(strnlen((pathName), (PATH_MAX + 1)) >= (PATH_MAX + 1))) {
return EN_INVALID_PARAM;
}
unsigned int tmp = (unsigned int)flags;
if (((tmp & (O_TRUNC | O_WRONLY | O_RDWR | O_CREAT)) == MMPA_ZERO) && (flags != O_RDONLY)) {
return EN_INVALID_PARAM;
}
if (((mode & (S_IRUSR | S_IREAD)) == MMPA_ZERO) &&
((mode & (S_IWUSR | S_IWRITE)) == MMPA_ZERO)) {
return EN_INVALID_PARAM;
}
if ((out_path = (char *)malloc(PATH_MAX + 1)) &&
(!memset_s(out_path, (PATH_MAX + 1), 0, (PATH_MAX + 1))) &&
(realpath((pathName), out_path))) {
fd = open(out_path, flags, mode);
}
if (out_path != NULL) {
free(out_path);
out_path = NULL;
}
if (fd < MMPA_ZERO) {
return EN_ERROR;
}
return fd;
}
* 描述:往打开的文件或者设备驱动读取内容
* 参数: 打开的文件描述符fileId,buffer为用户分配缓存,len为buffer对应长度
* 返回值:执行成功返回实际读取的长度,执行错误返回EN_ERROR,入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY mmSsize_t mm_read_file(mmProcess fileId, void *buffer, signed int len)
{
if ((fileId < MMPA_ZERO) || (buffer == NULL) || (len < MMPA_ZERO)) {
return EN_INVALID_PARAM;
}
unsigned int readLen = (unsigned int)len;
mmSsize_t ret = read(fileId, buffer, readLen);
if (ret < MMPA_ZERO) {
return EN_ERROR;
}
return ret;
}
* 描述:设置当前执行的线程的线程名-线程体内调用, 仅在Linux下生效, Windows下不支持为空实现
* 参数:name--需要设置的线程名
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmSetCurrentThreadName(const char* name)
{
if (name == NULL) {
return EN_INVALID_PARAM;
}
signed int ret = prctl(PR_SET_NAME, name);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:睡眠指定时间
* 参数: milliSecond -- 睡眠时间 单位ms, linux下usleep函数microSecond入参必须小于1000000
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmSleep(unsigned int milliSecond)
{
if (milliSecond == MMPA_ZERO) {
return EN_INVALID_PARAM;
}
unsigned int microSecond;
if (milliSecond <= MMPA_MAX_SLEEP_MILLSECOND_USING_USLEEP) {
microSecond = milliSecond * MMPA_MSEC_TO_USEC;
} else {
microSecond = MMPA_MAX_SLEEP_MICROSECOND_USING_USLEEP;
}
signed int ret = usleep(microSecond);
if (ret != EN_OK) {
return EN_ERROR;
}
return EN_OK;
}
* 描述:创建socket
* 参数: sockFamily--协议域
* type--指定socket类型
* protocol--指定协议
* 返回值:执行成功返回创建的socket id, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY mmSockHandle mmSocket(signed int sockFamily, signed int type, signed int protocol)
{
signed int socketHandle = socket(sockFamily, type, protocol);
if (socketHandle < MMPA_ZERO) {
return EN_ERROR;
}
return socketHandle;
}
* 描述:往打开的文件或者设备驱动写内容
* 参数:打开的文件描述符fileId,buffer为用户分配缓存,len为buffer对应长度
* 返回值:执行成功返回EN_OK,执行错误返回EN_ERROR,入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY mmSsize_t mm_write_file(mmProcess fileId, const void *buffer, signed int len)
{
if ((fileId < MMPA_ZERO) || (buffer == NULL) || (len < MMPA_ZERO)) {
return EN_INVALID_PARAM;
}
unsigned int writeLen = (unsigned int)len;
mmSsize_t ret = write(fileId, buffer, writeLen);
if (ret < MMPA_ZERO) {
return EN_ERROR;
}
return ret;
}
* 描述:用于在一次函数调用中写多个非连续缓冲区
* 参数: fd -- 打开的资源描述符
* iov -- 指向非连续缓存区的首地址的指针
* iovcnt -- 非连续缓冲区的个数, 最大支持MAX_IOVEC_SIZE片非连续缓冲区
* 返回值:执行成功返回实际写入的长度, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY mmSsize_t mmWritev(mmSockHandle fd, mmIovSegment *iov, signed int iovcnt)
{
signed int i = 0;
if ((fd < MMPA_ZERO) || (iov == NULL) || (iovcnt < MMPA_ZERO) || (iovcnt > MAX_IOVEC_SIZE)) {
return EN_INVALID_PARAM;
}
struct iovec tmpSegment[MAX_IOVEC_SIZE];
(void)memset_s(tmpSegment, sizeof(tmpSegment), 0, sizeof(tmpSegment));
for (i = 0; i < iovcnt; i++) {
tmpSegment[i].iov_base = iov[i].sendBuf;
tmpSegment[i].iov_len = (unsigned int)iov[i].sendLen;
}
mmSsize_t ret = writev(fd, tmpSegment, iovcnt);
if (ret < EN_OK) {
return EN_ERROR;
}
return ret;
}
* 描述:创建一个消息队列用于进程间通信
* 参数:key--消息队列的KEY键值,
* msgFlag--取消息队列标识符
* 返回值:执行成功则返回打开的消息队列ID, 执行错误返回EN_ERROR
*/
static inline MMPA_FUNC_VISIBILITY mmMsgid mmMsgCreate(mmKey_t key, signed int msgFlag)
{
return (mmMsgid)msgget(key, msgFlag);
}
* 描述:往消息队列发送消息
* 参数:msqid--消息队列ID
* buf--由用户分配内存
* bufLen--缓存长度
* msgFlag--消息标志位
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmMsgSnd(mmMsgid msqid,
const void *buf, signed int bufLen, signed int msgFlag)
{
if ((buf == NULL) || (bufLen <= MMPA_ZERO)) {
return EN_INVALID_PARAM;
}
unsigned int sndLen = (unsigned int)bufLen;
return (signed int)msgsnd(msqid, buf, sndLen, msgFlag);
}
* 描述:从消息队列接收消息
* 参数:msqid--消息队列ID
* bufLen--缓存长度
* msgFlag--消息标志位
* buf--由用户分配内存
* 返回值:执行成功返回EN_OK, 执行错误返回EN_ERROR, 入参检查错误返回EN_INVALID_PARAM
*/
static inline MMPA_FUNC_VISIBILITY signed int mmMsgRcv(mmMsgid msqid,
void *buf, signed int bufLen, signed int msgFlag)
{
if ((buf == NULL) || (bufLen <= MMPA_ZERO)) {
return EN_INVALID_PARAM;
}
unsigned int rcvLen = (unsigned int)bufLen;
return (signed int)msgrcv(msqid, buf, rcvLen, MMPA_DEFAULT_MSG_TYPE, msgFlag);
}
static inline MMPA_FUNC_VISIBILITY signed int mmMsgCtl(mmMsgid msqid,
int cmd, struct msqid_ds *buf)
{
return (signed int)msgctl(msqid, cmd, buf);
}
#endif
#endif