C语言下命令行参数解析方式演进

命令行基本概念

在C语言程序开发过程中无论是示例应用还是工具程序都少不了要进行命令行解析的操作,如何高效优雅的解析命令行中传入的参数是个重要的能力。

无论是sylixos还是Linux,在命令行输入的命令字符串都会把其中的空格去掉,分割为一个字符串数组,通过int argc 和 char *argv[]传给应用的入口函数,所以一般应用程序的主函数格式为int main(int argc, char *argv[])。其中argc为分割后参数个数,argv为参数字符串数组且里面的字符串顺序和命令行中输入的顺序一致。一个命令行至少有一个有效的字符串也就是命令本身即argv[0],所以argc的值也至少为1。

如命令为:“cmd arga argb argc”
则 argc = 4
argv[0] = cmd
argv[1] = arga
argv[2] = argb
argv[3] = argc

把命令行中输入的字符串行转换为argc和argv格式是由操作系统完成的,而如何解析argc和argv中内容的含义则是由应用程序自己处理的。
下面列出来4种命令行参数解析方法,都以串口接收并发送为例子列出源码。4种方法由简单到复杂,适配越来越复杂的命令行参数解析操作。

  1. 不使用命令行参数
  2. 使用固定位置的命令行参数
  3. 使用getopt/getopt_long函数解析命令行参数
  4. 使用cmdParse函数解析命令行参数

不使用命令行参数

