linux下多线程间通信之信号量,消息队列的综合运用

一、消息队列介绍
消息队列是消息的链接表,存放在内核中。其实质上就是一个内核链表,消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。对消息队列有写权限的进程可以按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读出消息。消息队列是随内核持续的并和进程相关,
系统中记录消息队列的数据结构 (struct ipc_ids msg_ids)位于内核中,系统中的所有消息队列都可以在结构msg_ids中中找到访问入口。只有在内核重起或者显示删除一个消息队列时,该消息队列才会真正被删除。基于此原因,在做过的项目中曾经碰到过一个问题:当在调试程序完后让程序退出按下”ctrl+c”后,消息队列并未删除,此时再运行此程序可能会跑不起来的BUG,原因是没有删除的消息队列中有数据,这个时候接受者将其取出处理的结果是未知的,特别是当取出队列中的值是指针时,可以想象这时必死。

个人认为消息队列并不能实现进程之间的同步,还需要一些其它的操作来控制发送的是同步消息还是异步消息。
同步消息:进程A向进程B发送一个消息后,要等到进程B处理完由A发送来的 消息以后进程A才可以往下执行。否则进程A将一直等待不会往下执行。
异步消息:进程A向进程B发送一个消息后,进程A不管进程B处理完消息与否都往下执行。

1、IPC标识符
消息队列, 信号量和共享存储段, 都属于内核中的IPC结构, 它们都用标识符来描述.。这个标识符是一个非负整数, 与文件描述符不同的是, 创建时并不会重复利用通过删除回收的整数, 而是每次+1, 直到整数最大值回转到0。

2、IPC 关键字
标识符是IPC对象的内部名, 而它的外部名则是key(键), 它的基本类型是key_t, 在头文件中定义为长整型. 键由内核变换成标识符。linux一般用f t o k ( )函数来生成关键字。

二、ipcs 命令
命令ipcs用于读取System V IPC目标的状态。
ipcs -q: 只显示消息队列。
ipcs -s: 只显示信号量。
ipcs -m: 只显示共享内存。
ipcs –help: 其他的参数。
下面是ipcs命令输出的例子:
xxx@xxx-desktop:~$ ipcs

—— Shared Memory Segments ——–
key shmid owner perms bytes nattch status
0x00000000 0 ding 600 393216 2 dest
0x00000000 32769 ding 600 393216 2 dest
0x00000000 65538 ding 600 393216 2 dest
0x00000000 98307 ding 600 393216 2 dest
0x00000000 131076 ding 600 393216 2 dest
0x00000000 163845 ding 600 393216 2 dest
0x00000000 196614 ding 600 393216 2 dest
0x00000000 229383 ding 600 393216 2 dest
0x00000000 262152 ding 600 393216 2 dest
0x00000000 294921 ding 600 393216 2 dest
0x00000000 327690 ding 600 393216 2 dest
0x00000000 360459 ding 600 393216 2 dest
0x00000000 393228 ding 600 393216 2 dest
0x00000000 425997 ding 600 393216 2 dest
0x00000000 458766 ding 600 393216 2 dest
0x00000000 491535 ding 600 393216 2 dest
0x00000000 557072 ding 600 393216 2 dest
0x00000000 589841 ding 600 393216 2 dest

—— Semaphore Arrays ——–
key semid owner perms nsems
0x00000000 32768 root 666 1

—— Message Queues ——–
key msqid owner perms used-bytes messages

三、消息队列的相关函数
1、创建消息队列函数。

int msgget(key_t key, int msgflg)

参数:
key:消息队列关联的键。
msgflg:消息队列的建立标志和存取权限。
返回说明:
成功执行时,返回消息队列标识值。失败返回-1。
2、向消息队列中发送消息。

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)

参数:
msqid:消息队列的识别码。
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下
struct msgbuf {
long mtype; /* 消息类型,必须 > 0 */
char mtext[1]; /* 消息文本 */
};
msgsz:消息的大小。
msgtyp:从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都会被读取。
msgflg:用来指明核心程序在队列没有数据的情况下所应采取的行动。如果msgflg和常数IPC_NOWAIT合用,则在msgsnd()执行时若是消息队列已满,则msgsnd()将不会阻塞,而会立即返回-1,如果执行的是msgrcv(),则在消息队列呈空时,不做等待马上返回-1,并设定错误码为ENOMSG。当msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取阻塞等待的处理模式。

返回说明:
成功执行时,返回0, 失败返回-1。
3、从消息队列读取信息。

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)

参数: 同上。
成功执行时,返回0, 失败返回-1。
4、在消息队列上执行指定的操作。

int msgctl(int msqid, int cmd, struct msqid_ds *buf)

根据参数的不同和权限的不同,可以执行检索、删除等的操作。
参数:
msqid:消息队列的识别码。
buf: 消息队列进行的操作,它可以是:
(1) IPC_STAT: 取出系统保存的消息队列的msqid_ds 数据,并将其存入参数buf 指向的msqid_ds 结构中。msqid_ds 数据中唯一能被设定的只有msg_perm 成员,其是ipc_perm 类型的数据。而ipc_perm 中能被修改的只有mode,pid 和uid 成员。其他的都是只能由系统来设定。
(2) IPC_SET: 设定消息队列的msqid_ds 数据中的msg_perm 成员。设定的值由buf 指向的msqid_ds结构给出。
(3) IPC_EMID:将队列从系统内核中删除。

