开发者社区> 周兆熊> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Linux下入队列和出队列操作的C代码示例

简介: 本文用实际的C代码示例了简单的数据入队列和出队列的方法,大家可据此了解队列的实际用法,也可参照来实现更加复杂的队列操作。
+关注继续查看

概述
最近有在校的学生朋友在问我,数据结构中的队列在实际的软件开发项目中有什么样的用处。

大家都知道,队列的特点是先入先出,即数据是按照入队列的顺序出队列的。在实际的软件开发项目中,当一个中间模块需要接收和发送大量的消息时,队列就可以大展身手了。我们可以将接收到的数据存储在一个全局队列中,然后在另外的程序流程中将数据从同一个全局队列中取出来,经过一定的处理之后将消息发送到另外的模块。这样做可以降低程序的性能瓶颈。

本文用实际的C代码示例了简单的数据入队列和出队列的方法,大家可据此了解队列的实际用法,也可参照来实现更加复杂的队列操作。

C代码

/**********************************************************************
* 版权所有 (C)2016, Zhou Zhaoxiong
*
* 文件名称:QueueUse.c
* 文件标识:无
* 内容摘要:示例队列的使用(入队和出队)
* 其它说明:无
* 当前版本:V1.0
* 作    者:Zhou Zhaoxiong
* 完成日期:20160811
*
**********************************************************************/
#include <stdio.h>
#include <string.h>
#include <ftw.h>
#include <pthread.h>
#include <time.h>


// 重定义数据类型
typedef signed   int        INT32;
typedef unsigned int        UINT32;
typedef unsigned char       UINT8;

// 宏定义
#define     MAX_QUEUE      10000          // 最大队列元素个数

// 结构体变量
typedef struct
{
    UINT32 iID;             // 编号
    UINT8  szInfo[100];     // 描述
} T_StructInfo;

// 全局变量定义
T_StructInfo g_tQueue[MAX_QUEUE] = {0};      // 队列结构体
UINT32 g_iQueueHead = 0;                     // 队列头部索引
UINT32 g_iQueueTail = 0;                     // 队列尾部索引
pthread_mutex_t     g_mutex_queue_cs;        // 互斥信号量
pthread_cond_t      queue_cv;
pthread_mutexattr_t g_MutexAttr;

// 函数声明
void PutDataIntoQueue(void);
void GetDataFromQueue(void);
INT32 EnQueue(T_StructInfo tQueueData);
INT32 DeQueue(T_StructInfo *ptStructData);
void Sleep(UINT32 iCountMs);


/****************************************************************
* 功能描述: 主函数
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0-执行完成
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
* -------------------------------------------------------------
* 20160811        V1.0     Zhou Zhaoxiong     创建
****************************************************************/
INT32 main(void)
{
    pthread_mutex_init(&g_mutex_queue_cs, &g_MutexAttr);
    pthread_cond_init(&queue_cv, NULL);


    // 在循环中执行入队和出队操作
    while (1)
    {
        PutDataIntoQueue();  // 数据入队


        Sleep(5 * 1000);     // 间隔5秒


        GetDataFromQueue();  // 数据出队


        Sleep(60 * 1000);    // 每一分钟执行一次出队和入队
    }


    return 0;
}




/****************************************************************
* 功能描述: 将数据加入队列中
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0-成功   -1-失败
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
* -------------------------------------------------------------
* 20160811        V1.0     Zhou Zhaoxiong     创建
****************************************************************/
void PutDataIntoQueue(void)
{
    T_StructInfo tQueueData = {0};
    static UINT32 iCountNum = 0;


    // 对结构体的变量进行赋值
    tQueueData.iID = iCountNum;
    snprintf(tQueueData.szInfo, sizeof(tQueueData.szInfo) - 1, "zhou%d", iCountNum);


    // 计数值累加
    iCountNum ++;
    if (iCountNum >= MAX_QUEUE-1)
    {
        iCountNum = 0;
    }


    // 将数据加入队列(一直等到加入成功之后才退出)
    while (EnQueue(tQueueData) == -1)
    {
        Sleep(1000);       // 加入失败,1秒后重试
    }


    // 打印加入的数据
    printf("PutDataIntoQueue: ID=%d, Info=%s\n", tQueueData.iID, tQueueData.szInfo);
}




