├── readme ├── shm_check_authorize.c ├── shm_check_authorize.h ├── shm_circular_array.c ├── shm_circular_array.h ├── shm_core.h ├── shm_count_info.c ├── shm_count_info.h ├── shm_inner_func.c ├── shm_inner_func.h ├── shm_rr_queue.c ├── shm_rr_queue.h └── snow_ball.h /readme: -------------------------------------------------------------------------------- 1 | /* 2 | 进程间有多种通信方式,常见的包括 socket,共享内存,命名管道等等,最常见的是socket和共享内存,socket应该是用的最多的, 3 | 很简单,顺手抄起来就能用,并且移植性很强,如果改为分布式不在同一主机,只需要把配置ip和port修改即可,调试也很方便, 4 | 用tcpdump和netstat基本就够调试了,但是从效率上比共享内存要逊色不少,尤其是同一份数据需要发给多个进程时,做了大量重复性 5 | 劳动。 6 | 7 | 共享内存以高效著称,不仅使数据在用户进程和内核传递的次数减少了(共享内存2次,其他IPC4次),在多个进程接收数据时更是 8 | 可以大显神威,但是封装这样一个功能模块复杂度要比socket高很多。 9 | 10 | 这里将共享内存进行了封装,以循环队列的形式供进程进行读写(支持一个进程写,多个进程读,如果是需要多个进程写需要再 11 | 实例化一个对象即可),对数据同步进行了精心设计,尽最大努力减少锁冲突,在数据同步的前提下提高读写效率。 12 | 13 | 将源码贴出来,希望得到交流,研一时写的代码,代码风格和函数抽象层次确实让现在得我不敢苟同,将当时的代码贴出来我 14 | 付出了极大地勇气来面对过去的自己。 15 | 16 | 目前review了下自己的代码,有几个不满意的地方,1 代码风格当时还不稳定 2 接口设计的不是很合理,我会加上类似于tcp的三次 17 | 握手类似的接口。 3 阻塞做的不好,起码加个计时器。 4 加上调试的开关,如果用户需要调试,可以打开开关写日志核对读写信息。 18 | 19 | 20 | 参考书籍为stevens大神的unp1,unp2。 21 | 22 | 四年后重新看自己学生时代的代码 感觉写的好啰嗦,找时间重构下好了 23 | 现在工作天天跟共享内存打交道,项目组的一个前辈封装的一套接口十分简洁 24 | */ 25 | -------------------------------------------------------------------------------- /shm_check_authorize.c: -------------------------------------------------------------------------------- 1 | #include "shm_check_authorize.h" 2 | 3 | 4 | int check_read_id(int id) 5 | { 6 | int m = id & 0x0000ffff ^ 0x0000f5bf ^ 0x00002220; 7 | if(1 == m) 8 | { 9 | return SHM_TRUE; 10 | } 11 | 12 | else 13 | { 14 | return SHM_FALSE; 15 | } 16 | } 17 | 18 | 19 | int get_read_num(int id) 20 | { 21 | int num = ((id & 0xffff0000) >>(32 - 16)) | ((id & 0xffff0000) << 16); 22 | return num; 23 | } 24 | 25 | 26 | int check_write_id(int id) 27 | { 28 | int m= id & 0x0000ffff ^ 0x0000814a ^ 0x0000f4e0; 29 | if(1 == m) 30 | { 31 | return SHM_TRUE; 32 | } 33 | else 34 | { 35 | return SHM_FALSE; 36 | } 37 | } 38 | 39 | 40 | int get_write_num(int id) 41 | { 42 | int num = ((id & 0xffff0000) >>(32 - 16)) | ((id & 0xffff0000) << 16); 43 | return num; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /shm_check_authorize.h: -------------------------------------------------------------------------------- 1 | /*##################################################################################*//* 2 | 3 | *# @FILE: shm_check_authorize.h 4 | *# DESCRIPTION : 5 | this file is used for checking the process's authorize 6 | if the process don't have a right id, the interface 7 | will refuse the read or write operation. 8 | *# Author:lishiming2007@gmail.com 9 | *####################################################################################*/ 10 | #ifndef __H_CHECK_AUTHORIZE_HEADER_ 11 | #define __H_CHECK_AUTHORIZE_HEADER_ 12 | 13 | #ifndef SHM_TRUE 14 | #define SHM_TRUE 1 15 | #endif 16 | 17 | #ifndef SHM_FAIL 18 | #define SHM_FALSE -1 19 | #endif 20 | 21 | 22 | /** 23 | * 24 | * METHOD: check_read_id 25 | * DESCRIPTION: check the id whether has been authorized 26 | * @param :id, the read id who is distributed to the read process,not pid! 27 | * @return :SHM_TRUE if this id has been authorized,if not,SHM_FALSE is returned 28 | */ 29 | 30 | int check_read_id(int id); 31 | 32 | 33 | /** 34 | * 35 | * METHOD: get_read_num 36 | * DESCRIPTION: actually,the id can be mapped to a num between 1-32,we can use this num to stand for the process 37 | * @param :id,the read id who is distributed to the read process,not pid! 38 | * @return :the num between 1-32 39 | */ 40 | 41 | int get_read_num(int id); 42 | 43 | 44 | /** 45 | * 46 | * METHOD: check_write_id 47 | * DESCRIPTION: check the id whether has been authorized 48 | * @param :id, the write id who is distributed to the write process,not pid! 49 | * @return :SHM_TRUE if this id has been authorized,if not,SHM_FALSE is returned 50 | */ 51 | 52 | int check_write_id(int id); 53 | 54 | /** 55 | * 56 | * METHOD: get_write_num 57 | * DESCRIPTION: actually,the id can be mapped to a num between 1-32,we can use this num to stand for the process 58 | * @param :id,the write id who is distributed to the write process,not pid! 59 | * @return :the num between 1-32 60 | */ 61 | 62 | int get_write_num(int id); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /shm_circular_array.c: -------------------------------------------------------------------------------- 1 | #include "shm_circular_array.h" 2 | #include 3 | 4 | int init_queue(circular_array_t *pqueue, block_info_t *pbase) 5 | { 6 | if(NULL == pqueue || NULL == pbase) 7 | { 8 | return SHM_FALSE; 9 | } 10 | 11 | pqueue->head = 0; 12 | pqueue->tail = 0; 13 | pqueue->pbase = pbase; 14 | 15 | return SHM_TRUE; 16 | } 17 | 18 | 19 | int is_full(circular_array_t *pqueue,unsigned int queue_size) 20 | { 21 | if((pqueue->tail + 1) % queue_size == pqueue->head) 22 | { 23 | return SHM_TRUE; 24 | } 25 | else 26 | { 27 | return SHM_FALSE; 28 | } 29 | } 30 | 31 | 32 | int is_empty(circular_array_t *pqueue) 33 | { 34 | if(pqueue->head == pqueue->tail) 35 | { 36 | return SHM_TRUE; 37 | } 38 | else 39 | { 40 | return SHM_FALSE; 41 | } 42 | } 43 | 44 | 45 | int out_queue(circular_array_t *pqueue,unsigned int queue_size) 46 | { 47 | int ret = is_empty(pqueue); 48 | if(ret == SHM_TRUE) 49 | { 50 | return SHM_FALSE; 51 | } 52 | else 53 | { 54 | pqueue->head = (pqueue->head + 1) % queue_size; 55 | return SHM_TRUE; 56 | } 57 | } 58 | 59 | 60 | int en_queue(circular_array_t *pqueue,block_info_t *value,unsigned int queue_size) 61 | { 62 | if(is_full(pqueue,queue_size)) 63 | { 64 | return SHM_FALSE; 65 | } 66 | else 67 | { 68 | pqueue->pbase[pqueue->tail] = *value; 69 | pqueue->tail = (pqueue->tail + 1) % queue_size; 70 | return SHM_TRUE; 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /shm_circular_array.h: -------------------------------------------------------------------------------- 1 | /*##################################################################################*//* 2 | 3 | *# @FILE: shm_circular_array.h 4 | *# DESCRIPTION : 5 | in this file,I use an array to realize a round-robin queue, I don't use the link list 6 | because the round-robin queue should exist in the share memory(shm),the shm will be 7 | getted in init,if each time get a new shm for a new block,a lot of system calls will 8 | happen,so I use a given shm to realize a queue. 9 | *# Author:lishiming2007@gmail.com 10 | *####################################################################################*/ 11 | 12 | 13 | #ifndef __H_SHM_CIRCULAR_ARRAY_HEADER 14 | #define __H_SHM_CIRCULAR_ARRAY_HEADER 15 | 16 | 17 | #ifndef MAX_PROC_NUM 18 | #define MAX_PROC_NUM 32 19 | #endif 20 | 21 | #ifndef SHM_TRUE 22 | #define SHM_TRUE 1 23 | #endif 24 | 25 | #ifndef SHM_FAIL 26 | #define SHM_FALSE -1 27 | #endif 28 | 29 | 30 | /** 31 | * 32 | * STRUCT NAME: block_info_t 33 | * DESCRIPTION: it contains the info of each data block 34 | */ 35 | 36 | typedef struct _block_info 37 | { 38 | unsigned int block_size; /*the size of this data block*/ 39 | 40 | unsigned int block_start; /*offset of the data block'start to the start of shm*/ 41 | 42 | unsigned int block_end; /* offset of the data block'end to the start of shm*/ 43 | 44 | unsigned int is_splits; /*a data block may locate in both the end and the start of the shm, 45 | if this happens,this param will be SHM_SPLITS,contrary SHM_NO_SPLITS*/ 46 | 47 | char flags[MAX_PROC_NUM]; /* this array marks if this data block is readed by the process,process x read, 48 | flags[x]=FLAG_TRUE, default:FLAG_FALSE*/ 49 | 50 | }block_info_t; 51 | 52 | 53 | 54 | /** 55 | * 56 | * STRUCT NAME: circular_array_t 57 | * DESCRIPTION: info of the circular_array 58 | * 59 | * i will change block_info_t* to void*,i use this block_info_t * because this interface is 60 | * only inner interface. but I known this isn't beautiful. 61 | */ 62 | 63 | typedef struct _circular_array 64 | { 65 | int head; /*offset of the oldest data in the queue to the pbase*/ 66 | 67 | int tail; /*offset of the newest data in the queue to the pbase*/ 68 | 69 | block_info_t *pbase; /*the start of the circular_array*/ 70 | 71 | }circular_array_t; 72 | 73 | 74 | /** 75 | * 76 | * METHOD: init_queue 77 | * DESCRIPTION: init the info of queue 78 | * @param :pqueue, the addrss of array 79 | * @param :pbase, the first block should be located here 80 | * @return :SHM_TRUE,success,if fail,SHM_FALSE 81 | */ 82 | 83 | int init_queue(circular_array_t *pqueue, block_info_t *pbase); 84 | 85 | 86 | /** 87 | * 88 | * METHOD: en_queue 89 | * DESCRIPTION: insert a block to the queue to the tail 90 | * @param :pqueue, the addrss of array 91 | * @param :value, the block's info 92 | * @param :queue_size,the size of the queue 93 | * @return :SHM_TRUE,success,if fail,SHM_FALSE 94 | */ 95 | 96 | int en_queue(circular_array_t *pqueue, block_info_t *value, unsigned int queue_size); 97 | 98 | 99 | /** 100 | * 101 | * METHOD: out_queue 102 | * DESCRIPTION: the head dequeue 103 | * @param :pqueue, the addrss of array 104 | * @param :queue_size,the size of the queue 105 | * @return :SHM_TRUE,success,if fail,SHM_FALSE 106 | */ 107 | 108 | int out_queue(circular_array_t *pqueue, unsigned int queue_size); 109 | 110 | 111 | /** 112 | * 113 | * METHOD: is_full 114 | * DESCRIPTION: jude if the queue is full 115 | * @param :pqueue, the addrss of array 116 | * @param :queue_size,the size of the queue 117 | * @return :SHM_TRUE,if queue is full,if not,SHM_FALSE 118 | */ 119 | 120 | int is_full(circular_array_t *pqueue, unsigned int queue_size); 121 | 122 | 123 | /** 124 | * 125 | * METHOD: is_empty 126 | * DESCRIPTION: jude if the queue is empty 127 | * @param :pqueue, the addrss of array 128 | * @return :SHM_TRUE,if queue is empty,if not,SHM_FALSE 129 | */ 130 | int is_empty(circular_array_t *pqueue); 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /shm_core.h: -------------------------------------------------------------------------------- 1 | /*##################################################################################*//* 2 | 3 | *# @FILE: shm_core.h 4 | *# DESCRIPTION : 5 | this file creat the core data hierarchy 6 | *# Author:lishiming2007@gmail.com 7 | *####################################################################################*/ 8 | 9 | #ifndef __H_SHM_CORE_HEADER 10 | #define __H_SHM_CORE_HEADER 11 | 12 | #include 13 | #include 14 | #include 15 | #include "shm_circular_array.h" 16 | 17 | 18 | #define MAX_PROC_NUM 32 /* this num only contains 32 process to read the shm,you can change if you want*/ 19 | 20 | #define FLAG_TRUE '1' 21 | #define FLAG_FALSE '0' 22 | 23 | #define SHM_NO_SPLITS 0 24 | #define SHM_SPLITS 1 25 | 26 | #ifndef OP_MODE_READ 27 | #define OP_MODE_READ 0x01 /* value of SHMQ_PARAMETER_OP_MODE,set the op mode read*/ 28 | #endif 29 | 30 | #ifndef OP_MODE_WRITE 31 | #define OP_MODE_WRITE 0x02 /* value of SHMQ_PARAMETER_OP_MODE,set the op mode write*/ 32 | #endif 33 | 34 | #ifndef READ_PRIO 35 | #define READ_PRIO 0x01 /* value of SHMQ_PARAMETER_WHO_PRIO, 36 | this will assure all the data to be read before covered */ 37 | #endif 38 | 39 | #ifndef WRITE_PRIO 40 | #define WRITE_PRIO 0x02 /* value of SHMQ_PARAMETER_WHO_PRIO, 41 | this will assure the write process write as fast as it can,it will not wait for reader*/ 42 | #endif 43 | 44 | #ifndef SHMQ_PARAMETER_POOL_SIZE 45 | #define SHMQ_PARAMETER_POOL_SIZE 0x01 /* type to set shm's size*/ 46 | #endif 47 | 48 | #ifndef SHMQ_PARAMETER_BLOCK_NUM 49 | #define SHMQ_PARAMETER_BLOCK_NUM 0x02 /* type to set the num of queue'elements*/ 50 | #endif 51 | 52 | #ifndef SHMQ_PARAMETER_OP_MODE 53 | #define SHMQ_PARAMETER_OP_MODE 0x03 /* type to set op mod*/ 54 | #endif 55 | 56 | #ifndef SHMQ_PARAMETER_WHO_PRIO 57 | #define SHMQ_PARAMETER_WHO_PRIO 0x04 /* type to set read is prio or write is*/ 58 | #endif 59 | 60 | #ifndef RETURN_RET 61 | #define RETURN_RET 1 62 | 63 | enum SHM_RETURN_RET{ 64 | SHM_HANDLE_NULL = -201, /* error: the handle is null*/ 65 | SHM_UNKNOWN_OP, /* error: unknown op type*/ 66 | SHM_OP_WRONG, /* error: op value can't map the op mod*/ 67 | SHM_UNKNOWN_PRIO, /* error:the value of SHMQ_PARAMETER_WHO_PRIO is wrong*/ 68 | SHM_NO_AUTHORITY, /* error:the process don't have been authorized*/ 69 | SHM_UNKNOWN_TYPE, /* error:set a unknown type*/ 70 | SHM_NO_SHM, /* error:the shared memory is not exist*/ 71 | SHM_CREATE_SHMEM_FAIL, /* error: fail to create shared memory*/ 72 | SHM_ALREADY_EXIST, /* error: the shared memory is exist,can't create it repeatedly*/ 73 | SHM_NO_DATA, /* error: no data in the shared memory*/ 74 | SHM_DATA_READED_YET, /* error: this data block has been read by the same process*/ 75 | SHM_OUT_QUEUE_FAIL, /* error: fail to dequeue the tail*/ 76 | SHM_NO_SPACE, /* error: no space left to write data to shared memory*/ 77 | SHM_DELETE_SHM_FAIL, /* error:delete the shared memory failed*/ 78 | SHM_BUF_SHORT,/*error: when read if buf is too short,when write if shm is too short*/ 79 | SHM_FAIL = -1, /* error:the function gets a fail result*/ 80 | SHM_OK = 1 /* the function success*/ 81 | }; 82 | #endif 83 | 84 | /** 85 | * 86 | * STRUCT NAME: shm_queue_info_t 87 | * DESCRIPTION: this struct contains the basic info of shared memory 88 | */ 89 | 90 | typedef struct _shm_queue_info 91 | { 92 | unsigned int max_queue_size; /* the max elements's num of the queue*/ 93 | unsigned int pool_size; /* size of the memory pool(data block will be here)*/ 94 | unsigned int pool_left_size; /* size of the memory pool can be used*/ 95 | unsigned int pool_begin_offset; /* the offset of the memory pool's start to the start of the whole shared memory*/ 96 | unsigned int pool_end_offset; /*the offset of the memory pool's end to the start of the whole shared memory*/ 97 | unsigned int write_pos; /* the offset of the next write position to the start of the whole shared memory*/ 98 | unsigned int owner_id; /* which process create the shared memory(not pid)*/ 99 | unsigned int op_num; /* the num of processes who attached to the shared memory*/ 100 | char read_flags[MAX_PROC_NUM]; /* this array marks which reader is reading shared memory*/ 101 | pthread_mutex_t mutex; /* mutext protect op_num*/ 102 | pthread_rwlock_t rwlock; /* writer should get rwlock when write,reader only get trwlock when he first get head of queue*/ 103 | 104 | }shm_queue_info_t; 105 | 106 | 107 | /** 108 | * 109 | * STRUCT NAME: miss_reader_stat_t 110 | * DESCRIPTION: when SHMQ_PARAMETER_WHO_PRIO is WRITE_PRIO ,this struct record the info of reader missed 111 | */ 112 | 113 | typedef struct _miss_reader_stat_t 114 | { 115 | unsigned long long miss_block_num; /* the num of missed block*/ 116 | unsigned long long miss_bytes; /* the bytes of missed data*/ 117 | 118 | }miss_reader_stat_t; 119 | 120 | 121 | 122 | /** 123 | * 124 | * STRUCT NAME: shm_queue_handle_t 125 | * DESCRIPTION: process must have handle before read or write 126 | */ 127 | typedef struct _shm_queue_handle_t 128 | { 129 | 130 | unsigned int self_id; /* id contributed to process,not pid*/ 131 | unsigned int op_mode; /* read or write*/ 132 | unsigned int op_pos; /* offset the process has read or write */ 133 | unsigned int who_prior; /*SHMQ_PARAMETER_WHO_PRIO*/ 134 | unsigned long long op_total; /* the bytes process has read or written*/ 135 | key_t key_id; /* key_id is the id of share memory*/ 136 | int shm_fd; /* mid of shared memory*/ 137 | unsigned int para_queue_size; /* the queue elements' num*/ 138 | unsigned int para_pool_size; /* size of pool to store data*/ 139 | miss_reader_stat_t readers_miss[MAX_PROC_NUM]; /* if WRITE_PRIO,how many bytes the readers have missed*/ 140 | shm_queue_info_t *shm_que_info; /* start of shared memry*/ 141 | circular_array_t *que; /* start of array*/ 142 | 143 | }shm_queue_handle_t; 144 | 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /shm_count_info.c: -------------------------------------------------------------------------------- 1 | #include "shm_count_info.h" 2 | #include "shm_core.h" 3 | 4 | 5 | unsigned long long get_op_total(void*handle) 6 | { 7 | if(NULL == handle) 8 | { 9 | return SHM_FAIL; 10 | } 11 | 12 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 13 | 14 | return shmq_handle->op_total; 15 | } 16 | 17 | 18 | 19 | int get_miss_stat(void*handle, int id, unsigned long long *miss_block, unsigned long long *miss_bytes) 20 | { 21 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 22 | 23 | if(NULL == shmq_handle) 24 | { 25 | return SHM_FAIL; 26 | } 27 | int i = get_read_num(id); 28 | 29 | *miss_block = shmq_handle->readers_miss[i].miss_block_num; 30 | *miss_betys = shmq_handle->readers_miss [i].miss_bytes; 31 | return SHM_OK; 32 | } 33 | -------------------------------------------------------------------------------- /shm_count_info.h: -------------------------------------------------------------------------------- 1 | #ifndef __H_SHM_COUNT_INFO_HEADER_ 2 | #define __H_SHM_COUNT_INFO_HEADER_ 3 | 4 | 5 | extern int check_read_id(int id); 6 | 7 | /** 8 | * 9 | * METHOD: get_op_total 10 | * DESCRIPTION: get the total data process has read or writen 11 | * @param : handle,the handle created 12 | * @return : how many bytes process has read or writen 13 | */ 14 | 15 | unsigned long long get_op_total(void*handle); 16 | 17 | 18 | /** 19 | * 20 | * METHOD: get_miss_stat 21 | * DESCRIPTION: this function is used by write processto get a read process miss info 22 | * @param : handle,the handle created 23 | * @param : id, read process's id(not pid) 24 | * @param : miss_block, output how many blocks the reader has missed 25 | * @param : miss_bytes, output how many bytes the reader has missed 26 | * @return : SHM_OK if success,SHM_FAIL if fail 27 | */ 28 | 29 | int get_miss_stat(void*handle, int id, unsigned long long *miss_block, unsigned long long *miss_bytes); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /shm_inner_func.c: -------------------------------------------------------------------------------- 1 | #include "shm_inner_func.h" 2 | #include 3 | 4 | int init_read_handle_info(shm_queue_handle_t *handle,key_t key_id , char *sh_mem) 5 | { 6 | if(NULL == handle || NULL == sh_mem) 7 | { 8 | return SHM_FAIL; 9 | } 10 | handle->shm_fd = shmget(key_id,0,0); 11 | 12 | if(handle->shm_fd < 0) 13 | { 14 | return SHM_FAIL; 15 | } 16 | 17 | //sh_mem = (char*)shmat(handle->shm_fd,NULL,0); 18 | 19 | handle->shm_que_info = (shm_queue_info_t*)sh_mem; 20 | handle->que = (circular_array_t*)((char*)sh_mem + sizeof(shm_queue_info_t)); 21 | handle->para_queue_size = handle->shm_que_info->max_queue_size; 22 | handle->para_pool_size = handle->shm_que_info->pool_size; 23 | 24 | pthread_rwlock_rdlock(&handle->shm_que_info->rwlock); 25 | handle->op_pos = handle->que->head; 26 | pthread_rwlock_unlock(&handle->shm_que_info->rwlock); 27 | handle->shm_que_info->read_flags[get_read_num(handle->self_id)] = FLAG_TRUE; 28 | handle->op_total = 0; 29 | 30 | pthread_mutex_lock(&handle->shm_que_info->mutex); 31 | handle->shm_que_info->op_num++; 32 | pthread_mutex_unlock(&handle->shm_que_info->mutex); 33 | 34 | return SHM_OK; 35 | } 36 | 37 | 38 | 39 | int init_write_handle_info(shm_queue_handle_t *shmq_handle, key_t key_id, char *sh_mem) 40 | { 41 | if(NULL == shmq_handle || NULL == sh_mem) 42 | { 43 | return SHM_FAIL; 44 | } 45 | shmq_handle->shm_fd = shmget(key_id, 0, 0); 46 | 47 | if(shmq_handle->shm_fd < 0) 48 | { 49 | return SHM_FAIL; 50 | } 51 | 52 | //shmq_handle->shm_que_info = (shm_queue_info_t*)shmat(shmq_handle->shm_fd, NULL, 0); 53 | shmq_handle->shm_que_info = (shm_queue_info_t*)sh_mem; 54 | shmq_handle->key_id = key_id; 55 | shmq_handle->que = (circular_array_t*)((char*)shmq_handle->shm_que_info + sizeof(shm_queue_info_t)); 56 | shmq_handle->op_total = 0; 57 | 58 | pthread_mutex_lock(&shmq_handle->shm_que_info->mutex); 59 | shmq_handle->shm_que_info->op_num = 1; 60 | pthread_mutex_unlock(&shmq_handle->shm_que_info->mutex); 61 | 62 | int i = 0; 63 | for(i = 0; i < MAX_PROC_NUM; i++) 64 | { 65 | shmq_handle->readers_miss[i].miss_bytes = 0; 66 | shmq_handle->readers_miss[i].miss_block_num = 0; 67 | } 68 | 69 | return SHM_OK; 70 | } 71 | 72 | 73 | int shm_init_mutext(pthread_mutex_t * mutex) 74 | { 75 | int ret = -1; 76 | pthread_mutexattr_t mattr; 77 | pthread_mutexattr_init(&mattr); 78 | pthread_mutexattr_setpshared(&mattr,PTHREAD_PROCESS_SHARED); 79 | ret = pthread_mutex_init(mutex, &mattr); 80 | return ret; 81 | } 82 | 83 | 84 | int shm_init_rwlock(pthread_rwlock_t *rwlock) 85 | { 86 | int ret = -1; 87 | pthread_rwlockattr_t attr; 88 | pthread_rwlockattr_init(&attr); 89 | pthread_rwlockattr_setpshared(&attr,PTHREAD_PROCESS_SHARED); 90 | ret = pthread_rwlock_init(rwlock, &attr); 91 | return ret; 92 | } 93 | 94 | 95 | int init_circular_info(char* sh_mem) 96 | { 97 | if(NULL == sh_mem) 98 | { 99 | return SHM_FAIL; 100 | } 101 | circular_array_t *circular_array = (circular_array_t *)((char*)sh_mem + sizeof(shm_queue_info_t) ); 102 | circular_array->pbase = (block_info_t*)((char*)sh_mem + sizeof(shm_queue_info_t)+ sizeof(circular_array_t)); 103 | circular_array->head = 0; 104 | circular_array->tail = 0; 105 | return SHM_OK; 106 | } 107 | 108 | 109 | int copy_info_from_handle(char *sh_mem, shm_queue_handle_t *shmq_handle) 110 | { 111 | if(NULL == sh_mem || NULL == shmq_handle) 112 | { 113 | return SHM_FAIL; 114 | } 115 | 116 | shm_queue_info_t *shmem_info = (shm_queue_info_t *)sh_mem; 117 | shmem_info->owner_id = shmq_handle->self_id; 118 | shmem_info->op_num = 1; 119 | shmem_info->max_queue_size = shmq_handle->para_queue_size; 120 | shmem_info->pool_size = shmq_handle->para_pool_size; 121 | shmem_info->pool_left_size = shmq_handle->para_pool_size; 122 | shmem_info->pool_begin_offset = sizeof(shm_queue_info_t) + sizeof(circular_array_t) + sizeof(block_info_t) * shmem_info->max_queue_size; 123 | 124 | shmem_info->pool_end_offset = shmem_info->pool_begin_offset + shmem_info->pool_size - 1; 125 | shmem_info->write_pos = shmem_info->pool_begin_offset; 126 | 127 | return SHM_OK; 128 | } 129 | 130 | int init_shm_info(char *sh_mem, shm_queue_handle_t *shmq_handle) 131 | { 132 | int mem_len = sizeof(shm_queue_info_t) + 133 | sizeof(circular_array_t) + 134 | shmq_handle->para_pool_size + 135 | shmq_handle->para_queue_size * sizeof(block_info_t); 136 | 137 | memset(sh_mem, 0, mem_len); 138 | 139 | copy_info_from_handle(sh_mem, shmq_handle); 140 | init_circular_info(sh_mem); 141 | int j; 142 | for(j = 0;j < MAX_PROC_NUM; j++) 143 | { 144 | ((shm_queue_info_t*)sh_mem) -> read_flags[j] = FLAG_FALSE; 145 | } 146 | int ret1 = shm_init_mutext((pthread_mutex_t *)(&(((shm_queue_info_t *)sh_mem)->rwlock))); 147 | int ret2 = shm_init_rwlock((pthread_rwlock_t *)(&(((shm_queue_info_t *)sh_mem)->rwlock))); 148 | 149 | if(0 == ret1 && 0 == ret2) 150 | { 151 | return SHM_OK; 152 | } 153 | else 154 | { 155 | return SHM_FAIL; 156 | } 157 | } 158 | 159 | 160 | int read_block(block_info_t *to_read_block,shm_queue_handle_t *shmq_handle,char *to_read_buf, int buf_len) 161 | { 162 | if(to_read_block->block_size > buf_len) 163 | { 164 | return -1; 165 | } 166 | 167 | int begin_offset = shmq_handle->shm_que_info->pool_begin_offset; 168 | int end_offset = shmq_handle->shm_que_info->pool_end_offset; 169 | int w_pos = shmq_handle->shm_que_info->write_pos; 170 | 171 | if(0 == to_read_block->is_splits) 172 | { 173 | char * read_start_addr = (char*)shmq_handle->shm_que_info + to_read_block->block_start; 174 | memcpy(to_read_buf,read_start_addr,to_read_block->block_size); 175 | } 176 | else 177 | { 178 | char *first_read_start_addr = (char*)shmq_handle->shm_que_info + to_read_block->block_start; 179 | int first_read_size = end_offset - to_read_block->block_start + 1; 180 | memcpy(to_read_buf,first_read_start_addr,first_read_size); 181 | 182 | char * second_to_read_buf = to_read_buf + end_offset - to_read_block->block_start + 1; 183 | 184 | char * second_read_start_addr = (char*)shmq_handle->shm_que_info + begin_offset; 185 | 186 | int second_read_size = to_read_block->block_size - (end_offset - to_read_block->block_start + 1); 187 | memcpy(second_to_read_buf,second_read_start_addr,second_read_size); 188 | } 189 | 190 | return to_read_block->block_size; 191 | } 192 | 193 | 194 | int create_new_block(shm_queue_handle_t *shmq_handle, int buf_len, int is_split) 195 | { 196 | if(NULL == shmq_handle) 197 | { 198 | return SHM_FAIL; 199 | } 200 | 201 | int begin_offset = shmq_handle->shm_que_info->pool_begin_offset; 202 | int end_offset = shmq_handle->shm_que_info->pool_end_offset; 203 | int w_pos = shmq_handle->shm_que_info->write_pos; 204 | int off_len = sizeof(shm_queue_info_t) + sizeof(circular_array_t) + sizeof(block_info_t) * shmq_handle->que->tail ; 205 | 206 | block_info_t *block_info = (block_info_t*)((char*)(shmq_handle->shm_que_info) + off_len); 207 | 208 | block_info->block_size = buf_len; 209 | block_info->block_start = w_pos; 210 | if(is_split == SHM_NO_SPLITS) 211 | { 212 | block_info->block_end = (block_info->block_start + buf_len - 1); 213 | } 214 | else if(is_split == SHM_SPLITS) 215 | { 216 | block_info->block_end = begin_offset + buf_len - (end_offset - w_pos + 1) - 1; 217 | } 218 | block_info->is_splits = is_split; 219 | 220 | int j; 221 | for(j = 0;j < MAX_PROC_NUM; j++) 222 | { 223 | block_info->flags[j] = FLAG_FALSE; 224 | } 225 | 226 | return SHM_OK; 227 | 228 | } 229 | 230 | int update_handle_info(shm_queue_handle_t *shmq_handle, int buf_len) 231 | { 232 | if(NULL == shmq_handle || buf_len <= 0) 233 | { 234 | return SHM_FAIL; 235 | } 236 | 237 | int begin_offset = shmq_handle->shm_que_info->pool_begin_offset; 238 | int end_offset = shmq_handle->shm_que_info->pool_end_offset; 239 | int w_pos = shmq_handle->shm_que_info->write_pos; 240 | 241 | shmq_handle->que->tail = (shmq_handle->que->tail + 1) % shmq_handle->para_queue_size; 242 | shmq_handle->shm_que_info->pool_left_size -= buf_len; 243 | 244 | if(end_offset - w_pos + 1 > buf_len) 245 | { 246 | shmq_handle->shm_que_info->write_pos += buf_len; 247 | } 248 | else if(end_offset - w_pos + 1 == buf_len) 249 | { 250 | shmq_handle->shm_que_info->write_pos = begin_offset; 251 | } 252 | else 253 | { 254 | shmq_handle->shm_que_info->write_pos = begin_offset + buf_len - (end_offset - w_pos + 1); 255 | } 256 | shmq_handle->op_total += buf_len; 257 | 258 | return SHM_OK; 259 | } 260 | 261 | 262 | int write_block(shm_queue_handle_t *shmq_handle,const char *to_write_buf,int buf_len) 263 | { 264 | if(NULL == shmq_handle || NULL == to_write_buf || buf_len <= 0) 265 | { 266 | return SHM_FAIL; 267 | } 268 | 269 | int begin_offset = shmq_handle->shm_que_info->pool_begin_offset; 270 | int end_offset = shmq_handle->shm_que_info->pool_end_offset; 271 | int w_pos = shmq_handle->shm_que_info->write_pos; 272 | 273 | if(end_offset - w_pos + 1 >= buf_len) 274 | { 275 | char * to_write_addr = (char*)shmq_handle->shm_que_info + w_pos; 276 | memcpy(to_write_addr,to_write_buf,buf_len); 277 | 278 | create_new_block(shmq_handle, buf_len, SHM_NO_SPLITS); 279 | update_handle_info(shmq_handle, buf_len); 280 | } 281 | 282 | else if(end_offset - w_pos + 1 < buf_len) 283 | { 284 | char * first_cpy_addr = (char*)shmq_handle->shm_que_info + w_pos; 285 | int first_cpy_size = end_offset - w_pos +1; 286 | memcpy(first_cpy_addr,to_write_buf,first_cpy_size); 287 | 288 | char * second_cpy_addr = (char*)shmq_handle->shm_que_info + begin_offset; 289 | char * second_buf_addr = (char*)to_write_buf + end_offset - w_pos + 1; 290 | int second_cpy_size = buf_len - (end_offset - w_pos + 1); 291 | memcpy(second_cpy_addr,second_buf_addr,second_cpy_size ); 292 | 293 | create_new_block(shmq_handle, buf_len, SHM_SPLITS); 294 | update_handle_info(shmq_handle, buf_len); 295 | } 296 | return SHM_OK; 297 | } 298 | -------------------------------------------------------------------------------- /shm_inner_func.h: -------------------------------------------------------------------------------- 1 | #ifndef __H_SHM_INNER_FUNC_HEADER_ 2 | #define __H_SHM_INNER_FUNC_HEADER_ 3 | 4 | #include "shm_core.h" 5 | 6 | 7 | /** 8 | * 9 | * METHOD: init_read_handle_info 10 | * DESCRIPTION: init read process's handle,copy shared memory's info to the handle 11 | * @param :key_id,shared memory's key_id 12 | * @param :sh_mem,the address of shared memory 13 | * @return :SHM_TRUE if success,if not,SHM_FALSE is returned 14 | */ 15 | 16 | int init_read_handle_info(shm_queue_handle_t *handle,key_t key_id , char* sh_mem); 17 | 18 | 19 | /** 20 | * 21 | * METHOD: init_write_handle_info 22 | * DESCRIPTION: init write process's handle,copy shared memory's info to the handle 23 | * @param :key_id,shared memory's key_id 24 | * @param :sh_mem,the address of shared memory 25 | * @return :SHM_TRUE if success,if not,SHM_FALSE is returned 26 | */ 27 | 28 | 29 | int init_write_handle_info(shm_queue_handle_t *handle, key_t key_id, char *sh_mem); 30 | 31 | 32 | /** 33 | * 34 | * METHOD: shm_init_mutext 35 | * DESCRIPTION: init a mutex 36 | * @param :mutex,pointer of mutex 37 | * @return :return the result of pthread_mutex_init 38 | */ 39 | 40 | int shm_init_mutext(pthread_mutex_t * mutex); 41 | 42 | /** 43 | * 44 | * METHOD: shm_init_rwlock 45 | * DESCRIPTION: init a rwlock 46 | * @param :rwlock,pointer of rwlock 47 | * @return :return the result of pthread_rwlock_init 48 | */ 49 | 50 | int shm_init_rwlock(pthread_rwlock_t *rwlock); 51 | 52 | 53 | /** 54 | * 55 | * METHOD: init_circular_info 56 | * DESCRIPTION: init circular_array_t struct:head,tail,pbase 57 | * @param :sh_mem, the address of shared memory 58 | * @return :SHM_TRUE if success,if not,SHM_FALSE is returned 59 | */ 60 | 61 | int init_circular_info(char* sh_mem); 62 | 63 | 64 | /** 65 | * 66 | * METHOD: copy_info_from_handle 67 | * DESCRIPTION: copy info (owner_id,max_queue_size and so on) 68 | * @param :sh_mem, the address of shared memory 69 | * @param :shmq_handle, 70 | * @return :SHM_TRUE if success,if not,SHM_FALSE is returned 71 | */ 72 | 73 | int copy_info_from_handle(char *sh_mem, shm_queue_handle_t *shmq_handle); 74 | 75 | 76 | /** 77 | * 78 | * METHOD: init_shm_info 79 | * DESCRIPTION: init shared memory info 80 | * @param :sh_mem, the address of shared memory 81 | * @param :shmq_handle, 82 | * @return :SHM_TRUE if success,if not,SHM_FALSE is returned 83 | */ 84 | 85 | int init_shm_info(char *sh_mem, shm_queue_handle_t *shmq_handle); 86 | 87 | 88 | /** 89 | * 90 | * METHOD: read_block 91 | * DESCRIPTION: read a block of data from shared memory to process's buf 92 | * @param : to_read_block,block info of data to be read 93 | * @param : shmq_handle,handle 94 | * @param : to_read_buf,the buf to store data 95 | * @param : buf_len, length of buf 96 | * @return : SHM_TRUE if success,if not,SHM_FALSE is returned 97 | */ 98 | 99 | int read_block(block_info_t *to_read_block, shm_queue_handle_t *shmq_handle, char *to_read_buf, int buf_len); 100 | 101 | 102 | /** 103 | * 104 | * METHOD: create_new_block 105 | * DESCRIPTION: create a new block info to the queue 106 | * @param :shmq_handle, 107 | * @param : buf_len,length of data 108 | * @param : is_split,SHM_NO_SPLITS or SHM_SPLITS 109 | * @return :SHM_TRUE if success,if not,SHM_FALSE is returned 110 | */ 111 | 112 | int create_new_block(shm_queue_handle_t *shmq_handle, int buf_len, int is_split); 113 | 114 | 115 | /** 116 | * 117 | * METHOD: update_handle_info 118 | * DESCRIPTION: update handle's info after read or write 119 | * @param :shmq_handle, 120 | * @param : buf_len,length of data 121 | * @return :SHM_OK if success,if not,SHM_FAIL is returned 122 | */ 123 | 124 | int update_handle_info(shm_queue_handle_t *shmq_handle, int buf_len); 125 | 126 | 127 | /** 128 | * 129 | * METHOD: write_block 130 | * DESCRIPTION: write a block of data from shared memory from process's buf 131 | * @param : shmq_handle,handle 132 | * @param : to_write_buf ,pointer of buf 133 | * @param : buf_len, length of buf 134 | * @return :SHM_OK if success,if not,SHM_FAIL is returned 135 | */ 136 | 137 | int write_block(shm_queue_handle_t *shmq_handle,const char *to_write_buf,int buf_len); 138 | 139 | 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /shm_rr_queue.c: -------------------------------------------------------------------------------- 1 | #include "shm_core.h" 2 | #include "shm_rr_queue.h" 3 | #include "shm_circular_array.h" 4 | #include "shm_inner_func.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | void *get_shm_queue_handle(int self_id) 13 | { 14 | shm_queue_handle_t *handle = NULL; 15 | handle = (shm_queue_handle_t*)calloc(1,sizeof(shm_queue_handle_t)); 16 | if(NULL != handle) 17 | { 18 | handle->self_id = self_id; 19 | } 20 | 21 | handle->who_prior = READ_PRIO; 22 | 23 | return (void*)handle; 24 | } 25 | 26 | 27 | 28 | int set_shm_queue_handle(void *handle, int type, int value) 29 | { 30 | int ret = SHM_OK; 31 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 32 | 33 | if(NULL == shmq_handle) 34 | { 35 | return SHM_HANDLE_NULL; 36 | } 37 | 38 | switch(type) 39 | { 40 | case SHMQ_PARAMETER_BLOCK_NUM: 41 | { 42 | shmq_handle->para_queue_size = value; 43 | break; 44 | } 45 | case SHMQ_PARAMETER_POOL_SIZE: 46 | { 47 | shmq_handle->para_pool_size = value; 48 | break; 49 | } 50 | case SHMQ_PARAMETER_OP_MODE: 51 | { 52 | if(value == OP_MODE_READ || value == OP_MODE_WRITE) 53 | { 54 | shmq_handle->op_mode = value; 55 | } 56 | else 57 | { 58 | ret = SHM_UNKNOWN_OP; 59 | } 60 | break; 61 | } 62 | case SHMQ_PARAMETER_WHO_PRIO: 63 | { 64 | if(check_write_id(shmq_handle->self_id)) 65 | { 66 | if(value == READ_PRIO || value == WRITE_PRIO) 67 | { 68 | shmq_handle->who_prior = value; 69 | } 70 | else 71 | { 72 | ret = SHM_UNKNOWN_PRIO; 73 | } 74 | } 75 | else 76 | { 77 | ret = SHM_NO_AUTHORITY; 78 | } 79 | break; 80 | } 81 | default: 82 | { 83 | ret = SHM_UNKNOWN_TYPE; 84 | break; 85 | } 86 | } 87 | return ret; 88 | } 89 | 90 | 91 | 92 | 93 | int open_shm_queue(void*handle, key_t key_id) 94 | { 95 | int ret; 96 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 97 | 98 | if(NULL == shmq_handle) 99 | { 100 | return SHM_HANDLE_NULL; 101 | } 102 | 103 | if(shmq_handle->op_mode == OP_MODE_READ) 104 | { 105 | ret = check_read_id(shmq_handle->self_id); 106 | 107 | if(ret < 0) 108 | { 109 | return SHM_NO_AUTHORITY; 110 | } 111 | 112 | ret = shmget(key_id, 0, 0); 113 | 114 | if(ret < 0) 115 | { 116 | return SHM_NO_SHM; 117 | } 118 | 119 | else 120 | { 121 | char *sh_mem = NULL; 122 | sh_mem = (char*)shmat(ret , NULL , 0); 123 | if(NULL == sh_mem) 124 | { 125 | return SHM_NO_SHM; 126 | } 127 | 128 | init_read_handle_info(shmq_handle,key_id, sh_mem); 129 | } 130 | } 131 | 132 | else if(shmq_handle->op_mode == OP_MODE_WRITE) 133 | { 134 | ret = check_write_id(shmq_handle->self_id); 135 | 136 | if(!ret) 137 | { 138 | return SHM_NO_AUTHORITY; 139 | } 140 | 141 | ret = shmget(key_id,0,0); 142 | if(ret < 0) 143 | { 144 | 145 | int mem_len = sizeof(shm_queue_info_t) + 146 | sizeof(circular_array_t) + 147 | shmq_handle->para_pool_size + 148 | shmq_handle->para_queue_size * sizeof(block_info_t); 149 | 150 | shmq_handle->shm_fd = shmget(key_id,mem_len,0666 | IPC_CREAT); 151 | 152 | if(shmq_handle->shm_fd < 0) 153 | { 154 | return SHM_CREATE_SHMEM_FAIL; 155 | } 156 | char *sh_mem= (char*)shmat(shmq_handle->shm_fd, NULL, 0); 157 | init_shm_info(sh_mem, shmq_handle); 158 | init_write_handle_info(shmq_handle, key_id, sh_mem); 159 | } 160 | else 161 | { 162 | return SHM_ALREADY_EXIST; 163 | } 164 | } 165 | 166 | else 167 | { 168 | return SHM_UNKNOWN_OP; 169 | } 170 | 171 | return SHM_OK; 172 | } 173 | 174 | 175 | int read_shm_queue(void*handle, char *to_read_buf, int buf_len) 176 | { 177 | int ret; 178 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 179 | 180 | if(NULL == shmq_handle) 181 | { 182 | return SHM_HANDLE_NULL; 183 | } 184 | 185 | if(shmq_handle->op_mode != OP_MODE_READ) 186 | { 187 | return SHM_OP_WRONG; 188 | } 189 | 190 | ret = is_empty(shmq_handle->que); 191 | if(ret > 0) 192 | { 193 | return SHM_NO_DATA; 194 | } 195 | 196 | block_info_t *to_read_block; 197 | int off_set = sizeof(shm_queue_info_t) + sizeof(circular_array_t) + sizeof(block_info_t) * shmq_handle->op_pos; 198 | to_read_block = (block_info_t*)((char*)(shmq_handle->shm_que_info) + off_set); 199 | 200 | if(shmq_handle->op_pos == shmq_handle->que->tail) 201 | { 202 | return SHM_NO_DATA; 203 | } 204 | 205 | ret = get_read_num(shmq_handle->self_id); 206 | 207 | if(to_read_block->flags[ret] == FLAG_TRUE) 208 | { 209 | return SHM_DATA_READED_YET; 210 | } 211 | 212 | if(to_read_block->block_size <= 0) 213 | { 214 | return SHM_NO_DATA; 215 | } 216 | 217 | if(to_read_block->block_size > buf_len) 218 | { 219 | return SHM_BUF_SHORT; 220 | } 221 | 222 | int read_len = read_block(to_read_block,shmq_handle,to_read_buf, buf_len); 223 | 224 | to_read_block->flags[ret] = FLAG_TRUE; 225 | 226 | shmq_handle->op_total += (to_read_block->block_size); 227 | 228 | shmq_handle->op_pos = (shmq_handle->op_pos + 1) % shmq_handle->para_queue_size; 229 | 230 | return read_len; 231 | } 232 | 233 | 234 | 235 | int write_shm_queue(void* handle, const char* to_write_buf, int buf_len) 236 | { 237 | 238 | int ret; 239 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 240 | 241 | if(NULL == shmq_handle) 242 | { 243 | return SHM_HANDLE_NULL; 244 | } 245 | 246 | if(shmq_handle->op_mode != OP_MODE_WRITE) 247 | { 248 | return SHM_OP_WRONG; 249 | } 250 | 251 | if(shmq_handle->pool_size < buf_len) 252 | { 253 | return SHM_BUF_SHORT; 254 | } 255 | 256 | pthread_rwlock_wrlock(&(shmq_handle->shm_que_info->rwlock)); 257 | int f_ret; 258 | while((f_ret = is_full(shmq_handle->que,shmq_handle->para_queue_size)) > 0 259 | || shmq_handle->shm_que_info->pool_left_size < buf_len) 260 | { 261 | block_info_t *head_block; 262 | int head_offset = sizeof(shm_queue_info_t) + sizeof(circular_array_t) + sizeof(block_info_t) * (shmq_handle->que->head); 263 | head_block = (block_info_t*)((char*)(shmq_handle->shm_que_info) + head_offset); 264 | 265 | if(shmq_handle->who_prior == READ_PRIO) 266 | { 267 | int i = 0; 268 | for( i = 0; i < MAX_PROC_NUM; i++) 269 | { 270 | if(shmq_handle->shm_que_info->read_flags[i] == FLAG_TRUE) 271 | { 272 | while(head_block->flags[i] == FLAG_FALSE) 273 | { 274 | /* 275 | i think a clock will be here when i have more time 276 | */ 277 | } 278 | } 279 | } 280 | } 281 | 282 | else if(shmq_handle->who_prior == WRITE_PRIO) 283 | { 284 | int i = 0; 285 | for(i = 0; i < MAX_PROC_NUM; i++) 286 | { 287 | if(shmq_handle->shm_que_info->read_flags[i] == FLAG_TRUE && head_block->flags[i] == FLAG_FALSE) 288 | { 289 | shmq_handle->readers_miss[i].miss_bytes += head_block->block_size; 290 | shmq_handle->readers_miss[i].miss_block_num++; 291 | } 292 | } 293 | } 294 | 295 | 296 | ret = out_queue(shmq_handle->que,shmq_handle->para_queue_size); 297 | if(ret == SHM_OK) 298 | { 299 | shmq_handle->shm_que_info->pool_left_size += head_block->block_size; 300 | } 301 | 302 | else 303 | { 304 | pthread_rwlock_unlock(&(shmq_handle->shm_que_info->rwlock)); 305 | return SHM_OUT_QUEUE_FAIL; 306 | } 307 | } 308 | 309 | ret = is_full(shmq_handle->que,shmq_handle->para_queue_size); 310 | 311 | if(ret < 0 && shmq_handle->shm_que_info->pool_left_size >= buf_len) 312 | { 313 | write_block(shmq_handle,to_write_buf,buf_len); 314 | } 315 | 316 | else 317 | { 318 | pthread_rwlock_unlock(&(shmq_handle->shm_que_info->rwlock)); 319 | return SHM_NO_SPACE; 320 | } 321 | 322 | pthread_rwlock_unlock(&(shmq_handle->shm_que_info->rwlock)); 323 | return SHM_OK; 324 | } 325 | 326 | 327 | int close_shm_queue(void*handle) 328 | { 329 | 330 | int ret; 331 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 332 | 333 | if(shmq_handle == NULL) 334 | { 335 | return SHM_HANDLE_NULL; 336 | } 337 | 338 | if(shmq_handle->self_id != shmq_handle->shm_que_info->owner_id) 339 | { 340 | return SHM_NO_AUTHORITY; 341 | } 342 | 343 | if(shmq_handle->shm_que_info->op_num != 1) 344 | { 345 | sleep(5); 346 | /* 347 | give 5 sec is enough 348 | */ 349 | } 350 | 351 | shmctl(shmq_handle->shm_fd,IPC_RMID,NULL); 352 | 353 | ret = shmget(shmq_handle->shm_fd,0,0); 354 | 355 | if(!ret) 356 | { 357 | return SHM_OK; 358 | } 359 | 360 | else 361 | { 362 | return SHM_DELETE_SHM_FAIL; 363 | } 364 | } 365 | 366 | 367 | 368 | int destroy_shm_queue_handle(void*handle) 369 | { 370 | 371 | shm_queue_handle_t *shmq_handle = (shm_queue_handle_t*)handle; 372 | int ret = -1; 373 | if(shmq_handle->op_mode == OP_MODE_READ) 374 | { 375 | shmq_handle->shm_que_info->read_flags[get_read_num(shmq_handle->self_id)] = '0'; 376 | 377 | pthread_mutex_lock(&shmq_handle->shm_que_info->mutex); 378 | shmq_handle->shm_que_info->op_num--; 379 | pthread_mutex_unlock(&shmq_handle->shm_que_info->mutex); 380 | 381 | shmdt((char*)shmq_handle->shm_que_info); 382 | ret = SHM_OK; 383 | } 384 | else if(shmq_handle->op_mode == OP_MODE_WRITE) 385 | { 386 | ret = close_shm_queue(handle); 387 | } 388 | free(handle); 389 | return ret; 390 | } 391 | 392 | 393 | 394 | 395 | -------------------------------------------------------------------------------- /shm_rr_queue.h: -------------------------------------------------------------------------------- 1 | #ifndef __H_SHM_RR_QUEUE_HEADER_ 2 | #define __H_SHM_RR_QUEUE_HEADER_ 3 | 4 | /** 5 | * 6 | * METHOD: get_shm_queue_handle 7 | * DESCRIPTION: get a handle 8 | * @param : self_id , a id contributed to process 9 | * @return : NULL if fail, not NULL if success 10 | */ 11 | 12 | void *get_shm_queue_handle(int self_id); 13 | 14 | 15 | /** 16 | * 17 | * METHOD: set_shm_queue_handle 18 | * DESCRIPTION: set shared memory's info 19 | * @param : handle, handle not NULL 20 | * @param : type, SHMQ_PARAMETER_POOL_SIZE,SHMQ_PARAMETER_BLOCK_NUM,SHMQ_PARAMETER_OP_MODE,SHMQ_PARAMETER_WHO_PRIO in 21 | * file shm_core.h 22 | * @param : value, in shm_core.h 23 | * @return : value in shm_core.h enum SHM_FAIL_RET 24 | */ 25 | 26 | int set_shm_queue_handle(void *handle, int type, int value); 27 | 28 | 29 | /** 30 | * 31 | * METHOD: open_shm_queue 32 | * DESCRIPTION: open the shared memory, write process will create shared memory 33 | * @param : handle,can not NULL 34 | * @param : key_id, shared memory's key_id 35 | * @return : value in shm_core.h enum SHM_FAIL_RET 36 | */ 37 | 38 | int open_shm_queue(void*handle, key_t key_id); 39 | 40 | 41 | /** 42 | * 43 | * METHOD: read_shm_queue 44 | * DESCRIPTION: read a block from shared memory 45 | * @param : handle,can not NULL 46 | * @param : to_read_buf, buf 47 | * @param : buf_len, length of buf 48 | * @return : length read from shared memory,if fail return value in shm_core.h enum SHM_FAIL_RET 49 | */ 50 | 51 | int read_shm_queue(void*handle, char *to_read_buf, int buf_len); 52 | 53 | 54 | /** 55 | * 56 | * METHOD: write_shm_queue 57 | * DESCRIPTION: write a block to shared memory 58 | * @param : handle,can not NULL 59 | * @param : to_write_buf, buf 60 | * @param : buf_len, length of buf 61 | * @return : return value in shm_core.h enum SHM_FAIL_RET 62 | */ 63 | 64 | int write_shm_queue(void* handle, const char* to_write_buf, int buf_len); 65 | 66 | 67 | /** 68 | * 69 | * METHOD: close_shm_queue 70 | * DESCRIPTION: writer process close shared memory 71 | * @param : handle,can not NULL 72 | * @return : return value in shm_core.h enum SHM_FAIL_RET 73 | */ 74 | 75 | int close_shm_queue(void*handle); 76 | 77 | 78 | /** 79 | * 80 | * METHOD: destroy_shm_queue_handle 81 | * DESCRIPTION: destroy handle 82 | * @param : handle,can not NULL 83 | * @return : return value in shm_core.h enum SHM_FAIL_RET 84 | */ 85 | 86 | int destroy_shm_queue_handle(void*handle); 87 | 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /snow_ball.h: -------------------------------------------------------------------------------- 1 | #ifndef __H_SNOW_BALL_HEADER 2 | #define __H_SNOW_BALL_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | #ifndef OP_MODE_READ 10 | #define OP_MODE_READ 0x01 /* value of SHMQ_PARAMETER_OP_MODE,set the op mode read*/ 11 | #endif 12 | 13 | #ifndef OP_MODE_WRITE 14 | #define OP_MODE_WRITE 0x02 /* value of SHMQ_PARAMETER_OP_MODE,set the op mode write*/ 15 | #endif 16 | 17 | #ifndef READ_PRIO 18 | #define READ_PRIO 0x01 /* value of SHMQ_PARAMETER_WHO_PRIO, 19 | this will assure all the data to be read before covered */ 20 | #endif 21 | 22 | #ifndef WRITE_PRIO 23 | #define WRITE_PRIO 0x02 /* value of SHMQ_PARAMETER_WHO_PRIO, 24 | this will assure the write process write as fast as it can,it will not wait for reader*/ 25 | #endif 26 | 27 | #ifndef SHMQ_PARAMETER_POOL_SIZE 28 | #define SHMQ_PARAMETER_POOL_SIZE 0x01 /* type to set shm's size*/ 29 | #endif 30 | 31 | #ifndef SHMQ_PARAMETER_BLOCK_NUM 32 | #define SHMQ_PARAMETER_BLOCK_NUM 0x02 /* type to set the num of queue'elements*/ 33 | #endif 34 | 35 | #ifndef SHMQ_PARAMETER_OP_MODE 36 | #define SHMQ_PARAMETER_OP_MODE 0x03 /* type to set op mod*/ 37 | #endif 38 | 39 | #ifndef SHMQ_PARAMETER_WHO_PRIO 40 | #define SHMQ_PARAMETER_WHO_PRIO 0x04 /* type to set read is prio or write is*/ 41 | #endif 42 | 43 | #ifndef RETURN_RET 44 | #define RETURN_RET 1 45 | 46 | enum SHM_RETURN_RET{ 47 | SHM_HANDLE_NULL = -201, /* error: the handle is null*/ 48 | SHM_UNKNOWN_OP, /* error: unknown op type*/ 49 | SHM_OP_WRONG, /* error: op value can't map the op mod*/ 50 | SHM_UNKNOWN_PRIO, /* error:the value of SHMQ_PARAMETER_WHO_PRIO is wrong*/ 51 | SHM_NO_AUTHORITY, /* error:the process don't have been authorized*/ 52 | SHM_UNKNOWN_TYPE, /* error:set a unknown type*/ 53 | SHM_NO_SHM, /* error:the shared memory is not exist*/ 54 | SHM_CREATE_SHMEM_FAIL, /* error: fail to create shared memory*/ 55 | SHM_ALREADY_EXIST, /* error: the shared memory is exist,can't create it repeatedly*/ 56 | SHM_NO_DATA, /* error: no data in the shared memory*/ 57 | SHM_DATA_READED_YET, /* error: this data block has been read by the same process*/ 58 | SHM_OUT_QUEUE_FAIL, /* error: fail to dequeue the tail*/ 59 | SHM_NO_SPACE, /* error: no space left to write data to shared memory*/ 60 | SHM_DELETE_SHM_FAIL, /* error:delete the shared memory failed*/ 61 | SHM_BUF_SHORT,/*error: when read if buf is too short,when write if shm is too short*/ 62 | SHM_FAIL = -1, /* error:the function gets a fail result*/ 63 | SHM_OK = 1 /* the function success*/ 64 | }; 65 | #endif 66 | 67 | /** 68 | * 69 | * METHOD: get_shm_queue_handle 70 | * DESCRIPTION: get a handle 71 | * @param : self_id , a id contributed to process 72 | * @return : NULL if fail, not NULL if success 73 | */ 74 | 75 | void *get_shm_queue_handle(int self_id); 76 | 77 | /** 78 | * 79 | * METHOD: set_shm_queue_handle 80 | * DESCRIPTION: set shared memory's info 81 | * @param : handle, handle not NULL 82 | * @param : type, SHMQ_PARAMETER_POOL_SIZE,SHMQ_PARAMETER_BLOCK_NUM,SHMQ_PARAMETER_OP_MODE,SHMQ_PARAMETER_WHO_PRIO 83 | * @param : value, 84 | * @return : value in enum SHM_FAIL_RET 85 | */ 86 | 87 | int set_shm_queue_handle(void *handle, int type, int value); 88 | 89 | /** 90 | * 91 | * METHOD: open_shm_queue 92 | * DESCRIPTION: open the shared memory, write process will create shared memory 93 | * @param : handle,can not NULL 94 | * @param : key_id, shared memory's key_id 95 | * @return : value in enum SHM_FAIL_RET 96 | */ 97 | 98 | int open_shm_queue(void*handle, key_t key_id); 99 | 100 | /** 101 | * 102 | * METHOD: read_shm_queue 103 | * DESCRIPTION: read a block from shared memory 104 | * @param : handle,can not NULL 105 | * @param : to_read_buf, buf 106 | * @param : buf_len, length of buf 107 | * @return : length read from shared memory,if fail return value in enum SHM_FAIL_RET 108 | */ 109 | 110 | int read_shm_queue(void*handle, char *to_read_buf, int buf_len); 111 | 112 | /** 113 | * 114 | * METHOD: write_shm_queue 115 | * DESCRIPTION: write a block to shared memory 116 | * @param : handle,can not NULL 117 | * @param : to_write_buf, buf 118 | * @param : buf_len, length of buf 119 | * @return : return value in enum SHM_FAIL_RET 120 | */ 121 | 122 | int write_shm_queue(void* handle, const char* to_write_buf, int buf_len); 123 | 124 | 125 | /** 126 | * 127 | * METHOD: destroy_shm_queue_handle 128 | * DESCRIPTION: destroy handle 129 | * @param : handle,can not NULL 130 | * @return : return value in enum SHM_FAIL_RET 131 | */ 132 | 133 | int destroy_shm_queue_handle(void*handle); 134 | 135 | 136 | #ifdef __cplusplus 137 | } 138 | #endif 139 | 140 | #endif 141 | --------------------------------------------------------------------------------