四、实例
以下的实例是基于的上一篇我写的文章Linux下多线程编程实例解析修改的:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>


#include "module.h"
#include "message.h"

void thread_one_msg_init(message_receive_t& message_receive)
{   
    message_receive.add_source_id(THREAD_TWO_ID);
}

/***************************thread_one_main主函数****************************************/
void *thread_one_main(void* arg) 
{
    message_receive_t message_receive;
    thread_one_msg_init(message_receive);
    while(true)
    {   
        sleep(3);       
        message_receive.wait_message(MSG_NOERROR);
        printf("MODULE ONE main func++++++++++++\n");
    }
}
/***********thread_two_main主函数********************/
void *thread_two_main(void* arg) 
{
    while(true)
    {
        printf("MODULE TWO main func------------\n");
        sleep(3);
    }
}
int main(void)
{
    init_main_thread_info();
    init_thread_list();

    mod_if_register_thread(THREAD_ONE_ID,
                            INIT_TOP_RIGHT,
                            1,
                            const_cast<char *>("test thread1~~~"),
                            NULL,
                            thread_one_main,
                            SCHED_OTHER);
    mod_if_register_thread(THREAD_TWO_ID,
                            INIT_TOP_RIGHT,
                            3,
                            const_cast<char *>("test thread2~~~"),
                            NULL,
                            thread_two_main,
                            SCHED_OTHER);
    init_module_manager();


}

message.cpp文件

#include <iostream>
#include <string>
#include <tr1/memory>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <typeinfo>
#include <stdlib.h>

#include "message.h"
using namespace std;
/******************************************************************* define *******************************************************************/
#define MAX_MSG_TYPE_NUM 50
#define MAX_MODULE_NUM 20
#define MAX_MSG_BUFFER 100

const static int syn_message_type = 1;
const static int asyn_message_type = 2;

/******************************************************************* type defines *******************************************************************/

struct gos_message_t
{
    int reserved;
    nsp_mssage_t nsp_mssage;
};

/*******获取目的模块的消息队列ID***************/
message_send_t::message_send_t(int _destination_id)
{
    destination_id = _destination_id;
}
/**************发送同步消息**************/
int message_send_t::send_syn_message(int message_id,
    void *in_message, int message_size)
{
    if(message_id < 0)
        return -1;
    if(message_size != sizeof(void *))
        message_size = sizeof(void *);

    add_message_common_header(get_message_buffer(),message_size, message_id);

    nsp_mssage_t & nsp_message = get_message_buffer();
    set_mssage_text(&nsp_message, in_message, message_size);
    send_message(nsp_message, syn_message_type, sizeof(nsp_mssage_t));

    int source_module_id = mod_if_get_current_module_id();
    int semaphore_id = mod_if_get_sem_id(source_module_id);
    if(semaphore_id == 0)
    {
        cout<<"the pointer is NULL"<<endl;
        return -1;
    }
    sem_wait((sem_t*)semaphore_id);
    return 0;
}
/**************发送异步消息************/
int message_send_t::send_asyn_message(int message_id, void *in_message, int message_size)
{
    if(message_id < 0)
    {
        cout<<"message_id < 0"<<endl;
        return -1;
    }
    if(message_size > CFG_MAX_MSG_SIZE)
    {
        cout<<"message_size too big"<<endl;
        message_size = CFG_MAX_MSG_SIZE;
    }
    //使用unique_ptr这个独享所有权的指针智能管理p_uniqure_msg
    unique_ptr<unsigned char[]> p_uniqure_msg(new unsigned char[message_size+sizeof(nsp_messsge_head_t)]);
    nsp_mssage_t* p_msg = (nsp_mssage_t*)p_uniqure_msg.get();

    add_message_common_header(*p_msg, message_size, message_id);

    memcpy(p_msg->msg_data.msg,in_message,message_size);

    send_message(*p_msg, asyn_message_type, sizeof(nsp_messsge_head_t)+message_size);

    return 0;
}
/**************************获取消息返回值**************************************/
int message_send_t::get_return_value(void)
{
    nsp_mssage_t& message_buffer_instance =  get_message_buffer();
    get_message_ret_code(&message_buffer_instance);
}

/************************发送消息*******************************************/
void message_send_t::send_message(nsp_mssage_t& message_buffer,
                                        int message_type,
                                        int message_size)
{
    set_message_syn(&message_buffer, message_type);
    message_buffer.header.reservered = get_message_id(&message_buffer); //the "msgrcv()" requare message type, must be > 0 

    int destination_id = get_destination_id();
    int qunue_id = mod_if_get_msgque_id(destination_id);

    int return_v = msgsnd(qunue_id, &message_buffer, message_size-sizeof(message_buffer.header.reservered), 0);
    if(return_v < 0)
    {
        cout<<"message_send_t::send_message gos_msgsnd failed"<<endl;
    }
}
/**************************获取目的模块ID*****************************************/
void message_send_t::add_message_common_header(nsp_mssage_t& nsp_message,
                                                            int message_size,
                                                            int message_id)
{
    set_message_id(&nsp_message,message_id );
    int source_module_id = pthread_self();//获取自身线程的ID
    set_message_srcmodule(&nsp_message, source_module_id);
    int destination_id = get_destination_id();
    set_message_destmodule(&nsp_message, destination_id);
    set_message_data_length(nsp_message, message_size);
}