/****************************************************************
* 功能描述: 将数据取出队列中
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0-成功   -1-失败
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
* -------------------------------------------------------------
* 20160811        V1.0     Zhou Zhaoxiong     创建
****************************************************************/
void GetDataFromQueue(void)
{
    T_StructInfo tQueueData = {0};


    if (DeQueue(&tQueueData) == -1)
    {
        return;
    }


    // 打印取出的数据
    printf("GetDataFromQueue: ID=%d, Info=%s\n", tQueueData.iID, tQueueData.szInfo);
}




/****************************************************************
* 功能描述: 数据入队列
* 输入参数: tQueueData-队列数据
* 输出参数: 无
* 返 回 值: 0-成功   -1-失败
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
* -------------------------------------------------------------
* 20160811        V1.0     Zhou Zhaoxiong     创建
****************************************************************/
INT32 EnQueue(T_StructInfo tQueueData)
{
    INT32  iRetVal  = 0;
    UINT32 iNextPos = 0;


    pthread_mutex_lock(&g_mutex_queue_cs);
    iNextPos = g_iQueueTail + 1;


    if (iNextPos >= MAX_QUEUE)
    {
        iNextPos = 0;
    }


    if (iNextPos == g_iQueueHead)
    {
        iRetVal = -1;   // 已达到队列的最大长度
    }
    else
    {
        // 入队列
        memset(&g_tQueue[g_iQueueTail], 0x00,  sizeof(T_StructInfo));
        memcpy(&g_tQueue[g_iQueueTail], &tQueueData, sizeof(T_StructInfo));


        g_iQueueTail = iNextPos;
    }


    pthread_cond_signal(&queue_cv);
    pthread_mutex_unlock(&g_mutex_queue_cs);


    return iRetVal;
}




/****************************************************************
* 功能描述: 数据出队列
* 输入参数: ptStructData-队列数据
* 输出参数: 无
* 返 回 值: 0-成功   -1-失败
* 其他说明: 无
* 修改日期       版本号        修改人        修改内容
* -------------------------------------------------------------
* 20160811        V1.0     Zhou Zhaoxiong     创建
****************************************************************/
INT32 DeQueue(T_StructInfo *ptStructData)
{
    T_StructInfo tQueueData = {0};


    if (ptStructData == NULL)
    {
        return -1;
    }


    pthread_mutex_lock(&g_mutex_queue_cs);


    while (g_iQueueHead == g_iQueueTail)
    {
        pthread_cond_wait(&queue_cv, &g_mutex_queue_cs);
    }


    memset(&tQueueData, 0x00, sizeof(T_StructInfo));
    memcpy(&tQueueData, &g_tQueue[g_iQueueHead], sizeof(T_StructInfo));
    g_iQueueHead ++;


    if (g_iQueueHead >= MAX_QUEUE)
    {
        g_iQueueHead = 0;
    }


    pthread_mutex_unlock(&g_mutex_queue_cs);
    memcpy(ptStructData, &tQueueData, sizeof(T_StructInfo));


    return 0;
}




/**********************************************************************
* 功能描述: 程序休眠
* 输入参数: iCountMs-休眠时间(单位:ms)
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
* 修改日期      版本号       修改人        修改内容
* ------------------------------------------------------------------
* 20160811       V1.0     Zhou Zhaoxiong     创建
********************************************************************/ 
void Sleep(UINT32 iCountMs)
{
    struct timeval t_timeout = {0};


    if (iCountMs < 1000)
    {
        t_timeout.tv_sec  = 0;
        t_timeout.tv_usec = iCountMs * 1000;
    }
    else
    {
        t_timeout.tv_sec  = iCountMs / 1000;
        t_timeout.tv_usec = (iCountMs % 1000) * 1000;
    }
    select(0, NULL, NULL, NULL, &t_timeout);    // 调用select函数阻塞程序
}

程序运行情况
我们将上面编写好的QueueUse.c文件上传到Linux机器上,使用“gcc -g -o QueueUseQueueUse.c”命令编译之后,生成QueueUse文件。之后,执行“QueueUse”命令,即可看到程序的运行结果(结果会不断地更新)如下:

~/zhouzx/Test/QueueUse> QueueUse
PutDataIntoQueue: ID=0, Info=zhou0