解析命令行参数最简单的方法就是不解析,也就是设计的程序没有命令参数只有命令。这样的应用功能固定单一,一般只能作为简单的示例程序,程序中的很多配置都是以源码的方式写死的,一旦需要修改参数就需要修改源码并重新编译部署。

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                       SylixOS(TM)
**
**                               Copyright  All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: uartExample.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2018 年 01 月 11 日
**
** 描        述: 串口示例程序,收到一组数据后将此组数据通过串口返回
*********************************************************************************************************/
#include <SylixOS.h>
/*********************************************************************************************************
  宏定义
*********************************************************************************************************/
#define BUF_SIZE      (512)
#define DEV_NAME      "/dev/ttyS1"
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 程序入口
** 输    入: argc   参数个数
**           argv   参数列表
** 输    出: ERROR_CODE
*********************************************************************************************************/
int main(int argc, char *argv[])
{
    int         iFd;
    char        pcBuff[BUF_SIZE];
    ssize_t     sstReadLen;

    /*
     * 打开串口设备
     */
    iFd = open(DEV_NAME, O_RDWR);
    if (iFd < 0) {
        return  (-1);
    }

    /*
     * 设置串口属性
     * 波特率为  : 115200
     * 硬件选项为: 8位数据位, 一位停止位,无校验
     */
    ioctl(iFd, SIO_BAUD_SET,    SIO_BAUD_115200);
    ioctl(iFd, SIO_HW_OPTS_SET, CREAD | CS8);

    /*
     * 读取输入串口的数据,并原样发送出去
     * 注意,默认情况下,读写都可能会阻塞
     */
    while (1) {
        sstReadLen = read(iFd, pcBuff, BUF_SIZE);
        write(iFd, pcBuff, sstReadLen);
    }

    /*
     * 关闭串口设备
     */
    close(iFd);

    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

使用固定位置的命令行参数

设计命令参数一个简单的思路就是不同位置的参数代表不同含义。这样设计的一个缺点就是只有从末尾倒序的参数才能不输入,前面的参数则必须要输入,即便是默认值。
如下面程序所示,输入的命令必须按照cmd [filename] [baudrate] [option]的格式,后面的参数可以不输入,此时就会使用程序默认的参数值。

以下都是合法的输入命令
uart /dev/ttyS1 115200 none //设置了全部参数
uart /dev/ttyS1 115200 //设置文件名和波特率,校验方式使用默认
uart /dev/ttyS1 //设置文件,校验方式名和波特率使用默认
uart // 全部使用默认参数
以下则都是不合法的输入命令
uart 115200 none
uart none
uart 115200 none /dev/ttyS1

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                       SylixOS(TM)
**
**                               Copyright  All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: uartExample.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2018 年 01 月 11 日
**
** 描        述: 串口示例程序,收到一组数据后将此组数据通过串口返回
**               cmd  [filename] [baudrate] [option]
*********************************************************************************************************/
#include <SylixOS.h>
#include <string.h>
#include <stdlib.h>
/*********************************************************************************************************
  宏定义
*********************************************************************************************************/
#define BUF_SIZE                   (512)
#define CFG_DEFAULT_UART_NAME      ("/dev/ttyS1")
#define CFG_DEFAULT_UART_BAUD      (SIO_BAUD_115200)
#define CFG_DEFAULT_UART_OPTS      (CREAD | CS8)
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 程序入口
** 输    入: argc   参数个数
**           argv   参数列表
** 输    出: ERROR_CODE
*********************************************************************************************************/
int main(int argc, char *argv[])
{
    int         iFd;
    char        pcBuff[BUF_SIZE];
    ssize_t     sstReadLen;

    char        cFileName[64] = CFG_DEFAULT_UART_NAME;                  /*  设备文件名                  */
    uint32_t    uiBaud        = CFG_DEFAULT_UART_BAUD;                  /*  波特率                      */
    uint32_t    uiOption      = CFG_DEFAULT_UART_OPTS;                  /*  硬件选项                    */

    /*
     * 解析输入的命令参数
     */
    switch (argc) {
    case 4:
        if (strcmp(argv[3], "none") == 0) {
            uiOption = CREAD | CS8;
        } else if (strcmp(argv[3], "odd") == 0) {
            uiOption = CREAD | CS8 | PARENB | PARODD;
        } else if (strcmp(argv[3], "even") == 0) {
            uiOption = CREAD | CS8 | PARENB;
        }
    case 3:
        uiBaud = strtoul(argv[2], NULL, 0);
    case 2:
        memcpy(cFileName, argv[1], strlen(argv[1]));
    case 1:
        break;
    default:
        break;
    }

    /*
     * 打开串口设备
     */
    iFd = open(cFileName, O_RDWR);
    if (iFd < 0) {
        return  (-1);
    }

    /*
     * 设置串口属性
     */
    ioctl(iFd, SIO_BAUD_SET,    uiBaud);
    ioctl(iFd, SIO_HW_OPTS_SET, uiOption);

    /*
     * 读取输入串口的数据,并原样发送出去
     * 注意,默认情况下,读写都可能会阻塞
     */
    while (1) {
        sstReadLen = read(iFd, pcBuff, BUF_SIZE);
        write(iFd, pcBuff, sstReadLen);
    }

    /*
     * 关闭串口设备
     */
    close(iFd);

    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

使用getopt/getopt_long函数解析命令行参数

getopt函数是POSIX标准下的一个通用命令参数解析函数,getopt_long是它的加强版可以支持长选项。

上一节使用的参数都是位置参数,参数位置不能随意改变,也不能随意缺失,用起来不是很方便灵活,尤其是参数比较多时,不得不输入长长的一串参数,还得记着位置和个数不能出错。getopt则使用的是选项参数,通过“-”来标注选项(getopt_long可以使用长选项,通过“–”来标注),选项后面的则是选项参数,当然选项也可以没有选项参数。首先各选项在命令行中的位置可以是任意的,其次使用默认值得选项可以不输入,这样在输入命令时就方便多了。

关于getopt函数的用法网上有很多教程这里不再细说,其实也比较简单,看看下面的例程,对照一下应该就基本会用了。

#include <unistd.h>
int getopt(int argc, char * const argv[],const char *optstring);

extern char *optarg; //存储选项的参数
extern int optind //指向下一个扫描的位置
extern int opterr //是否显示错误信息
extern int optopt; //读取到的字符如果不在opstring(上面例子是"alRtS")中,则存入optopt中

#include <getopt.h>

int getopt_long(int argc, char * const argv[],const char*optstring,const struct option *longopts, int *longindex);

int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                       SylixOS(TM)
**
**                               Copyright  All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: uartExample.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2018 年 01 月 11 日
**
** 描        述: 串口示例程序,收到一组数据后将此组数据通过串口返回
**               cmd  [-f filename]/[-b baudrate]/[-o option]
*********************************************************************************************************/
#include <SylixOS.h>
#include <string.h>
#include <stdlib.h>
/*********************************************************************************************************
  宏定义
*********************************************************************************************************/
#define BUF_SIZE                   (512)
#define CFG_DEFAULT_UART_NAME      ("/dev/ttyS1")
#define CFG_DEFAULT_UART_BAUD      (SIO_BAUD_115200)
#define CFG_DEFAULT_UART_OPTS      (CREAD | CS8)
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 程序入口
** 输    入: argc   参数个数
**           argv   参数列表
** 输    出: ERROR_CODE
*********************************************************************************************************/
int main(int argc, char *argv[])
{
    int         c;
    int         iFd;
    char        pcBuff[BUF_SIZE];
    ssize_t     sstReadLen;

    char        cFileName[64] = CFG_DEFAULT_UART_NAME;                  /*  设备文件名                  */
    uint32_t    uiBaud        = CFG_DEFAULT_UART_BAUD;                  /*  波特率                      */
    uint32_t    uiOption      = CFG_DEFAULT_UART_OPTS;                  /*  硬件选项                    */

    /*
     * 解析输入的命令参数
     */
    while (1) {
        c = getopt(argc, argv, "f:b:o:");
        if (c == -1) {
            break;
        }

        switch (c) {
        case 'f':
            memcpy(cFileName, optarg, strlen(optarg));
            break;
        case 'b':
            uiBaud = strtoul(optarg, NULL, 0);
            break;

        case 'o':
            if (strcmp(optarg, "none") == 0) {
                uiOption = CREAD | CS8;
            } else if (strcmp(optarg, "odd") == 0) {
                uiOption = CREAD | CS8 | PARENB | PARODD;
            } else if (strcmp(optarg, "even") == 0) {
                uiOption = CREAD | CS8 | PARENB;
            }
            break;

        default:
            return  (PX_ERROR);
        }
    }

    /*
     * 打开串口设备
     */
    iFd = open(cFileName, O_RDWR);
    if (iFd < 0) {
        return  (-1);
    }

    /*
     * 设置串口属性
     */
    ioctl(iFd, SIO_BAUD_SET,    uiBaud);
    ioctl(iFd, SIO_HW_OPTS_SET, uiOption);

    /*
     * 读取输入串口的数据,并原样发送出去
     * 注意,默认情况下,读写都可能会阻塞
     */
    while (1) {
        sstReadLen = read(iFd, pcBuff, BUF_SIZE);
        write(iFd, pcBuff, sstReadLen);
    }

    /*
     * 关闭串口设备
     */
    close(iFd);

    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

使用cmdParse函数解析命令行参数

虽然getopt函数使用比较广泛,也能完成大部分参数解析工作,但当参数很多很复杂时用着就比较费时费力了。为了简化并高效率进行参数解析,科技猎人设计了cmdParse函数模块,虽然实现不是很复杂,但是真的很好用啊!!!

cmdParse和getopt一样使用选项参数,但不区分短选项和长选项,选项可以是任意字符串,只要和输入完全匹配即可。同时cmdParse也没有选项字串,只有选项列表,是通过选项列表的的目标来工作的,可以是直接解析选项参数并回填参数值也可以是回调一个函数进行更复杂的选项参数处理。

cmdParse函数模块的实现稍后会再另一篇博客里细讲,这里先列一个使用cmdParse函数的例子。其实初看是体会不到cmdParse函比数getopt函数方便多少的,读者可以试着用getopt函数实现一下同样功能,看看是不是不便了很多。

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: uartAccessCmd.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2017 年 10 月 17 日
**
** 描        述: 通用串口测试工具
*********************************************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "cmdParse/cmdParse.h"
/*********************************************************************************************************
  宏定义
*********************************************************************************************************/
#define CFG_DEFAULT_BUF_SIZE                (64)                        /*  默认缓存大小                */
#define CFG_DEFAULT_BUF_COUNT               (32)                        /*  默认缓存个数                */
/*********************************************************************************************************
  宏函数
*********************************************************************************************************/
#if 1
#define PRINT_DEBUG(fmt, ...)     do {printf(fmt, ##__VA_ARGS__);} while (0)
#else
#define PRINT_DEBUG(fmt, ...)
#endif

#define PRINT_ERROR(fmt, ...)     do {printf("[ERROR]%s:%d---", __FILE__, __LINE__); \
                                      printf(fmt, ##__VA_ARGS__);  } while (0)

#define PRINT_DATA_UINT8(ptr, len, fmt, ...)                            \
                do {UINT  j;                                            \
                    printf(fmt, ##__VA_ARGS__);                         \
                    for (j = 0; j < (len); j++) {                       \
                        if ((j & 0x0f) == 0) {printf("\r\n[%04x]", j);} \
                        printf(" %02x", ((UINT8 *)ptr)[j]);             \
                    } printf("\n");} while (0)
/*********************************************************************************************************
  设备配置参数结构
*********************************************************************************************************/
typedef struct {
    UINT32                      uiEchoState;                            /*  0 不反射 1反射接收的数据    */
    UINT32                      uiDisplayState;                         /*  0 不显示收发数据 1显示      */
    INT                         iFd;                                    /*  设备文件标识符              */
    pthread_t                   tidRecv;                                /*  接收线程ID                  */
    pthread_t                   tidEcho;                                /*  反射线程ID                  */
    pthread_t                   tidSend;                                /*  发送线程ID                  */
    LW_OBJECT_HANDLE            hQueueSend;                             /*  消息队列句柄                */
    CHAR                        cFileName[64];                          /*  波特率                      */
    UINT32                      uiBaud;                                 /*  波特率                      */
    UINT32                      uiOption;                               /*  硬件选项                    */
    UINT32                      uiRecvCount;                            /*  串口接收数据计数            */
    UINT32                      uiEchoCount;                            /*  串口反射数据计数            */
    UINT32                      uiSendCount;                            /*  串口发送数据计数            */

    UINT32                      uiSendInterval;                         /*  发送间隔,单位毫秒          */
    UINT32                      uiSendNumber;                           /*  串口发送次数                */
    INT32                       uiBufLength;                            /*  缓冲区有效数据长度          */
    UINT8                       ucBuf[CFG_DEFAULT_BUF_SIZE];            /*  缓冲区                      */

} DEV_ARG_ST;
/*********************************************************************************************************
** 名称: getInfo
** 输入: cmd        命令参数
**       opti       参数索引
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 获取 info 选项
*********************************************************************************************************/
static int  getInfo (command_st  *cmd, int opti)
{
    DEV_ARG_ST  *pArg;

    pArg = cmd->priv;

    printf("echo     = %d\n", pArg->uiEchoState);
    printf("display  = %d\n", pArg->uiDisplayState);
    printf("iFd      = %d\n", pArg->iFd);
    printf("tidRecv  = %08x\n", (UINT)pArg->tidRecv);
    printf("tidEcho  = %08x\n", (UINT)pArg->tidEcho);
    printf("tidSend  = %08x\n", (UINT)pArg->tidSend);
    printf("file     = %s\n", pArg->cFileName);
    printf("uiBaud   = %d\n", pArg->uiBaud);
    printf("uiOption = %08x\n", pArg->uiOption);
    printf("recvCount= %d\n", pArg->uiRecvCount);
    printf("echoCount= %d\n", pArg->uiEchoCount);
    printf("sendCount= %d\n", pArg->uiSendCount);
    printf("interval = %d\n", pArg->uiSendInterval);
    printf("number   = %d\n", pArg->uiSendNumber);
    printf("uiLength = %d\n", pArg->uiBufLength);

    if (pArg->uiBufLength) {
        PRINT_DATA_UINT8(pArg->ucBuf, pArg->uiBufLength, "send data :");
    }

    return  (ERROR);
}
/*********************************************************************************************************
** 名称: getClose
** 输入: cmd        命令参数
**       opti       参数索引
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 获取 Option 选项
*********************************************************************************************************/
static int  getOption (command_st  *cmd, int opti)
{
    option_st   *opt;
    DEV_ARG_ST  *pArg;
    char        *str;

    pArg = cmd->priv;
    opt  = &cmd->optv[opti];

    if (opt->argc <= 0) {
        return  (NONE);
    }

    str = cmd->argv[opt->index + 1];
    if (strcmp(str, "none") == 0) {
        pArg->uiOption = CREAD | CS8;
    } else if (strcmp(str, "odd") == 0) {
        pArg->uiOption = CREAD | CS8 | PARENB | PARODD;
    } else if (strcmp(str, "even") == 0) {
        pArg->uiOption = CREAD | CS8 | PARENB;
    } else {
        pArg->uiOption = strtoul(str, NULL, 0);
    }

    return  (NONE);
}
/*********************************************************************************************************
** 名称: devPthreadRecv
** 描述: 串口接收线程
** 输入: pvArg       参数结构
** 输出: ERROR_CODE
*********************************************************************************************************/
static  void   *devPthreadRecv (void * pvArg)
{
    INT          res;
    UINT8        buf[CFG_DEFAULT_BUF_SIZE];
    DEV_ARG_ST  *pArg = (DEV_ARG_ST  *)pvArg;

    while(1) {
        res = read(pArg->iFd, buf, sizeof(buf));
        if (res > 0) {                                                  /*  接收数据                    */
            pArg->uiRecvCount += res;
            if (pArg->uiEchoState) {
                Lw_MsgQueue_SendEx2(pArg->hQueueSend,
                                    (PVOID)buf,
                                    res,
                                    LW_OPTION_NOT_WAIT,
                                    LW_OPTION_DEFAULT);

            }

            if (pArg->uiDisplayState) {
                PRINT_DATA_UINT8(buf, res, "[uart %s] recv %d byte, data :", pArg->cFileName, res);
            }

        } else {
            PRINT_ERROR("read err,res = %d \n", res);
            break;
        }
    }

    return  (NULL);
}
/*********************************************************************************************************
** 名称: devPthreadEcho
** 描述: 串口反射线程
** 输入: pvArg       参数结构
** 输出: ERROR_CODE
*********************************************************************************************************/
static  void   *devPthreadEcho (void * pvArg)
{
    INT          res;
    size_t       txLen;
    UINT8        buf[CFG_DEFAULT_BUF_SIZE];
    DEV_ARG_ST  *pArg = (DEV_ARG_ST  *)pvArg;

    while(1) {
        res = Lw_MsgQueue_Receive(pArg->hQueueSend,
                                  buf,
                                  CFG_DEFAULT_BUF_SIZE,
                                  &txLen,
                                  LW_OPTION_WAIT_INFINITE);


        if (res < 0) {
            PRINT_ERROR("Lw_MsgQueue_Receive,res = %d", res);
            break;
        } else {                                                        /*  接收数据                    */
            if (pArg->uiDisplayState) {
                pArg->uiEchoCount += txLen;
                write(pArg->iFd, buf, txLen);
                PRINT_DATA_UINT8(buf, txLen, "[uart %s] echo %d byte, data :", pArg->cFileName, txLen);
            }
        }
    }

    return  (NULL);
}
/*********************************************************************************************************
** 名称: devPthreadSend
** 描述: 串口发送线程
** 输入: pvArg       参数结构
** 输出: ERROR_CODE
*********************************************************************************************************/
static  void   *devPthreadSend (void * pvArg)
{
    DEV_ARG_ST  *pArg = (DEV_ARG_ST  *)pvArg;

    while(pArg->uiBufLength && pArg->uiSendNumber--) {
        if (pArg->uiDisplayState) {
            PRINT_DATA_UINT8(pArg->ucBuf, pArg->uiBufLength,
                            "[uart %s] send %d byte, data :", pArg->cFileName, pArg->uiBufLength);
        }

        pArg->uiSendCount += pArg->uiBufLength;
        write(pArg->iFd, pArg->ucBuf, pArg->uiBufLength);

        usleep(pArg->uiSendInterval * 1000);
    }

    return  (NULL);
}
/*********************************************************************************************************
** 名称: uartTool
** 输入: argc       参数个数
**       argv       参数列表
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 通用串口测试工具
*********************************************************************************************************/
static int uartTool (int argc, char *argv[])
{
    DEV_ARG_ST  devArg = {
        .uiEchoState    = 0,
        .uiDisplayState = 1,
        .iFd            = -1,
        .cFileName      = "/dev/ttyS1",
        .uiBaud         = SIO_BAUD_115200,
        .uiOption       = CREAD | CS8,
        .uiRecvCount    = 0,
        .uiEchoCount    = 0,
        .uiSendCount    = 0,
        .uiSendInterval = 1000,
        .uiSendNumber   = 0,
        .uiBufLength    = 0,
        .ucBuf          = { 0 },
    };
    option_st  optv[] = {
        {ATT_BUF_SIZE(sizeof(devArg.cFileName)) |
         ATT_TYPE_SBUF, &devArg.cFileName,      "f",      "set uart device file name"},
        {ATT_TYPE_BOOL, &devArg.uiDisplayState, "d",      "set dispaly state"},
        {ATT_TYPE_BOOL, &devArg.uiEchoState,    "e",      "set echo state"},
        {ATT_TYPE_U32,  &devArg.uiBaud,         "b",      "set baudrate"},
        {ATT_FUNC,      getOption,              "o",      "set option, none/odd/even/0x0e"},
        {ATT_TYPE_U32,  &devArg.uiSendInterval, "i",      "set send interval, ms"},
        {ATT_TYPE_U32,  &devArg.uiSendNumber,   "n",      "set send number"},
        {ATT_ARRAY(GET_ARRAY_COUNT(devArg.ucBuf)) |
         ATT_TYPE_U8,   &devArg.ucBuf,          "w",      "set send data", &devArg.uiBufLength},
        {ATT_FUNC,      getInfo,                "info",   "print cmd info"},
    };
    command_st           cmd;
    DEV_ARG_ST          *pArg = &devArg;
    int                  err;
    LW_CLASS_THREADATTR  hThreadAttr;


    cmd.argc = argc;
    cmd.argv = argv;
    cmd.optc = GET_OPTC(optv);
    cmd.optv = optv;
    cmd.priv = pArg;

    err = cmdParse(&cmd);
    if (err != NONE) {
        return  (err);
    }

    pArg->hQueueSend = Lw_MsgQueue_Create(
        "uartQueue",
        CFG_DEFAULT_BUF_COUNT,
        CFG_DEFAULT_BUF_SIZE,
        LW_OPTION_WAIT_FIFO | LW_OPTION_OBJECT_LOCAL,
        NULL);

    pArg->iFd = open(pArg->cFileName, O_RDWR, 0666);
    if (pArg->iFd < 0) {
        PRINT_ERROR("open device [%s] faild\n", pArg->cFileName);
        return  (PX_ERROR);
    }

    ioctl(pArg->iFd, FIOFLUSH, NULL);                                   /*  清空设备收发缓冲区          */
    if (ioctl(pArg->iFd, SIO_BAUD_SET, pArg->uiBaud) != ERROR_NONE) {
        PRINT_ERROR("set baudrate faild\n");
        close(pArg->iFd);
        return  (PX_ERROR);
    }
    if (ioctl(pArg->iFd, SIO_HW_OPTS_SET, pArg->uiOption) != ERROR_NONE) {
        PRINT_ERROR("set opt faild\n");
        close(pArg->iFd);
        return  (PX_ERROR);
    }

    Lw_ThreadAttr_Build(&hThreadAttr, 4 * LW_CFG_KB_SIZE, LW_PRIO_NORMAL + 0, 0, (void *)pArg);
    Lw_Thread_Create("t_uartRecv", devPthreadRecv, &hThreadAttr, &pArg->tidRecv);
    Lw_ThreadAttr_Build(&hThreadAttr, 4 * LW_CFG_KB_SIZE, LW_PRIO_NORMAL + 1, 0, (void *)pArg);
    Lw_Thread_Create("t_uartEcho", devPthreadEcho, &hThreadAttr, &pArg->tidEcho);
    Lw_ThreadAttr_Build(&hThreadAttr, 4 * LW_CFG_KB_SIZE, LW_PRIO_NORMAL + 2, 0, (void *)pArg);
    Lw_Thread_Create("t_uartSend", devPthreadSend, &hThreadAttr, &pArg->tidSend);

    Lw_Thread_Join(pArg->tidRecv, NULL);
    Lw_Thread_Join(pArg->tidEcho, NULL);

    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 名称: main
** 描述: 程序入口
** 输入: argc   参数个数
**       argv   参数列表
** 输出: ERROR_CODE
*********************************************************************************************************/
int main (int argc, char **argv)
{
    uartTool(argc, argv);

    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

发布了39 篇原创文章 · 获赞 6 · 访问量 5061

猜你喜欢

转载自blog.csdn.net/ScilogyHunter/article/details/104380512
今日推荐