/********************************获取目的模块ID**********************************/
int message_send_t::get_destination_id(void)
{
    return destination_id;
}

/*****************************获取消息缓冲区*************************************/

struct nsp_mssage_t& message_send_t::get_message_buffer(void)
{
    return message_buffer;
}
/************************构造函数,初始化目的模块ID******************************************/
message_receive_t::message_receive_t()
{
    destination_module_id = THREAD_ZERO_ID;
    message_id = 100;
}

/**********************注册接收端消息类型*********************************************/
int message_receive_t::register_message(deal_message_t* deal_message)
{
    message_map[message_id] = deal_message;

    return message_id ++;
}
/***************************等待消息****************************************/
int message_receive_t::wait_message(int msgflg, int msg_id)
{
    nsp_mssage_t& nsp_message_header = get_nsp_message_header();
    int return_v = get_message(msgflg, nsp_message_header, msg_id);

    if(return_v < 0)
    {
        return return_v;
    }   

    return_v = deal_message();
    if(return_v < 0)
    {
        cout<<"deal_message error"<<endl;
        return return_v;
    }

    int syn_flag = get_message_syn(&nsp_message_header);
    if(syn_message_type == syn_flag)
    {
        send_ack_semaphore();
    }

    return return_v;
}

/******************************设定目的模块ID*************************************/
 void message_receive_t::set_destination_id(int id)
{
    if(destination_module_id == THREAD_ZERO_ID)
        destination_module_id = id;
}

/*******************************添加消息源模块ID************************************/
 void message_receive_t::add_source_id(int id)
{
    source_module_id_array.push_back(id);
}
/**************************** 打印最近一次消息的消息源模块名字 **************************************/
void message_receive_t::print_recent_source_module_name(void)
{
    nsp_mssage_t& nsp_message_header = get_nsp_message_header();
    string name = mod_if_get_module_name(nsp_message_header.header.srcmodule);
    cout<<"source module name = "<<name<<endl;
}
/***************************判断源模块是否合法****************************************/
int message_receive_t::is_source_module_id_invalid(MODULE_IDS module_id)
{
    int not_found_id = TRUE;

    for(int i = 0; i < source_module_id_array.size();i++)
    {
        if(source_module_id_array[i] == module_id)
        {
            not_found_id = FALSE;
        }
    }

    return not_found_id;
}

/*************************判断目的模块ID是否合法******************************************/
int message_receive_t::is_destination_module_id_invalid(MODULE_IDS module_id)
{
    if(destination_module_id == module_id)
    {
        return FALSE;
    }else
    {
        return TRUE;
    }
}
/****************************获取消息buffer地址***************************************/
nsp_mssage_t&  message_receive_t::get_nsp_message_header(void)
{
    return nsp_message.header;
}

/********************************获取消息***********************************/
int message_receive_t::get_message(int msgflg,nsp_mssage_t& nsp_message, int msg_id)
{
    int queue_id = get_queue_id();
    int return_v = msgrcv(queue_id,&nsp_message,sizeof(nsp_message_rececive_t),msg_id,msgflg);

    return return_v;
}

/*************************获取对应模块的消息队列ID******************************************/
int message_receive_t::get_queue_id(void)
{
    int module_id = 0;

    module_id = mod_if_get_current_module_id();
    int queue_id = mod_if_get_msgque_id(module_id);
    return queue_id;
}
/**************************获取对应模块的信号量队列ID*****************************************/
sem_t* message_receive_t::get_semaphore_id(MODULE_IDS module_id)
{
    int id = 0;

    id = mod_if_get_sem_id(module_id);

    return reinterpret_cast<sem_t*>(id) ;
}

/************************通知消息发送模块,消息处理完成。*******************************************/
void message_receive_t::send_ack_semaphore(void)
{
    nsp_mssage_t& nsp_message = get_nsp_message_header();
    int source_module = get_message_srcmodule(&nsp_message);
    sem_t* source_semaphore_id = get_semaphore_id(static_cast<MODULE_IDS>(source_module));
    sem_post(source_semaphore_id); 
}
/************************构造函数******************************************/
deal_message_t::deal_message_t()
{
    set_message_length(sizeof(void*));
}

/******************************消息处理*************************************/
void deal_message_t:: deal(nsp_mssage_t *message_buffer)
 {
    if(is_message_length_valid(message_buffer, message_length) == FALSE)
    {
        cout<<"deal_message_t:: deal::message length error::"<<typeid(*this).name()<<endl;
    }

    deal_message(message_buffer);
 }