GetDataFromQueue: ID=0, Info=zhou0
PutDataIntoQueue: ID=1, Info=zhou1
GetDataFromQueue: ID=1, Info=zhou1
PutDataIntoQueue: ID=2, Info=zhou2
GetDataFromQueue: ID=2, Info=zhou2
PutDataIntoQueue: ID=3, Info=zhou3
GetDataFromQueue: ID=3, Info=zhou3

我们看到,数据先是被加入到队列中,然后再从队列中取出来。

程序说明
第一,在本程序中,入队列和出队列是在同一个函数中完成的,但是,在实际开发项目的程序中,入队列和出队列一般是在不同的程序流程(两个不同的线程)中完成的。

第二,本程序的数据入队列操作是在EnQueue函数中完成的,数据出队列操作是在DeQueue函数中完成的,全局变量g_tQueue用于存放需要处理的数据。

第三,在实际开发项目的程序中,有可能会有很多流程都会调用入队列和出队列的函数,为了防止多个流程同时向队列中加入数据或取出数据,在EnQueue和DeQueue函数中使用了锁操作。也就是说,在操作数据之前,先用pthread_mutex_lock函数执行加锁操作,在处理完数据之后,再用pthread_mutex_unlock函数执行解锁操作。

第四,在实际开发项目中,为了防止程序从队列中取数据的速率过快而使得下游模块处理不过来,我们常在从队列取出数据之后发消息的流程中控制数据的发送速率,具体每秒钟发送多少条可在配置文件中设置。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
12.24 Linux查看内存使用状态(free命令)
free 命令用来显示系统内存状态,包括系统物理内存、虚拟内存(swap 交换分区)、共享内存和系统缓存的使用情况,其输出和 top 命令的内存部分非常相似。
0 0
【Linux】之【磁盘】相关的命令及解析[df、du、iostat、iotop]
df命令来自于英文词组”Disk Free“的缩写,其功能是用于显示系统上磁盘空间的使用量情况。df命令显示的磁盘使用量情况含可用、已有及使用率等信息,默认单位为Kb,建议使用-h参数进行单位换算。
0 0
【Linux】之【网络】相关的命令及解析[ethtool、nload、nethogs、iftop、iptraf、ifstat]
ethtool命令用于查询ethX网口基本设置、及设置网卡的参数。
0 0
【Linux】综合性命令及解析【top、htop、vmstat、dstat、glances、sar】
top命令的功能是用于实时显示系统运行状态,包含处理器、内存、服务、进程等重要资源信息。运维工程师们常常会把top命令比作是“加强版的Windows任务管理器”,因为除了能看到常规的服务进程信息以外,还能够对处理器和内存的负载情况一目了然,实时感知系统全局的运行状态,非常适合作为接手服务器后执行的第一条命令。
0 0
vos3000怎样解决费率表导入时精度丢失,Linux 硬件信息查询命令是怎样的
vos3000怎样解决费率表导入时精度丢失,Linux 硬件信息查询命令是怎样的
0 0
再也不用百度了!快速构建自己的Linux命令查询系统
刚学Linux是不是被很多命令吓到了?其实可以部署一套自己的Linux命令查询系统,随时查询。
0 0
Linux命令总结
Linux命令总结
0 0
Linux巩固篇004-Linux Shell 命令脚本
纸上得来终觉浅,绝知此事要躬行
0 0
NFS (网络文件系统) | CentOS7 升级系统和内核 | Linux man 命令汉化
NFS (网络文件系统) | CentOS7 升级系统和内核 | Linux man 命令汉化
0 0
+关注
周兆熊
硕士研究生毕业于南京邮电大学计算机应用技术专业,曾在中兴通讯从事软件开发工作,现就职于重庆某物联网技术公司,任高级嵌入式软件开发工程师。著有《C程序员从校园到职场》一书,同时也是《信息通信技术百科全书》的编者之一及CSDN博客专家。QQ(微信):245924426。
文章
问答
文章排行榜
最热
最新
相关电子书
更多
从 Linux 系统内核层面来解决实际问题的实战经验
立即下载
ECS系统指南之Linux系统诊断
立即下载
深入解析数据存储技术原理及发展演进—Linux开源存储技术
立即下载