Linux下入队列和出队列操作的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函数执行解锁操作。

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

时间: 2024-12-21 07:33:37

Linux下入队列和出队列操作的C代码示例的相关文章

Linux下互斥量加锁与解锁操作的C代码实现

一.概述 在实际的软件程序中,由于代码量较大,函数之间的调用关系较为复杂,因此对于某些全局变量的操作要格外小心.在程序中,一般采用互斥量加锁的方式来保证对全局变量的操作的唯一性. 本文详细介绍了Linux下互斥量加锁与解锁操作的C代码实现,为相关的软件开发工作的开展提供了有益的参考. 二.加锁与解锁函数及时间结构体介绍 1.加锁函数pthread_mutex_timedlock 函数原型:int pthread_mutex_timedlock(pthread_mutex_t *restrict

软件开发实践中的入队列和出队列操作的C代码示例

概述 最近有在校的学生朋友在问我,数据结构中的队列在实际的软件开发项目中有什么样的用处. 大家都知道,队列的特点是先入先出,即数据是按照入队列的顺序出队列的.在实际的软件开发项目中,当一个中间模块需要接收和发送大量的消息时,队列就可以大展身手了.我们可以将接收到的数据存储在一个全局队列中,然后在另外的程序流程中将数据从同一个全局队列中取出来,经过一定的处理之后将消息发送到另外的模块.这样做可以降低程序的性能瓶颈. 本文用实际的C代码示例了简单的数据入队列和出队列的方法,大家可据此了解队列的实际用

多线程-队列:构造队列 完成入队列和出队列的函数

问题描述 队列:构造队列 完成入队列和出队列的函数 用C++实现 (队列支持多线程:一个线程做入队列操作而另一个做出队列操作,两队列同时进行) 队列中存放int数据 类名MyQueue ///把key追加到队列中 void MyQueue::Push(int key) ///从队列中获取一个值///成功返回true 失败false bool MyQueue::pop(int& key) ///获取当前队列大小(队列中包含有效数据个数)int MyQueue::GetSize() 求大神指导下这道

c++-关于C++的入栈和出栈操作

问题描述 关于C++的入栈和出栈操作 使用模板实现一个栈类,实现入栈和出栈操作,分别测试doubleintcharlongbool等类型 解决方案 http://wenku.baidu.com/link?url=FSCYEuOOM_QSZUMRDTi8NV8lyVP0G6pBXPzZ7SbH9ZLskbNUr6dHsX75CPgh1xH2pukZB40OozK9zSNHx4l1sGmesAOa6tAXGlDcLm2d21m 解决方案二: http://zhidao.baidu.com/link?

请问测试linux下某个jsp站点cpu和内存占用率代码怎么写?

问题描述 请问测试linux下某个jsp站点cpu和内存占用率代码怎么写?谢谢! 解决方案 解决方案二:up解决方案三:Up解决方案四:Up解决方案五:http://www.diybl.com/course/4_webprogram/jsp/jsp_js/20090212/155296_3.html看看这个~·解决方案六:思路就是调用linux下的命令然后分析输出的结果.解决方案七:继续问解决方案八:Runtimerun=Runtime.getRuntime();Processpro=run.e

【数据结构之旅】顺序栈的定义、初始化、空栈判断、入栈、出栈操作

说明:     往前学习数据结构,想运行一个完整的顺序栈的程序都运行不了,因为书上给的都是一部分一部分的算法,并没有提供一个完整可运行的程序,听了实验课,自己折腾了一下,总算可以写一个比较完整的顺序栈操作的小程序,对于栈也慢慢开始有了感觉.下面我会把整个程序拆开来做说明,只要把这些代码放在一个文件中,用编译器就可以直接编译运行了. 一.实现 1.程序功能   关于栈操作的经典程序,首当要提及进制数转换的问题,利用栈的操作,就可以十分快速地完成数的进制转换. 2.预定义.头文件导入和类型别名   

Linux下通过script 命令记录(数据库)操作步骤

对DBA而言,经常碰到升级数据库或是apply patch,以及有些时候需要运行大量的脚本.对于这些操作我们希望现在在屏幕同时又输出的文件以备后续查询过程中曾经丢失的步骤或错误.Linux下的script命令就是解决这个问题的好帮手   1.script命令描述   复制代码 代码如下: script命令会记录所有的操作到文件同时在屏幕上输出,直到终止登陆的会话,或使用CRTL+D,或使用exit退出则停止记录. 这个命令对于数据库的升级或是重要设置的情形下使用可以用于后续查询操作成功或失败.

Linux下C编程:消息队列实例

消息队列是一系列连续排列的消息,保存在内核中,通过消息队列的引用标识符来访问.消息队列与管道很相似,但使用消息队列的好处是对每个消息指定了特定消息类型,接收消息的进程可以请求接收下一条消息,也可以请求接收下一条特定类型的消息. #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <string.h> int mai

linux下管理员强行踢出用户的命令使用方法

  linux强制踢出用户命令: 一.输入w命令查看已登录用户信息 [root@KW_S01_192.168.1.106_A ~]# w 19:22:31 up 2:11, 3 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.1.178 18:41 0.00s 0.16s 0.01s w root pts/1 192.168.1.178 19:22