/************************设定目的模块值给源模块******************************************/
void deal_message_t::set_message_value(struct nsp_mssage_t * in_buffer, long double value)
{
    set_mssage_fp64_text(in_buffer, value);
}
/*******************************设定目的模块值给源模块************************************/
void deal_message_t::set_message_value(struct nsp_mssage_t * in_buffer, int value)
{
    set_mssage_int32_text(in_buffer,value);
}

/*******************************设定目的模块值给源模块************************************/
void deal_message_t::set_message_value(struct nsp_mssage_t * in_buffer, void* message, int message_size)
{
    set_mssage_pointer_text( in_buffer, 
                        message, 
                        message_size);
}

/*****************************设定消息返回值**************************************/
void deal_message_t::set_message_return_value(struct nsp_mssage_t * in_buffer, int value)
{
    set_message_ret_code(in_buffer, value);
}

/*****************************获取消息的值**************************************/
void deal_message_t::get_message_value(struct nsp_mssage_t * in_buffer, long double *out_value)
{
    *out_value = get_mssage_fp64_text(in_buffer);
}
/*****************************获取消息值**************************************/
void deal_message_t::get_message_value(struct nsp_mssage_t * in_buffer, int *out_value)
{
    *out_value = get_mssage_int32_text(in_buffer);
}

/****************************获取消息值**************************************/
void*  deal_message_t::get_message_value(struct nsp_mssage_t * in_buffer)
{
    int length = get_message_text_length(in_buffer);
    void* message_buffer = NULL;
    if(in_buffer->header.syn == syn_message_type)
    {
        message_buffer = get_mssage_text_address(in_buffer,length);
    }else if(in_buffer->header.syn == asyn_message_type)
    {
        message_buffer = (void*)&in_buffer->msg_data.msg[0];
    }   
    return message_buffer;
}
/*****************************获取消息长度**************************************/
int deal_message_t::get_message_data_length(struct nsp_mssage_t * in_buffer)
{
    int length = get_message_text_length(in_buffer);

    return length;
}

/********************设定消息长度***********************************************/
void deal_message_t::set_message_length(int length)
{
    message_length = length;
}

/***************************获取消息长度****************************************/
int deal_message_t::get_message_length(void)
{
    return message_length;
}
/*********************************判断消息长度是否合法**********************************/
 int deal_message_t::is_message_length_valid(struct nsp_mssage_t * in_buffer, 
                                                                                                        const  int standard_lenth) 
{
    int message_length = get_message_text_length(in_buffer);
    if(message_length > standard_lenth)
    {
        return FALSE;
    }else
    {
        return TRUE;
    }
}

/****************************设定消息标志***************************************/
void set_message_flag(struct nsp_mssage_t *in_buffer, int flag)
{
    in_buffer->header.flag = flag;
}
/*****************************设置消息为同步消息或者为异步消息**************************************/
void set_message_syn(struct nsp_mssage_t *in_buffer, int syn)
{
    in_buffer->header.syn = syn;
}

/***************************设置消息的ID****************************************/
void set_message_id(struct nsp_mssage_t *in_buffer, int type)
{
    in_buffer->header.msg_type = type;
}

/***************************设定消息返回值****************************************/
void set_message_ret_code(struct nsp_mssage_t *in_buffer, int ret_code)
{
    in_buffer->header.ret_code = ret_code;
}

/************************设置目的模块的消息队列ID******************************************/
void set_message_destmodule(struct nsp_mssage_t *in_buffer, int destmodule)
{
    in_buffer->header.destmodule = destmodule;
}
/************************设置源模块的消息队列ID******************************************/
void set_message_srcmodule(struct nsp_mssage_t *in_buffer, int srcmodule)
{
    in_buffer->header.srcmodule = srcmodule;
}

/***************************:获取对应模块的消息队列ID****************************************/
int set_mssage_text(struct nsp_mssage_t *const in_buffer, 
                        void const *text, 
                        int in_buffer_length)
{
    if(in_buffer == NULL)
    {
        return -1;
    }
    if(text == NULL)
    {
        return -1;
    }
    in_buffer->msg_data.ptext = const_cast<void *>(text);
}
/*************************将消息内容转换为long double类型******************************************/
int set_mssage_fp64_text(struct nsp_mssage_t *const in_buffer, long double data)
{
    if(in_buffer == NULL)
    {
        return -1;
    }
    if(in_buffer->msg_data.ptext == NULL)
    {
        return -1;
    }

    long double *ptext = reinterpret_cast<long double *>(in_buffer->msg_data.ptext);
    *ptext = data;
}

/**************************将消息内容转换为long double类型*****************************************/
int set_mssage_int32_text(struct nsp_mssage_t *const in_buffer, int data)
{
    if(in_buffer == NULL)
    {
        return -1;
    }
    if(in_buffer->msg_data.ptext == NULL)
    {
        return -1;
    }

    int *ptext =  reinterpret_cast<int *>(in_buffer->msg_data.ptext);
    *ptext = data;
}
/****************************将消息内容转换为void *类型***************************************/
int set_mssage_pointer_text(struct nsp_mssage_t *const in_buffer, 
                                            void const *text, 
                                            int in_buffer_length)
{
    if(in_buffer == NULL)
    {
        return -1;
    }
    if(in_buffer->msg_data.ptext == NULL)
    {
        return -1;
    }
    memcpy(in_buffer->msg_data.ptext, text, in_buffer_length);
}

/****************************消息数据的长度***************************************/
int set_message_data_length(nsp_mssage_t& in_buffer, int length)
{
    in_buffer.header.data_length = length;
}
/*******************************************************************/
int get_message_flag(struct nsp_mssage_t *in_buffer)
{
    return in_buffer->header.flag;
}

/*************************或许消息同步标致段******************************************/
int get_message_syn(struct nsp_mssage_t *header)
{
    return header->header.syn;
}

/*************************获取消息类型******************************************/
int get_message_id(struct nsp_mssage_t *in_buffer)
{
    return in_buffer->header.msg_type;
}

/*****************************获取返回值**************************************/
int get_message_ret_code(struct nsp_mssage_t *in_buffer)
{
    return in_buffer->header.ret_code;
}
/************************获取源模块ID*******************************************/
int get_message_srcmodule(const struct nsp_mssage_t *in_buffer)
{
    return in_buffer->header.srcmodule;
}


/***************************获取目的模块ID****************************************/
int get_message_destmodule(struct nsp_mssage_t *in_buffer)
{
    return in_buffer->header.destmodule;
}

/***************************获取消息内容地址****************************************/
void* get_mssage_text_address(struct nsp_mssage_t *const in_buffer, 
                                    int out_buffer_length)
{
    if(out_buffer_length < in_buffer->header.data_length)
    {
        return static_cast<void*>(NULL);
    }
    if(in_buffer->msg_data.ptext == NULL)
    {
        return static_cast<void*>(NULL);
    }
     void* out_buffer = in_buffer->msg_data.ptext;

    return out_buffer;
}
/***************************获取 float 消息****************************************/
float get_mssage_fp64_text(struct nsp_mssage_t *const in_buffer)
{
    if(in_buffer->msg_data.ptext == NULL)
    {
        return -1;
    }
    if(sizeof(void*) != in_buffer->header.data_length)
    {
        return -1;
    }

    float * ptext = (float *)in_buffer->msg_data.ptext;

    return *ptext;
}

/****************************获取 int 消息***************************************/
int get_mssage_int32_text(struct nsp_mssage_t *const in_buffer)
{
    if(in_buffer->msg_data.ptext == NULL)
    {
        return -1;
    }
    if(sizeof(void*) != in_buffer->header.data_length)
    {
        return -1;
    }


    int * ptext = (int *)in_buffer->msg_data.ptext;

    return *ptext;
}
 /**********************获取消息长度*********************************************/
int get_message_text_length(struct nsp_mssage_t *const in_buffer)
{
    int data_length = in_buffer->header.data_length;
    return data_length;
}

message.h文件

#ifndef MESSAGE_H
#define MESSAGE_H
#if __cplusplus

/******************************************************************* include file *******************************************************************/
#include <vector>
#include <map>
#include "module.h"
//#include <atomic>


/******************************************************************* define *******************************************************************/
#define ASYNC 0
#define SYNC 1
#define TRUE 1
#define FALSE 0
/******************************************************************* type defines *******************************************************************/
using namespace std;


typedef void (*msg_type_f_t)(int, void*);

class deal_message_t;

#define CFG_MAX_MSG_SIZE (sizeof(char)*10*1024)//最大发送10k字节异步消息

union message_data_t{   
    void* ptext;    
    long double float_data; 
    int int_data;   
    unsigned char msg[0];
};
struct nsp_messsge_head_t{  
    unsigned int reservered;//4
    unsigned int version:8;
    unsigned int flag:4;
    unsigned int syn:4;
    unsigned int msg_type:16;
    unsigned int ret_code:32;
    unsigned int sn:16;
    unsigned int srcmodule:8;
    unsigned int destmodule:8;
    unsigned int reserver0:32;
    unsigned int reserver1:16;
    unsigned int data_length:16;
};
struct nsp_mssage_t
{
    nsp_messsge_head_t header;  
    message_data_t msg_data;
};

struct nsp_message_rececive_t
{
    nsp_mssage_t header;
    signed char data[CFG_MAX_MSG_SIZE];
};
class message_send_t
{
    public:
    explicit message_send_t(int _destination_id);
    int send_syn_message(int message_id,
                                    void *in_message,
                                    int message_size);
    int send_asyn_message(int message_id,                               
                                    void *in_message,
                                    int message_size);
    int get_return_value(void); private:
    void send_message(nsp_mssage_t& message_buffer,                                     
                            int message_type,                                       
                            int message_size);      
    void add_message_common_header(nsp_mssage_t& nsp_mssage,
                                                    int message_size,
                                                    int message_id);        
    int get_destination_id(void);           
    struct nsp_mssage_t& get_message_buffer(void);

    struct nsp_mssage_t message_buffer;     // 消息缓冲区
    int destination_id;//向哪个模块发送消息
};
class message_receive_t
{
    public:
        explicit message_receive_t();       
        virtual int register_message(deal_message_t* deal_message);
        virtual int wait_message(int msgflg, int msg_id = 0);       
        void set_destination_id(int id);        
        void add_source_id(int id);

        void print_recent_source_module_name(void);
    private:
        message_receive_t(const message_receive_t&);        
        message_receive_t& operator=(const message_receive_t&);

        int deal_message(void);

        int is_source_module_id_invalid(MODULE_IDS module_id);
        int is_destination_module_id_invalid(MODULE_IDS module_id);
        nsp_mssage_t& get_nsp_message_header(void);     
        int get_message(int msgflg,nsp_mssage_t& nsp_message, int msg_id = 0);
        int get_queue_id(void);     
        sem_t* get_semaphore_id(MODULE_IDS module_id);
        void send_ack_semaphore(void);

        nsp_message_rececive_t nsp_message;// syn message 

        int message_id;
        int destination_module_id;
        vector <int>  source_module_id_array;
        map<int,deal_message_t*> message_map; 
};
typedef void (*INIT_MSG)(message_receive_t& );
class deal_message_t
 {
    public:
        deal_message_t();
        virtual void deal(nsp_mssage_t *message_buffer);    
    protected:
            virtual void deal_message(struct nsp_mssage_t * in_buffer) = 0; 
            void set_message_value(struct nsp_mssage_t * in_buffer, long double value);         
            void set_message_value(struct nsp_mssage_t * in_buffer, int value);
            void set_message_value(struct nsp_mssage_t * in_buffer, void* message, int message_size);          
            void set_message_return_value(struct nsp_mssage_t * in_buffer, int value);

            void get_message_value(struct nsp_mssage_t * in_buffer, long double *out_value);        
            void get_message_value(struct nsp_mssage_t * in_buffer, int *out_value);
            void* get_message_value(struct nsp_mssage_t * in_buffer);        
            int get_message_data_length(struct nsp_mssage_t * in_buffer);
            void set_message_length(int length);
            int get_message_length(void);

    private:
            int is_message_length_valid(struct nsp_mssage_t * in_buffer,                                             
                                                    const  int standard_lenth) ;
            int is_set_message(struct nsp_mssage_t * in_buffer);        
    int message_length;
};
void set_message_flag(struct nsp_mssage_t *in_buffer, int flag);
void set_message_syn(struct nsp_mssage_t *in_buffer, int syn);
void set_message_id(struct nsp_mssage_t *in_buffer, int type);
void set_message_ret_code(struct nsp_mssage_t *in_buffer, int ret_code);
void set_message_destmodule(struct nsp_mssage_t *in_buffer, int destmodule);
void set_message_srcmodule(struct nsp_mssage_t *in_buffer, int srcmodule);
int set_mssage_text(struct nsp_mssage_t *const in_buffer, 
                        void const *text, 
                        int in_buffer_length);
//给消息字段指针赋值
int set_mssage_fp64_text(struct nsp_mssage_t *const in_buffer, long double data);
int set_mssage_int32_text(struct nsp_mssage_t *const in_buffer, int data);
int set_mssage_pointer_text(struct nsp_mssage_t *const in_buffer, 
                                        void const *text,                                           
                                        int in_buffer_length);

int set_message_data_length(struct nsp_mssage_t& in_buffer, int length);
int get_message_flag(struct nsp_mssage_t *in_buffer);
int get_message_syn(struct nsp_mssage_t *header);
int get_message_id(struct nsp_mssage_t *in_buffer);
int get_message_ret_code(struct nsp_mssage_t *in_buffer);
int get_message_srcmodule(const struct nsp_mssage_t *in_buffer);
int get_message_destmodule(struct nsp_mssage_t *in_buffer);
void* get_mssage_text_address(struct nsp_mssage_t *const in_buffer,                     
                                        int out_buffer_length);
float get_mssage_fp64_text(struct nsp_mssage_t *const in_buffer);
int get_mssage_int32_text(struct nsp_mssage_t *const in_buffer);

int get_message_text_length(struct nsp_mssage_t *const in_buffer);

//int is_message_valid(atomic<int>& message_id);

#endif
#endif

module.cpp文件

    #include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <sys/sem.h>
#include "module.h"

using namespace std;

/*获取IPC资源的KEY,每获取一个IPC资源都会自增1*/
unsigned char ipc_key = 1;

/* 在这里定义所有的应用模块,注意这里的数组需要和模块ID对应起来,方便管理*/
thread_ctrl_t  thread_info[THREAD_END_ID+1];
/******************将主线程的信息与其他线程信息一同管理 在此函数中完成主线程信息的特殊初始化 流程**************************************************/
void init_main_thread_info(void)
{
    thread_info[THREAD_MAIN_ID].thread_id= THREAD_MAIN_ID;
    strcpy(thread_info[THREAD_MAIN_ID].thread_name, "Main Thread");
    thread_info[THREAD_MAIN_ID].init_func= NULL;
    thread_info[THREAD_MAIN_ID].msg_que_id= 0;
    thread_info[THREAD_MAIN_ID].task_id= pthread_self();
    strcpy(thread_info[THREAD_MAIN_ID].task_name, "Main Thread");
    thread_info[THREAD_MAIN_ID].init_pri= INIT_TOP_RIGHT;
    thread_info[THREAD_MAIN_ID].task_pri= 0;
    thread_info[THREAD_MAIN_ID].task_func= NULL;
    thread_info[THREAD_MAIN_ID].task_para= 0;
}
/*****************************显式初始化模块注册数组**************************************/
void init_thread_list(void)
{
    int thread_id;
    for(thread_id = THREAD_ZERO_ID;thread_id < THREAD_END_ID+1;thread_id++)
    {
        thread_info[thread_id].thread_id= 0;
        strcpy(thread_info[thread_id].thread_name, "null");
        thread_info[thread_id].init_func= NULL;
        thread_info[thread_id].msg_que_id= 0;
        thread_info[thread_id].task_id= 0;
        strcpy(thread_info[thread_id].task_name, "null");
        thread_info[thread_id].init_pri= 0;
        thread_info[thread_id].task_pri= 0;
        thread_info[thread_id].task_func= NULL;
        thread_info[thread_id].task_para= 0;
    }
}
unsigned char get_ipc_key(void)
{
    unsigned char temp_key = 0;
    temp_key = ipc_key;
    ipc_key++;
    return temp_key;
}
int init_message(void)
{
    int id = 0;
    int message_key = 0;
    unsigned char key = 0;

    key = get_ipc_key();
    message_key = ftok(".", key);
    id = msgget(message_key, 0777|IPC_CREAT);
    if(id < 0)
        return -1;

    return id;
}

/**********************申请信号量的过程*********************************************/
int init_semaphore(sem_t* sem)
{
    int return_v;
    return_v = sem_init(sem, 0,0);
    if(return_v < 0)
        return -1;

    return return_v;
}
/************************** 申请IPC资源*****************************************/
void init_ipc_resource(void)
{
    int thread_id;
    for(thread_id = THREAD_ZERO_ID + 1; thread_id < THREAD_END_ID; thread_id++)
    {
        thread_info[thread_id].msg_que_id = init_message();
         init_semaphore(&thread_info[thread_id].sem_id);
    }
}

/***********************获取对应模块的线程优先级********************************************/
int mod_if_get_thread_priority(int thread_id)
{
    int result;
    result = thread_info[thread_id].task_pri;

    return result;
}
/****************************创建线程***************************************/
int task_create(unsigned int thread_id, unsigned long* p_tidp,int policy,
                        PF_TASK_MAIN func_entry,void * args)
{
    if (p_tidp == NULL)
    {
        return -1;
    }

    int result;
    pthread_attr_t pattr;
    struct sched_param param;
    pthread_attr_init(&pattr);
    param.sched_priority = mod_if_get_thread_priority(thread_id);   

    pthread_attr_setschedpolicy(&pattr,policy);
    pthread_attr_setschedparam(&pattr,&param);
    pthread_attr_setinheritsched(&pattr,PTHREAD_EXPLICIT_SCHED);
    result = pthread_create(p_tidp,
                            &pattr,
                            func_entry,
                            args);
    pthread_attr_destroy(&pattr);
    return result;
}
void startup_module(int thread_id)
{
    task_create(thread_id, &thread_info[thread_id].task_id, thread_info[thread_id].policy, thread_info[thread_id].task_func, NULL);
}

/**********按照模块注册时传入的初始化优先级进行模块初始化并创建线程的操作****************/
void startup_module_flowline(void)
{
    int init_right = 0;
    int moduleid = 0;
    int init_result = 0;

    for(init_right = INIT_TOP_RIGHT;init_right < INIT_RIGHT_END;init_right++)
    {
        for(moduleid = THREAD_ZERO_ID+1;moduleid < THREAD_END_ID;moduleid++)
        {
            if((thread_info[moduleid].init_pri== init_right)&&(moduleid != THREAD_MAIN_ID))
            {
                if(thread_info[moduleid].init_func != NULL)
                {
                    init_result = thread_info[moduleid].init_func(moduleid);
                }
                startup_module(moduleid);
            }
            else
            {
                continue;
            }
        }
    }
}
/***************按照与启动时相反的顺序以阻塞主线程的方式等待线程结束***************/
void block_module_queue(void)
{
    int init_right = 0;
    int moduleid = 0;
    int val;

    for(init_right = INIT_RIGHT_END - 1; init_right > INIT_RIGHT_START; init_right--)
    {
        for(moduleid = THREAD_END_ID - 1; moduleid > THREAD_ZERO_ID; moduleid--)
        {
            if((thread_info[moduleid].init_pri== init_right)&&(moduleid != THREAD_MAIN_ID))
            {

                if(strcmp(thread_info[moduleid].thread_name,"null"))
                {   
                    val = pthread_join(thread_info[moduleid].task_id,NULL);
                }
            }
        }
    }
}
/*************************模块管理的入口函数******************************************/
void init_module_manager(void)
{
    init_ipc_resource();
    startup_module_flowline();
    block_module_queue();

}
/************注册线程***********/
int mod_if_register_thread(int thread_id,int init_right,int task_right,char * thread_name,PF_INIT_FUNC init_func,PF_TASK_MAIN func_entry, int policy)
{
    if(thread_id >= THREAD_END_ID)
    {
        printf("module error!!!\n");
        return -1;
    }
    if((task_right < 1) ||(task_right > 99))
    {
        printf("The value of task priority should between 1 and 99!\n");
        while(1);
    }
    if((thread_info[thread_id].thread_id == 0)&&(thread_info[thread_id].init_pri ==0)
        &&(thread_info[thread_id].task_pri == 0)&&(strcmp(thread_info[thread_id].thread_name,"null") == 0)
        &&(thread_info[thread_id].init_func == NULL)&&(thread_info[thread_id].task_func == NULL))
    {
        thread_info[thread_id].thread_id= thread_id;
        thread_info[thread_id].init_pri= init_right;
        thread_info[thread_id].task_pri= task_right;
        strcpy(thread_info[thread_id].thread_name,thread_name);
        thread_info[thread_id].init_func= init_func;
        thread_info[thread_id].task_func= func_entry;
        thread_info[thread_id].policy = policy;
    }
    else
    {
        printf("Registered module ID!\n");
        while(1);
    }
}
/********************************通过当前线程ID获取当前模块ID/***********************************/
int mod_if_get_current_module_id(void)
{
    int thread_id = 0;
    int module_id = 0;
    thread_id = pthread_self();
    for(module_id = THREAD_ZERO_ID; module_id < THREAD_END_ID; module_id++)
    {
        if(thread_id == thread_info[module_id].task_id)
        {
            return module_id;
        }
        else
        {
            continue;
        }
    }
}
/*************************获取对应模块的同步信号量ID******************************************/
int mod_if_get_sem_id(int module_id)
{
    int result;
    result =(int)&thread_info[module_id].sem_id;

    return result;
}

/************************获取对应模块的消息队列ID*******************************************/
int mod_if_get_msgque_id(int module_id)
{
    int result;
    result = thread_info[module_id].msg_que_id;
    return result;
}
char * mod_if_get_module_name(int module_id)
{
    char * result;
    result = thread_info[module_id].thread_name;
    return result;
}

module.h文件

#ifndef _MODULE_H_
#define _MODULE_H_

#include <string.h>
#include <semaphore.h>

#define MODULE_NAME_MAX_LEN 32 /* 定义模块名最大长度 */

/*初始化优先级枚举*/
typedef enum
{
    INIT_RIGHT_START,

    INIT_TOP_RIGHT=1,
    INIT_HIGH_RIGHT,
    INIT_NORMAL_RIGHT,
    INIT_LOW_RIGHT,

    INIT_RIGHT_END,
}INIT_RIGHTS;
typedef void* (* PF_TASK_MAIN )(void* arg);
typedef unsigned long (* PF_INIT_FUNC )(unsigned long thread_id); 

typedef struct  ThreadCtl
{
    unsigned long thread_id; /* 线程ID ,固定分配*/
    char thread_name[MODULE_NAME_MAX_LEN];          /* 模块名 */
    PF_INIT_FUNC init_func; /* 各个模块的初始化入口函数 */
    unsigned long msg_que_id; /* 各个模块的队列ID */
    sem_t sem_id; /* 各个模块的同步消息信号量 */
    unsigned long task_id;   /* 模块任务ID,创建线程时,返回此值 */    
    char task_name[MODULE_NAME_MAX_LEN];          /* 任务名 */   
    unsigned long init_pri;/*模块的初始化优先级*/
    unsigned long task_pri; /* 各个模块的任务优先级 */
    int policy; /* 模块对应线程的调试策略*/
    PF_TASK_MAIN task_func;  /* 各个模块的任务入口函数 */
    unsigned long task_para; /* 各个模块的任务入口参数 */

}thread_ctrl_t;
typedef enum
{
    /*0模块ID预留*/
    THREAD_ZERO_ID, 
    /*特殊模块号,主线程模块ID*/
    THREAD_MAIN_ID,
    /*在此处罗列模块枚举*/
    THREAD_ONE_ID,
    THREAD_TWO_ID,

    /*模块结束ID*/ 
    THREAD_END_ID,
}MODULE_IDS;
void init_main_thread_info(void);
void init_thread_list(void);
void init_module_manager(void);
int mod_if_register_thread(int thread_id,int init_right,int task_right,char * thread_name,
                            PF_INIT_FUNC init_func,PF_TASK_MAIN func_entry, int policy);
int mod_if_get_current_module_id(void);
int mod_if_get_sem_id(int module_id);
int mod_if_get_msgque_id(int module_id);
char * mod_if_get_module_name(int module_id);

#endif

makefile文件

GG = g++
CPPFLAGES = -std=c++0x -pthread

CPPRCS := $(wildcard *.cpp)
OBJS := $(CPPRCS:%.cpp=%.o)

main: $(OBJS)
    $(GG) $(CPPFLAGES) -o $@ $^
    @echo $@

%.o: %.cpp
    $(GG) $(CPPFLAGES) -c $< -o $@
    @echo $@

.PHONY: clean
clean:
    rm -rf *.o main

你可能感兴趣的:(多线程,linux,C-C++)