├── README.md ├── linux_datastruct ├── list │ ├── list.h │ └── main.c └── rbtree │ ├── main.c │ ├── rbtree.c │ └── rbtree.h ├── litequeue ├── litequeue.c ├── litequeue.h └── main.c ├── ringbuffer ├── readme.md ├── ringbuffer_copy │ ├── Makefile │ ├── main.c │ ├── ringbuffer.c │ └── ringbuffer.h ├── ringbuffer_muti │ ├── Makefile │ ├── main.c │ ├── ringbuffer_muti.c │ └── ringbuffer_muti.h ├── ringbuffer_no_copy │ ├── Makefile │ ├── main.c │ ├── ringbuffer.c │ └── ringbuffer.h ├── ringbuffer_single │ ├── Makefile │ ├── main.c │ ├── ringbuffer_single.c │ └── ringbuffer_single.h └── testfile │ └── generate_bin_file.cpp └── slist ├── main.c └── slist.h /README.md: -------------------------------------------------------------------------------- 1 | 一些精巧实用得数据结构模块 2 | 1.使用二重指针实现队列、栈 3 | 2.循环buffer,拷贝与免拷贝 4 | 3.slist C语言实现泛型单链表 5 | -------------------------------------------------------------------------------- /linux_datastruct/list/list.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _LIST_HEAD_H 3 | #define _LIST_HEAD_H 4 | 5 | // 双向链表节点 6 | struct list_head { 7 | struct list_head *next, *prev; 8 | }; 9 | 10 | // 初始化节点:设置name节点的前继节点和后继节点都是指向name本身。 11 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 12 | 13 | // 定义表头(节点):新建双向链表表头name,并设置name的前继节点和后继节点都是指向name本身。 14 | #define LIST_HEAD(name) \ 15 | struct list_head name = LIST_HEAD_INIT(name) 16 | 17 | // 初始化节点:将list节点的前继节点和后继节点都是指向list本身。 18 | static inline void INIT_LIST_HEAD(struct list_head *list) 19 | { 20 | list->next = list; 21 | list->prev = list; 22 | } 23 | 24 | // 添加节点:将new_n插入到prev和next之间。 25 | static inline void __list_add(struct list_head *new_n, 26 | struct list_head *prev, 27 | struct list_head *next) 28 | { 29 | next->prev = new_n; 30 | new_n->next = next; 31 | new_n->prev = prev; 32 | prev->next = new_n; 33 | } 34 | 35 | // 添加new_n节点:将new_n添加到head之后,是new_n称为head的后继节点。 36 | static inline void list_add(struct list_head *new_n, struct list_head *head) 37 | { 38 | __list_add(new_n, head, head->next); 39 | } 40 | 41 | // 添加new_n节点:将new_n添加到head之前,即将new_n添加到双链表的末尾。 42 | static inline void list_add_tail(struct list_head *new_n, struct list_head *head) 43 | { 44 | __list_add(new_n, head->prev, head); 45 | } 46 | 47 | // 从双链表中删除entry节点。 48 | static inline void __list_del(struct list_head * prev, struct list_head * next) 49 | { 50 | next->prev = prev; 51 | prev->next = next; 52 | } 53 | 54 | // 从双链表中删除entry节点。 55 | static inline void list_del(struct list_head *entry) 56 | { 57 | __list_del(entry->prev, entry->next); 58 | } 59 | 60 | // 从双链表中删除entry节点。 61 | static inline void __list_del_entry(struct list_head *entry) 62 | { 63 | __list_del(entry->prev, entry->next); 64 | } 65 | 66 | // 从双链表中删除entry节点,并将entry节点的前继节点和后继节点都指向entry本身。 67 | static inline void list_del_init(struct list_head *entry) 68 | { 69 | __list_del_entry(entry); 70 | INIT_LIST_HEAD(entry); 71 | } 72 | 73 | // 用new_n节点取代old节点 74 | static inline void list_replace(struct list_head *old, 75 | struct list_head *new_n) 76 | { 77 | new_n->next = old->next; 78 | new_n->next->prev = new_n; 79 | new_n->prev = old->prev; 80 | new_n->prev->next = new_n; 81 | } 82 | 83 | // 双链表是否为空 84 | static inline int list_empty(const struct list_head *head) 85 | { 86 | return head->next == head; 87 | } 88 | 89 | // 获取"MEMBER成员"在"结构体TYPE"中的位置偏移 90 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 91 | 92 | // 根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针 93 | #define container_of(ptr, type, member) ({ \ 94 | const __typeof( ((type *)0)->member ) *__mptr = (ptr); \ 95 | (type *)( (char *)__mptr - offsetof(type,member) );}) 96 | 97 | #define list_entry(ptr, type, member) \ 98 | container_of(ptr, type, member) 99 | 100 | // 遍历双向链表 101 | #define list_for_each(pos, head) \ 102 | for (pos = (head)->next; pos != (head); pos = pos->next) 103 | 104 | #define list_for_each_safe(pos, n, head) \ 105 | for (pos = (head)->next, n = pos->next; pos != (head); \ 106 | pos = n, n = pos->next) 107 | 108 | #endif -------------------------------------------------------------------------------- /linux_datastruct/list/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "list.h" 4 | 5 | //定义用户结构体 6 | struct info_t 7 | { 8 | int id; 9 | char name[32]; 10 | struct list_head node; //作为链表的一个节点 11 | }; 12 | 13 | int main(int argc, char** argv) 14 | { 15 | struct list_head hlist; //链表头节点 16 | struct info_t *pnode; 17 | 18 | INIT_LIST_HEAD(&hlist); //初始化链表头节点 19 | 20 | for(int i=0; i<10; ++i){ 21 | //申请内存,创建节点 22 | pnode = (struct info_t*)malloc(sizeof(struct info_t)); 23 | pnode->id=i; 24 | snprintf(pnode->name, 32, "Info-%d", i); 25 | list_add_tail(&pnode->node, &hlist);//将节点加入链表 26 | } 27 | 28 | struct list_head *pos, *n; 29 | struct info_t *pinfo; 30 | list_for_each(pos, &hlist){ //遍历链表 31 | pinfo = list_entry(pos, struct info_t, node); 32 | printf("get node: %s\n", pinfo->name); 33 | }; 34 | 35 | list_for_each_safe(pos, n, &hlist){ //遍历并删除节点 36 | pinfo = list_entry(pos, struct info_t, node); 37 | printf("del safe node: %s\n", pinfo->name); 38 | list_del(pos); 39 | free(pinfo); 40 | } 41 | 42 | int is_empty = list_empty(&hlist); 43 | printf("链表状态: %s\n", is_empty?"空":"非空"); 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /linux_datastruct/rbtree/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "rbtree.h" 4 | 5 | 6 | /** 7 | * 定义用户的数据结构,包含rb_node 8 | */ 9 | struct info_t { 10 | struct rb_node node; // 红黑树节点 11 | int key; // 键值 12 | //...... 自定义其他数据结构 13 | }; 14 | 15 | /** 16 | * 根据key值在红黑树中搜索, 17 | */ 18 | struct info_t* rbtree_search(struct rb_root *root, int key) 19 | { 20 | struct rb_node *rbnode = root->rb_node; 21 | struct info_t *pinfo=NULL; 22 | 23 | while (rbnode!=NULL) 24 | { 25 | pinfo = container_of(rbnode, struct info_t, node);//获取节点信息 26 | 27 | if (key < pinfo->key) //key值小于当前节点key,往左边节点走 28 | rbnode = rbnode->rb_left; 29 | else if (key > pinfo->key) //key值大于当前节点key,往右边节点走 30 | rbnode = rbnode->rb_right; 31 | else //找到key返回 32 | return pinfo; 33 | } 34 | 35 | return NULL; //未找到,返回null 36 | } 37 | 38 | /** 39 | * 往红黑树中插入一个节点 40 | */ 41 | int rbtree_insert(struct rb_root *root, struct info_t *new) 42 | { 43 | struct info_t *mynode, *pinfo; // 新建结点 44 | struct rb_node **tmp = &(root->rb_node), *parent = NULL; 45 | int key = new->key; 46 | 47 | //1.找到插入节点位置 48 | while (*tmp) 49 | { 50 | pinfo = container_of(*tmp, struct info_t, node); 51 | 52 | parent = *tmp; 53 | if (key < pinfo->key) 54 | tmp = &((*tmp)->rb_left); 55 | else if (key > pinfo->key) 56 | tmp = &((*tmp)->rb_right); 57 | else 58 | return -1; 59 | } 60 | 61 | //2.插入节点 62 | rb_link_node(&new->node, parent, tmp); 63 | //3.调整并重新着色 64 | rb_insert_color(&new->node, root); 65 | 66 | return 0; 67 | } 68 | 69 | /** 70 | * 删除一个节点 71 | * 注意:只是从红黑树移除节点,并未free内存,需要外部free内存 72 | */ 73 | struct info_t* rbtree_delete(struct rb_root *root, int key) 74 | { 75 | struct info_t *tmp=NULL; 76 | 77 | // 在红黑树中查找key对应的节点tmp 78 | if ((tmp = rbtree_search(root, key)) == NULL) 79 | return NULL; 80 | // 从红黑树中删除节点tmp 81 | rb_erase(&tmp->node, root); 82 | 83 | return tmp; 84 | } 85 | 86 | /** 87 | * 这个函数只是我们用来打印看节点信息的 88 | */ 89 | static void rbtree_print(struct rb_node *tree, int key, int direction) 90 | { 91 | if(tree != NULL) 92 | { 93 | if(direction==0) // tree是根节点 94 | printf("%2d(B) is root\n", key); 95 | else // tree是分支节点 96 | printf("%2d(%s) is %2d's %6s child\n", key, rb_is_black(tree)?"B":"R", key, direction==1?"right" : "left"); 97 | 98 | if (tree->rb_left) 99 | rbtree_print(tree->rb_left, rb_entry(tree->rb_left, struct info_t, node)->key, -1); 100 | if (tree->rb_right) 101 | rbtree_print(tree->rb_right,rb_entry(tree->rb_right, struct info_t, node)->key, 1); 102 | } 103 | } 104 | 105 | void show(struct rb_root *root) 106 | { 107 | if (root!=NULL && root->rb_node!=NULL) 108 | rbtree_print(root->rb_node, rb_entry(root->rb_node, struct info_t, node)->key, 0); 109 | } 110 | 111 | 112 | void main() 113 | { 114 | int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80}; 115 | int i, ilen=sizeof(a)/sizeof(a[0]); 116 | struct rb_root mytree = RB_ROOT; 117 | struct info_t *pinfo=NULL; 118 | 119 | printf("== 原始数据: "); 120 | for(i=0; ikey = a[i]; 128 | rbtree_insert(&mytree, pinfo); 129 | 130 | printf("== 添加节点: %d\n", a[i]); 131 | printf("== 树的详细信息: \n"); 132 | show(&mytree); 133 | printf("\n"); 134 | } 135 | 136 | for (i=0; i 4 | (C) 2002 David Woodhouse 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | linux/lib/rbtree.c 21 | */ 22 | 23 | #include "rbtree.h" 24 | 25 | static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) 26 | { 27 | struct rb_node *right = node->rb_right; 28 | struct rb_node *parent = rb_parent(node); 29 | 30 | if ((node->rb_right = right->rb_left)) 31 | rb_set_parent(right->rb_left, node); 32 | right->rb_left = node; 33 | 34 | rb_set_parent(right, parent); 35 | 36 | if (parent) 37 | { 38 | if (node == parent->rb_left) 39 | parent->rb_left = right; 40 | else 41 | parent->rb_right = right; 42 | } 43 | else 44 | root->rb_node = right; 45 | rb_set_parent(node, right); 46 | } 47 | 48 | static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 49 | { 50 | struct rb_node *left = node->rb_left; 51 | struct rb_node *parent = rb_parent(node); 52 | 53 | if ((node->rb_left = left->rb_right)) 54 | rb_set_parent(left->rb_right, node); 55 | left->rb_right = node; 56 | 57 | rb_set_parent(left, parent); 58 | 59 | if (parent) 60 | { 61 | if (node == parent->rb_right) 62 | parent->rb_right = left; 63 | else 64 | parent->rb_left = left; 65 | } 66 | else 67 | root->rb_node = left; 68 | rb_set_parent(node, left); 69 | } 70 | 71 | void rb_insert_color(struct rb_node *node, struct rb_root *root) 72 | { 73 | struct rb_node *parent, *gparent; 74 | 75 | /** 76 | * 1.情况说明:被插入的节点是根节点。处理方法:直接把此节点涂为黑色。 77 | * 2.情况说明:被插入的节点的父节点是黑色。处理方法:什么也不需要做。节点被插入后,仍然是红黑树。 78 | * 3.情况说明:被插入的节点的父节点是红色: 79 | * A.当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色。 80 | * (01) 将“父节点”设为黑色。 81 | * (02) 将“叔叔节点”设为黑色。 82 | * (03) 将“祖父节点”设为“红色”。 83 | * (04) 将“祖父节点”设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作。 84 | * B.当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的右孩子 85 | * (01) 将“父节点”作为“新的当前节点”。 86 | * (02) 以“新的当前节点”为支点进行左旋。 87 | * C.当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子 88 | * (01) 将“父节点”设为“黑色”。 89 | * (02) 将“祖父节点”设为“红色”。 90 | * (03) 以“祖父节点”为支点进行右旋。 91 | */ 92 | while ((parent = rb_parent(node)) && rb_is_red(parent)) 93 | { 94 | gparent = rb_parent(parent); 95 | 96 | if (parent == gparent->rb_left) //父节点是左孩子 97 | { 98 | { 99 | register struct rb_node *uncle = gparent->rb_right; 100 | if (uncle && rb_is_red(uncle))//叔叔节点是红色 101 | { 102 | rb_set_black(uncle); 103 | rb_set_black(parent); 104 | rb_set_red(gparent); 105 | node = gparent; 106 | continue; 107 | } 108 | } 109 | 110 | if (parent->rb_right == node) 111 | { 112 | register struct rb_node *tmp; 113 | __rb_rotate_left(parent, root); 114 | tmp = parent; 115 | parent = node; 116 | node = tmp; 117 | } 118 | 119 | rb_set_black(parent); 120 | rb_set_red(gparent); 121 | __rb_rotate_right(gparent, root); 122 | } else { 123 | { 124 | register struct rb_node *uncle = gparent->rb_left; 125 | if (uncle && rb_is_red(uncle)) 126 | { 127 | rb_set_black(uncle); 128 | rb_set_black(parent); 129 | rb_set_red(gparent); 130 | node = gparent; 131 | continue; 132 | } 133 | } 134 | 135 | if (parent->rb_left == node) 136 | { 137 | register struct rb_node *tmp; 138 | __rb_rotate_right(parent, root); 139 | tmp = parent; 140 | parent = node; 141 | node = tmp; 142 | } 143 | 144 | rb_set_black(parent); 145 | rb_set_red(gparent); 146 | __rb_rotate_left(gparent, root); 147 | } 148 | } 149 | 150 | rb_set_black(root->rb_node); 151 | } 152 | 153 | static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, 154 | struct rb_root *root) 155 | { 156 | struct rb_node *other; 157 | 158 | while ((!node || rb_is_black(node)) && node != root->rb_node) 159 | { 160 | if (parent->rb_left == node) 161 | { 162 | other = parent->rb_right; 163 | if (rb_is_red(other)) 164 | { 165 | rb_set_black(other); 166 | rb_set_red(parent); 167 | __rb_rotate_left(parent, root); 168 | other = parent->rb_right; 169 | } 170 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 171 | (!other->rb_right || rb_is_black(other->rb_right))) 172 | { 173 | rb_set_red(other); 174 | node = parent; 175 | parent = rb_parent(node); 176 | } 177 | else 178 | { 179 | if (!other->rb_right || rb_is_black(other->rb_right)) 180 | { 181 | rb_set_black(other->rb_left); 182 | rb_set_red(other); 183 | __rb_rotate_right(other, root); 184 | other = parent->rb_right; 185 | } 186 | rb_set_color(other, rb_color(parent)); 187 | rb_set_black(parent); 188 | rb_set_black(other->rb_right); 189 | __rb_rotate_left(parent, root); 190 | node = root->rb_node; 191 | break; 192 | } 193 | } 194 | else 195 | { 196 | other = parent->rb_left; 197 | if (rb_is_red(other)) 198 | { 199 | rb_set_black(other); 200 | rb_set_red(parent); 201 | __rb_rotate_right(parent, root); 202 | other = parent->rb_left; 203 | } 204 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 205 | (!other->rb_right || rb_is_black(other->rb_right))) 206 | { 207 | rb_set_red(other); 208 | node = parent; 209 | parent = rb_parent(node); 210 | } 211 | else 212 | { 213 | if (!other->rb_left || rb_is_black(other->rb_left)) 214 | { 215 | rb_set_black(other->rb_right); 216 | rb_set_red(other); 217 | __rb_rotate_left(other, root); 218 | other = parent->rb_left; 219 | } 220 | rb_set_color(other, rb_color(parent)); 221 | rb_set_black(parent); 222 | rb_set_black(other->rb_left); 223 | __rb_rotate_right(parent, root); 224 | node = root->rb_node; 225 | break; 226 | } 227 | } 228 | } 229 | if (node) 230 | rb_set_black(node); 231 | } 232 | 233 | void rb_erase(struct rb_node *node, struct rb_root *root) 234 | { 235 | struct rb_node *child, *parent; 236 | int color; 237 | 238 | if (!node->rb_left) 239 | child = node->rb_right; 240 | else if (!node->rb_right) 241 | child = node->rb_left; 242 | else 243 | { 244 | struct rb_node *old = node, *left; 245 | 246 | node = node->rb_right; 247 | while ((left = node->rb_left) != NULL) 248 | node = left; 249 | 250 | if (rb_parent(old)) { 251 | if (rb_parent(old)->rb_left == old) 252 | rb_parent(old)->rb_left = node; 253 | else 254 | rb_parent(old)->rb_right = node; 255 | } else 256 | root->rb_node = node; 257 | 258 | child = node->rb_right; 259 | parent = rb_parent(node); 260 | color = rb_color(node); 261 | 262 | if (parent == old) { 263 | parent = node; 264 | } else { 265 | if (child) 266 | rb_set_parent(child, parent); 267 | parent->rb_left = child; 268 | 269 | node->rb_right = old->rb_right; 270 | rb_set_parent(old->rb_right, node); 271 | } 272 | 273 | node->rb_parent_color = old->rb_parent_color; 274 | node->rb_left = old->rb_left; 275 | rb_set_parent(old->rb_left, node); 276 | 277 | goto color; 278 | } 279 | 280 | parent = rb_parent(node); 281 | color = rb_color(node); 282 | 283 | if (child) 284 | rb_set_parent(child, parent); 285 | if (parent) 286 | { 287 | if (parent->rb_left == node) 288 | parent->rb_left = child; 289 | else 290 | parent->rb_right = child; 291 | } 292 | else 293 | root->rb_node = child; 294 | 295 | color: 296 | if (color == RB_BLACK) 297 | __rb_erase_color(child, parent, root); 298 | } 299 | 300 | static void rb_augment_path(struct rb_node *node, rb_augment_f func, void *data) 301 | { 302 | struct rb_node *parent; 303 | 304 | up: 305 | func(node, data); 306 | parent = rb_parent(node); 307 | if (!parent) 308 | return; 309 | 310 | if (node == parent->rb_left && parent->rb_right) 311 | func(parent->rb_right, data); 312 | else if (parent->rb_left) 313 | func(parent->rb_left, data); 314 | 315 | node = parent; 316 | goto up; 317 | } 318 | 319 | /* 320 | * after inserting @node into the tree, update the tree to account for 321 | * both the new entry and any damage done by rebalance 322 | */ 323 | void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data) 324 | { 325 | if (node->rb_left) 326 | node = node->rb_left; 327 | else if (node->rb_right) 328 | node = node->rb_right; 329 | 330 | rb_augment_path(node, func, data); 331 | } 332 | 333 | /* 334 | * before removing the node, find the deepest node on the rebalance path 335 | * that will still be there after @node gets removed 336 | */ 337 | struct rb_node *rb_augment_erase_begin(struct rb_node *node) 338 | { 339 | struct rb_node *deepest; 340 | 341 | if (!node->rb_right && !node->rb_left) 342 | deepest = rb_parent(node); 343 | else if (!node->rb_right) 344 | deepest = node->rb_left; 345 | else if (!node->rb_left) 346 | deepest = node->rb_right; 347 | else { 348 | deepest = rb_next(node); 349 | if (deepest->rb_right) 350 | deepest = deepest->rb_right; 351 | else if (rb_parent(deepest) != node) 352 | deepest = rb_parent(deepest); 353 | } 354 | 355 | return deepest; 356 | } 357 | 358 | /* 359 | * after removal, update the tree to account for the removed entry 360 | * and any rebalance damage. 361 | */ 362 | void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data) 363 | { 364 | if (node) 365 | rb_augment_path(node, func, data); 366 | } 367 | 368 | /* 369 | * This function returns the first node (in sort order) of the tree. 370 | */ 371 | struct rb_node *rb_first(const struct rb_root *root) 372 | { 373 | struct rb_node *n; 374 | 375 | n = root->rb_node; 376 | if (!n) 377 | return NULL; 378 | while (n->rb_left) 379 | n = n->rb_left; 380 | return n; 381 | } 382 | 383 | struct rb_node *rb_last(const struct rb_root *root) 384 | { 385 | struct rb_node *n; 386 | 387 | n = root->rb_node; 388 | if (!n) 389 | return NULL; 390 | while (n->rb_right) 391 | n = n->rb_right; 392 | return n; 393 | } 394 | 395 | struct rb_node *rb_next(const struct rb_node *node) 396 | { 397 | struct rb_node *parent; 398 | 399 | if (rb_parent(node) == node) 400 | return NULL; 401 | 402 | /* If we have a right-hand child, go down and then left as far 403 | as we can. */ 404 | if (node->rb_right) { 405 | node = node->rb_right; 406 | while (node->rb_left) 407 | node=node->rb_left; 408 | return (struct rb_node *)node; 409 | } 410 | 411 | /* No right-hand children. Everything down and left is 412 | smaller than us, so any 'next' node must be in the general 413 | direction of our parent. Go up the tree; any time the 414 | ancestor is a right-hand child of its parent, keep going 415 | up. First time it's a left-hand child of its parent, said 416 | parent is our 'next' node. */ 417 | while ((parent = rb_parent(node)) && node == parent->rb_right) 418 | node = parent; 419 | 420 | return parent; 421 | } 422 | 423 | struct rb_node *rb_prev(const struct rb_node *node) 424 | { 425 | struct rb_node *parent; 426 | 427 | if (rb_parent(node) == node) 428 | return NULL; 429 | 430 | /* If we have a left-hand child, go down and then right as far 431 | as we can. */ 432 | if (node->rb_left) { 433 | node = node->rb_left; 434 | while (node->rb_right) 435 | node=node->rb_right; 436 | return (struct rb_node *)node; 437 | } 438 | 439 | /* No left-hand children. Go up till we find an ancestor which 440 | is a right-hand child of its parent */ 441 | while ((parent = rb_parent(node)) && node == parent->rb_left) 442 | node = parent; 443 | 444 | return parent; 445 | } 446 | 447 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, 448 | struct rb_root *root) 449 | { 450 | struct rb_node *parent = rb_parent(victim); 451 | 452 | /* Set the surrounding nodes to point to the replacement */ 453 | if (parent) { 454 | if (victim == parent->rb_left) 455 | parent->rb_left = new; 456 | else 457 | parent->rb_right = new; 458 | } else { 459 | root->rb_node = new; 460 | } 461 | if (victim->rb_left) 462 | rb_set_parent(victim->rb_left, new); 463 | if (victim->rb_right) 464 | rb_set_parent(victim->rb_right, new); 465 | 466 | /* Copy the pointers/colour from the victim to the replacement */ 467 | *new = *victim; 468 | } -------------------------------------------------------------------------------- /linux_datastruct/rbtree/rbtree.h: -------------------------------------------------------------------------------- 1 | /* 2 | Red Black Trees 3 | (C) 1999 Andrea Arcangeli 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | linux/include/linux/rbtree.h 20 | 21 | To use rbtrees you'll have to implement your own insert and search cores. 22 | This will avoid us to use callbacks and to drop drammatically performances. 23 | I know it's not the cleaner way, but in C (not in C++) to get 24 | performances and genericity... 25 | 26 | Some example of insert and search follows here. The search is a plain 27 | normal search over an ordered tree. The insert instead must be implemented 28 | in two steps: First, the code must insert the element in order as a red leaf 29 | in the tree, and then the support library function rb_insert_color() must 30 | be called. Such function will do the not trivial work to rebalance the 31 | rbtree, if necessary. 32 | 33 | ----------------------------------------------------------------------- 34 | static inline struct page * rb_search_page_cache(struct inode * inode, 35 | unsigned long offset) 36 | { 37 | struct rb_node * n = inode->i_rb_page_cache.rb_node; 38 | struct page * page; 39 | 40 | while (n) 41 | { 42 | page = rb_entry(n, struct page, rb_page_cache); 43 | 44 | if (offset < page->offset) 45 | n = n->rb_left; 46 | else if (offset > page->offset) 47 | n = n->rb_right; 48 | else 49 | return page; 50 | } 51 | return NULL; 52 | } 53 | 54 | static inline struct page * __rb_insert_page_cache(struct inode * inode, 55 | unsigned long offset, 56 | struct rb_node * node) 57 | { 58 | struct rb_node ** p = &inode->i_rb_page_cache.rb_node; 59 | struct rb_node * parent = NULL; 60 | struct page * page; 61 | 62 | while (*p) 63 | { 64 | parent = *p; 65 | page = rb_entry(parent, struct page, rb_page_cache); 66 | 67 | if (offset < page->offset) 68 | p = &(*p)->rb_left; 69 | else if (offset > page->offset) 70 | p = &(*p)->rb_right; 71 | else 72 | return page; 73 | } 74 | 75 | rb_link_node(node, parent, p); 76 | 77 | return NULL; 78 | } 79 | 80 | static inline struct page * rb_insert_page_cache(struct inode * inode, 81 | unsigned long offset, 82 | struct rb_node * node) 83 | { 84 | struct page * ret; 85 | if ((ret = __rb_insert_page_cache(inode, offset, node))) 86 | goto out; 87 | rb_insert_color(node, &inode->i_rb_page_cache); 88 | out: 89 | return ret; 90 | } 91 | ----------------------------------------------------------------------- 92 | */ 93 | 94 | #ifndef _SLINUX_RBTREE_H 95 | #define _SLINUX_RBTREE_H 96 | 97 | #include 98 | //#include 99 | //#include 100 | 101 | struct rb_node 102 | { 103 | unsigned long rb_parent_color; 104 | #define RB_RED 0 105 | #define RB_BLACK 1 106 | struct rb_node *rb_right; 107 | struct rb_node *rb_left; 108 | }__attribute__((aligned(sizeof(long)))); 109 | /* The alignment might seem pointless, but allegedly CRIS needs it */ 110 | 111 | struct rb_root 112 | { 113 | struct rb_node *rb_node; 114 | }; 115 | 116 | 117 | #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) 118 | #define rb_color(r) ((r)->rb_parent_color & 1) 119 | #define rb_is_red(r) (!rb_color(r)) 120 | #define rb_is_black(r) rb_color(r) 121 | #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) 122 | #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) 123 | 124 | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 125 | { 126 | rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; 127 | } 128 | static inline void rb_set_color(struct rb_node *rb, int color) 129 | { 130 | rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 131 | } 132 | 133 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 134 | 135 | #define container_of(ptr, type, member) ({ \ 136 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 137 | (type *)( (char *)__mptr - offsetof(type,member) );}) 138 | 139 | #define RB_ROOT (struct rb_root) { NULL, } 140 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) 141 | 142 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 143 | #define RB_EMPTY_NODE(node) (rb_parent(node) == node) 144 | #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) 145 | 146 | static inline void rb_init_node(struct rb_node *rb) 147 | { 148 | rb->rb_parent_color = 0; 149 | rb->rb_right = NULL; 150 | rb->rb_left = NULL; 151 | RB_CLEAR_NODE(rb); 152 | } 153 | 154 | extern void rb_insert_color(struct rb_node *, struct rb_root *); 155 | extern void rb_erase(struct rb_node *, struct rb_root *); 156 | 157 | typedef void (*rb_augment_f)(struct rb_node *node, void *data); 158 | 159 | extern void rb_augment_insert(struct rb_node *node, 160 | rb_augment_f func, void *data); 161 | extern struct rb_node *rb_augment_erase_begin(struct rb_node *node); 162 | extern void rb_augment_erase_end(struct rb_node *node, 163 | rb_augment_f func, void *data); 164 | 165 | /* Find logical next and previous nodes in a tree */ 166 | extern struct rb_node *rb_next(const struct rb_node *); 167 | extern struct rb_node *rb_prev(const struct rb_node *); 168 | extern struct rb_node *rb_first(const struct rb_root *); 169 | extern struct rb_node *rb_last(const struct rb_root *); 170 | 171 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ 172 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 173 | struct rb_root *root); 174 | 175 | static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, 176 | struct rb_node ** rb_link) 177 | { 178 | node->rb_parent_color = (unsigned long )parent; 179 | node->rb_left = node->rb_right = NULL; 180 | 181 | *rb_link = node; 182 | } 183 | 184 | #endif /* _LINUX_RBTREE_H */ -------------------------------------------------------------------------------- /litequeue/litequeue.c: -------------------------------------------------------------------------------- 1 | #include "litequeue.h" 2 | 3 | 4 | static int insert_tail_lite_queue(LiteQueue* queue, void* elem) 5 | { 6 | if(!queue || !elem || queue->curr_num > queue->max_node) return -1; 7 | 8 | void **node = (void**)((char*)elem+queue->offset); 9 | *queue->tail = node; 10 | queue->tail = node; 11 | *queue->tail = NULL; 12 | 13 | ++queue->curr_num; 14 | 15 | return 0; 16 | } 17 | 18 | static int insert_head_lite_queue(LiteQueue* queue, void* elem) 19 | { 20 | if(!queue || !elem || queue->curr_num > queue->max_node) return -1; 21 | void **node = (void**)((char*)elem+queue->offset); 22 | 23 | void** tmp = *queue->head; 24 | *queue->head = node; 25 | *node = tmp; 26 | 27 | ++queue->curr_num; 28 | 29 | return 0; 30 | } 31 | 32 | static void* front_lite_queue(LiteQueue* queue) 33 | { 34 | void** head=NULL; 35 | void* msg=NULL; 36 | 37 | if(!queue) return NULL; 38 | head = queue->head; 39 | 40 | if(!(*head)) return NULL; 41 | msg = (char*)*head - queue->offset; 42 | 43 | //删除节点 44 | head=*head; 45 | *queue->head = *head; 46 | 47 | --queue->curr_num; 48 | 49 | return msg; 50 | } 51 | 52 | static void free_lite_queue(LiteQueue* queue) 53 | { 54 | if(queue) free(queue); 55 | queue=NULL; 56 | } 57 | 58 | static int empty_lite_queue(LiteQueue* queue) 59 | { 60 | if(*queue->head==NULL) return 1; 61 | return 0; 62 | } 63 | 64 | LiteQueue* create_lite_queue(int max, int offset) 65 | { 66 | LiteQueue* queue = (LiteQueue*)malloc(sizeof(LiteQueue)); 67 | if(!queue) return NULL; 68 | queue->curr_num = 0; 69 | queue->max_node = max; 70 | queue->offset = offset; 71 | queue->head = (void**)&queue->node; 72 | queue->tail = queue->head; 73 | *queue->tail = NULL; 74 | 75 | queue->front = front_lite_queue; 76 | queue->insert_head = insert_head_lite_queue; 77 | queue->insert_tail = insert_tail_lite_queue; 78 | queue->free = free_lite_queue; 79 | queue->empty = empty_lite_queue; 80 | return queue; 81 | } 82 | -------------------------------------------------------------------------------- /litequeue/litequeue.h: -------------------------------------------------------------------------------- 1 | #ifndef __LITE_SDH_H__ 2 | #define __LITE_SDH_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct LiteQueue 9 | { 10 | void** head; //管理头节点 11 | void** tail; //管理尾节点 12 | int offset; //偏移即承载数据的大小 13 | int max_node; //链表中的最大节点数 14 | int curr_num; //当前链表中的节点数 15 | size_t node; //节点头位置 16 | 17 | int (*insert_head)(struct LiteQueue* queue, void* elem); //往头部插入数据 18 | int (*insert_tail)(struct LiteQueue* queue, void* elem); //往尾部插入数据 19 | void*(*front)(struct LiteQueue* queue); //取头节点 20 | void (*free)(struct LiteQueue* queue); //释放内存 21 | int (*empty)(struct LiteQueue* queue); //是否为空 22 | }LiteQueue; 23 | 24 | LiteQueue* create_lite_queue(int max, int offset); 25 | 26 | #define foreach_lite_queue(queue, msg) \ 27 | void** _node; \ 28 | for(_node=queue->head,msg=(char*)*_node-queue->offset; \ 29 | *_node; \ 30 | _node=*_node,msg=(char*)*_node-queue->offset) 31 | 32 | #endif // !__LITE_SDH_H__ 33 | -------------------------------------------------------------------------------- /litequeue/main.c: -------------------------------------------------------------------------------- 1 | #include "litequeue.h" 2 | 3 | void queue_test(void) //先进先出 4 | { 5 | LiteQueue* queue = create_lite_queue(100, 32); 6 | char *msg=NULL; 7 | 8 | //1.队列插入元素 9 | for(int i=0; i<5; ++i) 10 | { 11 | msg = (char*)malloc(32); //申请内存 12 | sprintf(msg, "queue node info = %d", i);//消息赋值 13 | queue->insert_tail(queue, msg); //往尾部插入元素 14 | } 15 | 16 | //2.遍历队列中的元素 17 | printf("遍历队列中所有元素:\n"); 18 | foreach_lite_queue(queue, msg){ 19 | printf("%s\n", msg); 20 | } 21 | 22 | //3.取数据 23 | printf("从队列头取元素:\n"); 24 | for(int i=0; i<5; ++i){ 25 | msg = queue->front(queue); 26 | if(!msg) continue; 27 | printf("%s\n", msg); 28 | free(msg); 29 | } 30 | 31 | //4.状态 32 | printf("状态: %s\n", queue->empty(queue)==1 ? "空" : "非空"); 33 | } 34 | 35 | void stack_test(void) //先进后出 36 | { 37 | LiteQueue* stack = create_lite_queue(100, 32); 38 | char *msg=NULL; 39 | 40 | //1.栈插入元素 41 | for(int i=0; i<5; ++i) 42 | { 43 | msg = (char*)malloc(32); 44 | sprintf(msg, "stack node info = %d", i); 45 | stack->insert_head(stack, msg); 46 | } 47 | 48 | //2.遍历栈中的元素 49 | printf("遍历栈中所有元素:\n"); 50 | foreach_lite_queue(stack, msg){ 51 | printf("%s\n", msg); 52 | } 53 | 54 | //3.取数据 55 | printf("栈顶取元素:\n"); 56 | for(int i=0; i<5; ++i){ 57 | msg = stack->front(stack); 58 | if(!msg) continue; 59 | printf("%s\n", msg); 60 | free(msg); 61 | } 62 | 63 | //4.状态 64 | printf("状态: %s\n", stack->empty(stack)==1 ? "空" : "非空"); 65 | } 66 | 67 | int main(void) 68 | { 69 | queue_test(); 70 | 71 | printf("\n"); 72 | 73 | stack_test(); 74 | 75 | return 0; 76 | } -------------------------------------------------------------------------------- /ringbuffer/readme.md: -------------------------------------------------------------------------------- 1 | # 循环buffer 2 | 提供两个版本的循环buffer,一个是读取数据时候拷贝的,另外一个是读取数据返回指针免拷贝的。 3 | 4 | ## ringbuffer_copy 5 | 这个目录下的代码是拷贝读取数据的。 6 | 7 | ## ringbuffer_no_copy 8 | 这个目录下的是免拷贝读取数据的。 9 | 10 | ## testfile 11 | 这个目录是生成测试文件数据的代码。 -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_copy/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | LDFLAGS := -ldl -lpthread 3 | CFLAGS := -Wall -g 4 | TARGET := mainApp 5 | 6 | OBJS = $(patsubst %.c, %.o, $(wildcard *.c)) 7 | 8 | $(TARGET):$(OBJS) 9 | $(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS) 10 | $(MAKE) clean 11 | 12 | %.o:%.cpp 13 | $(CC) -c $(CFLAGS) $< -o $@ 14 | 15 | .PHONY:clean cleanall 16 | cleanall:clean 17 | @rm $(TARGET) 18 | clean: 19 | @rm ./*.o 20 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_copy/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/3/1 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | 8 | #include 9 | #include "ringbuffer.h" 10 | #include 11 | #include 12 | #include 13 | 14 | #define ENABLE_WRITE_OUT_FILE 0 15 | 16 | static volatile int is_runing = 0; 17 | 18 | long get_sys_time(void) //获取系统时间 19 | { 20 | struct timeval tm; 21 | gettimeofday(&tm, NULL); 22 | return tm.tv_sec*1000000+tm.tv_usec; 23 | } 24 | 25 | void* write_data_task(void* args) //线程1 往循环buffer中写数据 26 | { 27 | FILE *fp = fopen("../ringbuffer_cpp/testfile/src.dat", "rb"); 28 | if(!fp){ 29 | printf("open src.dat error!\n"); 30 | is_runing=0; 31 | return NULL; 32 | } 33 | uint8_t buf[1024]={0}; 34 | ringbuffer_t *rb = (ringbuffer_t*)args; //获取传入进来的循环buffer参数 35 | int ret = -1; 36 | int data_len = 0; 37 | 38 | while(!feof(fp)) 39 | { 40 | 41 | data_len = 512+rand()%512; //获取随机长度写入循环buffer 42 | fread(buf, data_len, 1, fp); //根据长度从文件中读出原始数据写入循环buffer 43 | do{ 44 | ret = rb->write(rb, buf, data_len); //往循环buffer中写数据 45 | }while(ret == -1); //阻塞等待写入成功 46 | } 47 | is_runing=0; 48 | 49 | fclose(fp); 50 | return NULL; 51 | } 52 | 53 | void* read_data_task(void* args) 54 | { 55 | #if ENABLE_WRITE_OUT_FILE 56 | FILE *fp = fopen("./data/out.dat", "wb"); 57 | 58 | if(!fp){ 59 | printf("Open out.dat error! \n"); 60 | is_runing=0; 61 | return NULL; 62 | } 63 | #endif 64 | int ret = -1; 65 | ringbuffer_t *rb = (ringbuffer_t*)args; //获取传入进来的循环buffer参数 66 | uint8_t buf[1024]={0}; 67 | 68 | long start_time = get_sys_time(); //获取系统时间 69 | int data_len=0; 70 | while (is_runing) 71 | { 72 | data_len = 512+rand()%512; //获取随机长度从循环buffer中读取数据 73 | do{ 74 | ret = rb->read(rb, buf, data_len); //从循环buffer中读数据 75 | }while(ret==-1); //阻塞等待读取数据成功 76 | #if ENABLE_WRITE_OUT_FILE 77 | fwrite(buf, data_len, 1, fp); //将从循环buffer中读取的数据写入文件 78 | #endif 79 | } 80 | long end_time = get_sys_time(); //获取系统时间 81 | int use_time = end_time-start_time; 82 | double use_s = ((double)use_time/1000000.0); 83 | double rate = ((500*1024*1024*8.0)/use_s)/(1024*1024*1024.0); 84 | printf("500M Data Use time=%dus(%.2lfS) rate=%.2lfGbps\n", use_time, use_s, rate); 85 | 86 | #if ENABLE_WRITE_OUT_FILE 87 | fclose(fp); 88 | #endif 89 | return NULL; 90 | } 91 | 92 | int main(int argc, char** argv) 93 | { 94 | pthread_t th[2]={0}; 95 | ringbuffer_t* rb = creat_ringbuffer(16*1024); //创建循环buffer 96 | 97 | srand(time(NULL)); //初始化随机数 98 | is_runing = 1; 99 | 100 | pthread_create(&th[0], NULL, write_data_task, rb); //创建线程写数据 101 | pthread_create(&th[1], NULL, read_data_task, rb); //创建线程读数据 102 | 103 | pthread_join(th[0], NULL); //阻塞等待线程执行完毕 104 | pthread_join(th[1], NULL); //创建线程写数据 105 | 106 | printf("Finish Test Ringbuffer...\n"); 107 | 108 | destory_ringbuffer(rb); //销毁循环buffer 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_copy/ringbuffer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/3/1 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | #include "ringbuffer.h" 8 | 9 | #define smp_mb() __asm__ __volatile__ ("" : : : "memory") //内存屏障 10 | #define MIN(x, y) ((x)<(y) ? (x) : (y)) 11 | 12 | /** 13 | * @brief:从循环buffer中读取数据 14 | * @rb: 输入的循环buffer结构体 15 | * @buffer:存储读取到的数据buffer 16 | * @len:要读取的长度 17 | * @return: -1:失败 其他:读取到的长度 18 | */ 19 | int read_ringbuffer (ringbuffer_t *rb, uint8_t *buffer, int len) 20 | { 21 | int left_len = 0; 22 | int buf_size = rb->buffer_size; 23 | int wpos = rb->wpos; 24 | int rpos = rb->rpos; 25 | int available_len = ((wpos-rpos)+buf_size)&(buf_size-1); 26 | 27 | if(available_len <= len) return -1; 28 | 29 | left_len = MIN(len, buf_size-rpos); 30 | memcpy(buffer, rb->buffer+rpos, left_len); 31 | memcpy(buffer+left_len, rb->buffer, len-left_len); 32 | 33 | smp_mb(); 34 | 35 | rb->rpos += len; 36 | rb->rpos &= (buf_size-1); 37 | 38 | return len; 39 | } 40 | 41 | /** 42 | * @brief:向循环buffer中写入数据 43 | * @rb: 输入的循环buffer结构体 44 | * @buffer:写入循环buffer的数据 45 | * @len:要写入的长度 46 | * @return: -1:失败 其他:写入的长度 47 | */ 48 | int write_ringbuffer (ringbuffer_t *rb, uint8_t *buffer, int len) 49 | { 50 | int left_len = 0; 51 | volatile int buf_size = rb->buffer_size; 52 | int wpos = rb->wpos; 53 | int rpos = rb->rpos; 54 | int available_len = ((rpos-wpos)+buf_size)&(buf_size-1); 55 | 56 | if(available_len <= len){ 57 | if(!rb->is_init){ 58 | rb->is_init = 1; 59 | goto run; 60 | } 61 | return -1; 62 | } 63 | 64 | run: 65 | left_len = MIN(len, buf_size-wpos); 66 | memcpy(rb->buffer+wpos, buffer, left_len); 67 | memcpy(rb->buffer, buffer+left_len, len-left_len); 68 | 69 | smp_mb(); 70 | 71 | rb->wpos += len; 72 | rb->wpos &= (buf_size-1); 73 | 74 | return len; 75 | } 76 | 77 | #undef smp_mb 78 | #undef MIN 79 | 80 | /** 81 | * @brief:创建一个循环buffer 82 | * @buf_size:循环buffer的空间大小 83 | * @return: NULL:失败 84 | */ 85 | ringbuffer_t* creat_ringbuffer(int buf_size) 86 | { 87 | if(buf_size <= 0) return NULL; 88 | 89 | ringbuffer_t* rb = (ringbuffer_t*)malloc(sizeof(ringbuffer_t)); 90 | if(!rb){ 91 | perror("error!"); 92 | return NULL; 93 | } 94 | 95 | rb->buffer_size = 1; 96 | do{ 97 | buf_size /= 2; 98 | rb->buffer_size *= 2; 99 | }while(buf_size); 100 | printf("Round up buffer size=%d\n", rb->buffer_size); 101 | 102 | rb->buffer = (uint8_t*)malloc(rb->buffer_size); 103 | if(!rb->buffer){ 104 | perror("error!"); 105 | free(rb); 106 | return NULL; 107 | } 108 | 109 | rb->is_init = 0; 110 | rb->rpos = rb->wpos = 0; 111 | rb->read = read_ringbuffer; 112 | rb->write = write_ringbuffer; 113 | 114 | return rb; 115 | } 116 | 117 | /** 118 | * @brief:销毁循环buffer 119 | * @rb: 要销毁的循环buffer结构体 120 | */ 121 | int destory_ringbuffer(ringbuffer_t* rb) 122 | { 123 | if(rb){ 124 | if(rb->buffer) free(rb->buffer); 125 | free(rb); 126 | } 127 | rb=NULL; 128 | 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_copy/ringbuffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/3/1 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | #ifndef __RINGBUFFER_H__ 8 | #define __RINGBUFFER_H__ 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | //循环buffer结构体 17 | typedef struct ringbuffer_t 18 | { 19 | int (*read)(struct ringbuffer_t *rb, uint8_t *buffer, int len); //读数据函数指针 20 | int (*write)(struct ringbuffer_t *rb, uint8_t *buffer, int len); //写数据函数指针 21 | uint8_t *buffer; //缓冲区 22 | int buffer_size; //缓冲区大小 23 | uint8_t is_init; //是否初始化 24 | volatile int rpos; //读指针 25 | volatile int wpos; //写指针 26 | }ringbuffer_t; 27 | 28 | ringbuffer_t* creat_ringbuffer(int buf_size); //创建一个结构体 29 | int destory_ringbuffer(ringbuffer_t* rb); //销毁申请的缓冲区 30 | 31 | 32 | #endif // ! __RINGBUFFER_H__ -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_muti/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | LDFLAGS := -ldl -lpthread 3 | CFLAGS := -Wall -g 4 | TARGET := mainApp 5 | 6 | OBJS = $(patsubst %.c, %.o, $(wildcard *.c)) 7 | 8 | $(TARGET):$(OBJS) 9 | $(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS) 10 | $(MAKE) clean 11 | 12 | %.o:%.cpp 13 | $(CC) -c $(CFLAGS) $< -o $@ 14 | 15 | .PHONY:clean cleanall 16 | cleanall: 17 | @rm $(TARGET) 18 | clean: 19 | @rm ./*.o 20 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_muti/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/9/14 修改:2024/4/25 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "ringbuffer_muti.h" 13 | 14 | volatile int is_runing=0; 15 | 16 | m_ringbuffer_t *g_rb; 17 | 18 | #define ENABLE_WRITE_OUT_FILE 0 //读取数据是否写文件 19 | 20 | long get_sys_time(void) //获取系统时间 21 | { 22 | struct timeval tm; 23 | gettimeofday(&tm, NULL); 24 | return tm.tv_sec*1000000+tm.tv_usec; 25 | } 26 | 27 | void* write_data_task(void* args) //线程1 往循环buffer中写数据 28 | { 29 | FILE *fp = fopen("../src.dat", "rb"); 30 | if(!fp){ 31 | printf("open src.dat error!\n"); 32 | is_runing=0; 33 | return NULL; 34 | } 35 | uint8_t buf[1024]={0}; 36 | m_ringbuffer_t *rb = (m_ringbuffer_t*)args; //获取传入进来的循环buffer参数 37 | int ret = -1; 38 | int data_len = 0; 39 | 40 | while(!feof(fp)) 41 | { 42 | data_len = 512+rand()%512; //获取随机长度写入循环buffer 43 | fread(buf, data_len, 1, fp); //根据长度从文件中读出原始数据写入循环buffer 44 | do{ 45 | ret = rb->write(rb, buf, data_len); //往循环buffer中写数据 46 | }while(ret != 0); //阻塞等待写入成功 47 | } 48 | is_runing=0; 49 | 50 | fclose(fp); 51 | return NULL; 52 | } 53 | 54 | 55 | void* read_data_task(void* args) 56 | { 57 | int read_id = *(int*)args; 58 | 59 | #if ENABLE_WRITE_OUT_FILE 60 | char filename[64]={0}; 61 | sprintf(filename, "out_%d.dat", read_id); 62 | FILE *fp = fopen(filename, "wb"); 63 | 64 | if(!fp){ 65 | printf("Open out.dat error! \n"); 66 | is_runing=0; 67 | return NULL; 68 | } 69 | #endif 70 | 71 | m_ringbuffer_t *rb = g_rb; //获取传入进来的循环buffer参数 72 | uint8_t *buf=NULL; 73 | int ret_len=0; 74 | 75 | long start_time = get_sys_time(); //获取系统时间 76 | int data_len=0; 77 | while (is_runing) 78 | { 79 | data_len = 512+rand()%512; //获取随机长度从循环buffer中读取数据 80 | do{ 81 | ret_len = rb->read(rb, read_id, &buf, data_len); //从循环buffer中读数据 82 | }while(ret_len<0 && is_runing); //阻塞等待读取数据成功 83 | #if ENABLE_WRITE_OUT_FILE 84 | fwrite(buf, ret_len, 1, fp); //将从循环buffer中读取的数据写入文件 85 | #endif 86 | } 87 | long end_time = get_sys_time(); //获取系统时间 88 | int use_time = end_time-start_time; 89 | double use_s = ((double)use_time/1000000.0); 90 | double rate = ((500*1024*1024*8.0)/use_s)/(1024*1024*1024.0); 91 | printf("500M Data Use time=%dus(%.2lfS) rate=%.2lfGbps\n", use_time, use_s, rate); 92 | 93 | #if ENABLE_WRITE_OUT_FILE 94 | fclose(fp); 95 | #endif 96 | return NULL; 97 | } 98 | 99 | int main(void) 100 | { 101 | int i, a_id[64]; 102 | pthread_t wth, th[64]; 103 | const int test_read_cnt = 2; 104 | m_ringbuffer_t* rb = create_muti_ringbuffer(50*1024); 105 | g_rb = rb; 106 | 107 | 108 | srand(time(NULL)); //初始化随机数 109 | is_runing = 1; 110 | 111 | pthread_create(&wth, NULL, write_data_task, rb); 112 | 113 | for(i=0; iadd(rb); 115 | } 116 | 117 | for(i=0; i /* memcpy memset */ 9 | #include /* malloc free */ 10 | #include "ringbuffer_muti.h" 11 | 12 | #define _max(x, y) ( x>y ? x : y ) 13 | #define _min(x, y) ( xw_pos; 23 | 24 | right_len = mrb->rb_size - wpos; 25 | right_len = _min(right_len, len); 26 | memcpy(mrb->rb_buffer+wpos, buffer, right_len); 27 | memcpy(mrb->rb_buffer, buffer+right_len, len-right_len); 28 | 29 | /* 更新写指针位置 */ 30 | mrb->w_pos = (mrb->w_pos+len)&mrb->rb_size_mask; 31 | 32 | return 0; 33 | } 34 | 35 | /** 36 | * @brief 向循环buffer空间写入数据 37 | * @param pthis 循环buffer句柄 38 | * @param buffer 要写入的数据 39 | * @param len 要写入数据的长度 40 | * @return -1:参数错误 -2:可写空间不够 0:写入成功 41 | */ 42 | int mrb_write(void* pthis, const uint8_t* buffer, int len) 43 | { 44 | int i, n, wpos, rpos, free_len; 45 | m_ringbuffer_t* mrb = (m_ringbuffer_t*)pthis; 46 | 47 | if( unlikely(!pthis || !buffer || len<1) ) return -1; 48 | n = mrb->read_cnt; 49 | wpos = mrb->w_pos; 50 | 51 | for(i=0; iarr_pos[i]->r_pos; 53 | free_len = (rpos-wpos+mrb->rb_size)&mrb->rb_size_mask; 54 | if( unlikely(free_len <= len && rpos!=wpos) ){ /* 可写空间不够 */ 55 | ++(mrb->rb_overflow_cnt); 56 | return -2; 57 | } 58 | } 59 | 60 | return __write_data(pthis, buffer, len); 61 | } 62 | 63 | 64 | 65 | /** 66 | * @brief 从循环buffer空间读取数据 67 | * @param pthis 循环buffer句柄 68 | * @param readid 读者的id,区分读者 69 | * @param buffer 要的数据指针的地址 70 | * @param len 要读取数据的长度 71 | * @return -1:参数错误 -2:可读空间不够 len:读取的数据长度 72 | */ 73 | static int mrb_read(void* pthis, int readid, uint8_t **buffer, int len) 74 | { 75 | int free_len, right_len, rpos, last_len, wpos; 76 | m_ringbuffer_t* mrb = (m_ringbuffer_t*)pthis; 77 | 78 | if( unlikely(readid<0 || readid>mrb->read_cnt) ) return -1; 79 | if( unlikely(!pthis || !buffer || len<1) ) return -1; 80 | 81 | wpos = mrb->w_pos; 82 | rpos = mrb->arr_pos[readid]->r_pos; 83 | last_len = mrb->arr_pos[readid]->r_last_len; 84 | 85 | rpos = (rpos + last_len)&mrb->rb_size_mask; 86 | free_len = (wpos - rpos + mrb->rb_size)&mrb->rb_size_mask; 87 | 88 | if( unlikely(free_len < len) ) return -2; 89 | 90 | mrb->arr_pos[readid]->r_pos = rpos;/* 更新上次的读指针 */ 91 | 92 | right_len = mrb->rb_size - rpos; 93 | right_len = _min(right_len, len); 94 | 95 | *buffer = (mrb->rb_buffer + rpos); 96 | 97 | mrb->arr_pos[readid]->r_last_len = right_len; /* 记录本次读写的长度 */ 98 | 99 | return right_len; 100 | } 101 | 102 | /** 103 | * @brief 向循环buffer添加读者 104 | * @param pthis 循环buffer句柄 105 | * @return -1:添加失败 id:读者ID 106 | */ 107 | static int mrb_add(void* pthis) 108 | { 109 | int index; 110 | m_ringbuffer_t* mrb = (m_ringbuffer_t*)pthis; 111 | if(!pthis) return -1; 112 | index = mrb->read_cnt; 113 | mrb->arr_pos[index] = (struct readpos_t*)malloc(sizeof(struct readpos_t)); 114 | if(!mrb->arr_pos[index]) return -1; 115 | 116 | mrb->arr_pos[index]->r_pos = 0; 117 | mrb->arr_pos[index]->r_last_len = 0; 118 | ++mrb->read_cnt; 119 | 120 | return index; 121 | } 122 | 123 | /** 124 | * @brief 处理数的值为2的次幂 125 | * @param num 数组的数字 126 | * @return 返回最接近num的2的次幂数 127 | */ 128 | int _pow_num(int num) 129 | { 130 | int cnt=0, retn=1; 131 | 132 | while(num){ 133 | num>>=1; 134 | ++cnt; 135 | } 136 | 137 | cnt = cnt>31 ? 31 : cnt; 138 | 139 | while(cnt--) retn *= 2; 140 | 141 | return retn; 142 | } 143 | 144 | /** 145 | * @brief 创建一个循环buffer句柄 146 | * @param buf_size缓冲区大小 147 | * @return 循环buffer句柄 148 | */ 149 | m_ringbuffer_t* create_muti_ringbuffer(int buf_size) 150 | { 151 | m_ringbuffer_t* mrb; 152 | 153 | if(buf_size<1) return NULL; 154 | 155 | mrb = (m_ringbuffer_t*)malloc(sizeof(m_ringbuffer_t)); 156 | if(!mrb) return NULL; 157 | 158 | memset(mrb, 0, sizeof(m_ringbuffer_t)); 159 | mrb->rb_size = _pow_num(buf_size); 160 | mrb->rb_size_mask = mrb->rb_size - 1; 161 | mrb->rb_buffer = (uint8_t*)malloc( mrb->rb_size ); 162 | if(!mrb->rb_buffer){ 163 | free(mrb); 164 | return NULL; 165 | } 166 | mrb->add = mrb_add; 167 | mrb->read = mrb_read; 168 | mrb->write = mrb_write; 169 | 170 | return mrb; 171 | } 172 | 173 | /** 174 | * @brief 销毁循环buffer 175 | * @param srb循环buffer句柄 176 | * @return -1:err 0:ok 177 | */ 178 | int destory_muti_ringbuffer(m_ringbuffer_t* mrb) 179 | { 180 | int i=0; 181 | 182 | if(!mrb) return -1; 183 | if(mrb->rb_buffer) free(mrb->rb_buffer); 184 | for(i=0; iread_cnt; ++i){ 185 | free(mrb->arr_pos[i]); 186 | } 187 | free(mrb); 188 | return 0; 189 | } -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_muti/ringbuffer_muti.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2024/4/25 4 | * 作者:(c)小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | 8 | #ifndef __RINGBUFFER_MUTI_H___ 9 | #define __RINGBUFFER_MUTI_H___ 10 | 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #define MAX_READ_NUM (64) /* 最大读者数 */ 18 | 19 | struct readpos_t 20 | { 21 | int r_pos; 22 | int r_last_len; 23 | }; 24 | 25 | typedef struct m_ringbuffer 26 | { 27 | struct readpos_t *arr_pos[MAX_READ_NUM];/* 读者信息数组 */ 28 | volatile int w_pos; /* 写入数据指针位置 */ 29 | int read_cnt; /* 读者数量 */ 30 | int rb_overflow_cnt; /* 记录缓冲区溢出的次数 */ 31 | int rb_size, rb_size_mask; /* 缓冲区空间大小 */ 32 | uint8_t* rb_buffer; /* 缓存数据空间 */ 33 | int (*add)(void* pthis); /* 向循环buffer添加一个读者 */ 34 | int (*write)(void* pthis, const uint8_t* buffer, int len); /* 写数据函数 */ 35 | int (*read)(void* pthis, int readid, uint8_t **buffer, int len); /* 读数据函数 */ 36 | }m_ringbuffer_t; 37 | 38 | 39 | /** 40 | * @brief 创建一个循环buffer句柄 41 | * @param buf_size缓冲区大小 42 | * @return 循环buffer句柄 43 | */ 44 | m_ringbuffer_t* create_muti_ringbuffer(int buf_size); 45 | 46 | /** 47 | * @brief 销毁循环buffer 48 | * @param srb循环buffer句柄 49 | * @return -1:err 0:ok 50 | */ 51 | int destory_muti_ringbuffer(m_ringbuffer_t* mrb); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif // !__RINGBUFFER_SINGLE_H___ 58 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_no_copy/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | LDFLAGS := -ldl -lpthread 3 | CFLAGS := -Wall -g 4 | TARGET := mainApp 5 | 6 | OBJS = $(patsubst %.c, %.o, $(wildcard *.c)) 7 | 8 | $(TARGET):$(OBJS) 9 | $(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS) 10 | $(MAKE) clean 11 | 12 | %.o:%.cpp 13 | $(CC) -c $(CFLAGS) $< -o $@ 14 | 15 | .PHONY:clean cleanall 16 | cleanall:clean 17 | @rm $(TARGET) 18 | clean: 19 | @rm ./*.o 20 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_no_copy/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/9/14 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "ringbuffer.h" 12 | 13 | volatile int is_runing=0; 14 | 15 | #define ENABLE_WRITE_OUT_FILE 1 //读取数据是否写文件 16 | 17 | long get_sys_time(void) //获取系统时间 18 | { 19 | struct timeval tm; 20 | gettimeofday(&tm, NULL); 21 | return tm.tv_sec*1000000+tm.tv_usec; 22 | } 23 | 24 | void* write_data_task(void* args) //线程1 往循环buffer中写数据 25 | { 26 | FILE *fp = fopen("../src.dat", "rb"); 27 | if(!fp){ 28 | printf("open src.dat error!\n"); 29 | is_runing=0; 30 | return NULL; 31 | } 32 | uint8_t buf[1024]={0}; 33 | ringbuffer_t *rb = (ringbuffer_t*)args; //获取传入进来的循环buffer参数 34 | int ret = -1; 35 | int data_len = 0; 36 | 37 | while(!feof(fp)) 38 | { 39 | 40 | data_len = 512+rand()%512; //获取随机长度写入循环buffer 41 | fread(buf, data_len, 1, fp); //根据长度从文件中读出原始数据写入循环buffer 42 | do{ 43 | ret = rb->rb_write(rb, buf, data_len); //往循环buffer中写数据 44 | }while(ret == -1); //阻塞等待写入成功 45 | } 46 | is_runing=0; 47 | 48 | fclose(fp); 49 | return NULL; 50 | } 51 | 52 | 53 | void* read_data_task(void* args) 54 | { 55 | #if ENABLE_WRITE_OUT_FILE 56 | FILE *fp = fopen("./data/out.dat", "wb"); 57 | 58 | if(!fp){ 59 | printf("Open out.dat error! \n"); 60 | is_runing=0; 61 | return NULL; 62 | } 63 | #endif 64 | 65 | ringbuffer_t *rb = (ringbuffer_t*)args; //获取传入进来的循环buffer参数 66 | uint8_t *buf=NULL; 67 | 68 | long start_time = get_sys_time(); //获取系统时间 69 | int data_len=0; 70 | while (is_runing) 71 | { 72 | data_len = 512+rand()%512; //获取随机长度从循环buffer中读取数据 73 | do{ 74 | buf = rb->rb_read(rb, data_len); //从循环buffer中读数据 75 | }while(buf==NULL); //阻塞等待读取数据成功 76 | #if ENABLE_WRITE_OUT_FILE 77 | fwrite(buf, data_len, 1, fp); //将从循环buffer中读取的数据写入文件 78 | #endif 79 | rb->rb_refreash(rb, data_len); //刷新指针 80 | } 81 | long end_time = get_sys_time(); //获取系统时间 82 | int use_time = end_time-start_time; 83 | double use_s = ((double)use_time/1000000.0); 84 | double rate = ((500*1024*1024*8.0)/use_s)/(1024*1024*1024.0); 85 | printf("500M Data Use time=%dus(%.2lfS) rate=%.2lfGbps\n", use_time, use_s, rate); 86 | 87 | #if ENABLE_WRITE_OUT_FILE 88 | fclose(fp); 89 | #endif 90 | return NULL; 91 | } 92 | 93 | int main(void) 94 | { 95 | pthread_t th[2]; 96 | ringbuffer_t* rb = create_ringbuffer(50*1024, 2048); 97 | 98 | srand(time(NULL)); //初始化随机数 99 | is_runing = 1; 100 | 101 | pthread_create(&th[0], NULL, write_data_task, rb); 102 | pthread_create(&th[1], NULL, read_data_task, rb); 103 | 104 | pthread_join(th[0], NULL); 105 | pthread_join(th[1], NULL); 106 | 107 | printf("Finish Test Ringbuffer...\n"); 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_no_copy/ringbuffer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/9/14 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | #include "ringbuffer.h" 8 | 9 | #define _min(x, y) ((x) < (y)) ? (x) : (y) 10 | 11 | #define smp_mb() __asm__ __volatile__ ("" : : : "memory") //内存屏障 12 | 13 | static int ringbuffer_write(struct ringbuffer_t *rb, uint8_t *buffer, int len) 14 | { 15 | int space_len=0, left_len=0; 16 | 17 | if(!rb || !buffer || len>rb->reserve_size) return -1; 18 | 19 | space_len = ((rb->rpos - rb->wpos)+rb->buffer_size)%rb->buffer_size; //计算长度 20 | if(rb->rpos==rb->wpos) space_len=rb->buffer_size; 21 | if(space_len <= len) return -1; //避免读写指针相遇 22 | 23 | left_len = rb->buffer_size - rb->wpos; //右边的长度 24 | 25 | left_len = _min(len, left_len); //求出最小值 26 | 27 | memcpy(rb->buffer+rb->wpos, buffer, left_len); //若是最小值等于len则不执行下面的拷贝 28 | memcpy(rb->buffer, buffer+left_len, len-left_len);//过边界拷贝,将剩下的拷贝到最前面 29 | 30 | smp_mb(); 31 | 32 | rb->wpos = (rb->wpos+len)%rb->buffer_size;//取余 33 | 34 | return len; 35 | } 36 | 37 | static uint8_t* ringbuffer_read(struct ringbuffer_t *rb, int len) 38 | { 39 | int space_len=0, left_len=0; 40 | 41 | if(!rb || len>rb->reserve_size) return NULL; 42 | space_len = ((rb->wpos - rb->rpos)+rb->buffer_size)%rb->buffer_size; //求出当前可读取的空间长度 43 | if(space_len <= len) return NULL; //判断加上等于条件为了避免读写指针相遇 44 | 45 | left_len = rb->buffer_size - rb->rpos;//求出右边可读长度 46 | 47 | if(left_lenbuffer-left_len, rb->buffer+rb->rpos, left_len); 49 | return rb->buffer-left_len; 50 | } 51 | 52 | return rb->buffer + rb->rpos; 53 | } 54 | 55 | static void ringbuffer_refreash(struct ringbuffer_t *rb, int len) 56 | { 57 | if(!rb || len>rb->reserve_size) return; 58 | rb->rpos = (rb->rpos+len)%rb->buffer_size; //刷新指针位置 59 | } 60 | 61 | static void ringbuffer_free(struct ringbuffer_t *rb) 62 | { 63 | uint8_t* buffer=NULL; 64 | 65 | if(!rb) return; 66 | buffer = rb->buffer-rb->reserve_size; //将指针偏移空间起始地址 67 | free(buffer); 68 | free(rb); 69 | } 70 | 71 | ringbuffer_t* create_ringbuffer(int size, int reserve_size) 72 | { 73 | ringbuffer_t* rb=NULL; 74 | uint8_t* allbuffer=NULL; 75 | 76 | if(size < 0 || reserve_size<0) return NULL; 77 | rb = (ringbuffer_t*)malloc(sizeof(ringbuffer_t)); 78 | allbuffer = (uint8_t*)malloc(size+reserve_size); 79 | rb->buffer = allbuffer+reserve_size; //偏移预留大小 80 | rb->buffer_size = size; 81 | rb->reserve_size = reserve_size; 82 | rb->rpos = 0; 83 | rb->wpos = 0; 84 | rb->rb_write = ringbuffer_write; 85 | rb->rb_read = ringbuffer_read; 86 | rb->rb_refreash = ringbuffer_refreash; 87 | rb->rb_free = ringbuffer_free; 88 | 89 | return rb; 90 | } -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_no_copy/ringbuffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/9/14 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | #ifndef __RINGBUFFER_H__ 8 | #define __RINGBUFFER_H__ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | //循环buffer结构体 16 | typedef struct ringbuffer_t 17 | { 18 | uint8_t *buffer; //缓冲区 19 | int buffer_size; //缓冲区大小 20 | int reserve_size; //预留空间大小 21 | volatile int rpos; //读指针 22 | volatile int wpos; //写指针 23 | int (*rb_write)(struct ringbuffer_t *rb, uint8_t *buffer, int len);//写数据函数指针 24 | uint8_t* (*rb_read)(struct ringbuffer_t *rb, int len); //读数据函数指针 25 | void (*rb_refreash)(struct ringbuffer_t *rb, int len); //刷新读指针位置 26 | void (*rb_free)(struct ringbuffer_t *rb); //释放内存 27 | }ringbuffer_t; 28 | 29 | ringbuffer_t* create_ringbuffer(int size, int reserve_size); 30 | 31 | #endif // !__RINGBUFFER_H__ 32 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_single/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | LDFLAGS := -ldl -lpthread 3 | CFLAGS := -Wall -g 4 | TARGET := mainApp 5 | 6 | OBJS = $(patsubst %.c, %.o, $(wildcard *.c)) 7 | 8 | $(TARGET):$(OBJS) 9 | $(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS) 10 | $(MAKE) clean 11 | 12 | %.o:%.cpp 13 | $(CC) -c $(CFLAGS) $< -o $@ 14 | 15 | .PHONY:clean cleanall 16 | cleanall: 17 | @rm $(TARGET) 18 | clean: 19 | @rm ./*.o 20 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_single/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2023/9/14 修改:2024/4/25 4 | * 作者:小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "ringbuffer_single.h" 13 | 14 | volatile int is_runing=0; 15 | 16 | #define ENABLE_WRITE_OUT_FILE 1 //读取数据是否写文件 17 | 18 | long get_sys_time(void) //获取系统时间 19 | { 20 | struct timeval tm; 21 | gettimeofday(&tm, NULL); 22 | return tm.tv_sec*1000000+tm.tv_usec; 23 | } 24 | 25 | void* write_data_task(void* args) //线程1 往循环buffer中写数据 26 | { 27 | FILE *fp = fopen("../src.dat", "rb"); 28 | if(!fp){ 29 | printf("open src.dat error!\n"); 30 | is_runing=0; 31 | return NULL; 32 | } 33 | uint8_t buf[1024]={0}; 34 | s_ringbuffer_t *rb = (s_ringbuffer_t*)args; //获取传入进来的循环buffer参数 35 | int ret = -1; 36 | int data_len = 0; 37 | 38 | while(!feof(fp)) 39 | { 40 | data_len = 512+rand()%512; //获取随机长度写入循环buffer 41 | fread(buf, data_len, 1, fp); //根据长度从文件中读出原始数据写入循环buffer 42 | do{ 43 | ret = rb->write(rb, buf, data_len); //往循环buffer中写数据 44 | }while(ret != 0); //阻塞等待写入成功 45 | } 46 | is_runing=0; 47 | 48 | fclose(fp); 49 | return NULL; 50 | } 51 | 52 | 53 | void* read_data_task(void* args) 54 | { 55 | #if ENABLE_WRITE_OUT_FILE 56 | FILE *fp = fopen("out.dat", "wb"); 57 | 58 | if(!fp){ 59 | printf("Open out.dat error! \n"); 60 | is_runing=0; 61 | return NULL; 62 | } 63 | #endif 64 | 65 | s_ringbuffer_t *rb = (s_ringbuffer_t*)args; //获取传入进来的循环buffer参数 66 | uint8_t *buf=NULL; 67 | int ret_len=0; 68 | 69 | long start_time = get_sys_time(); //获取系统时间 70 | int data_len=0; 71 | while (is_runing) 72 | { 73 | data_len = 512+rand()%512; //获取随机长度从循环buffer中读取数据 74 | do{ 75 | ret_len = rb->read(rb, &buf, data_len); //从循环buffer中读数据 76 | }while(ret_len<0); //阻塞等待读取数据成功 77 | #if ENABLE_WRITE_OUT_FILE 78 | fwrite(buf, ret_len, 1, fp); //将从循环buffer中读取的数据写入文件 79 | #endif 80 | } 81 | long end_time = get_sys_time(); //获取系统时间 82 | int use_time = end_time-start_time; 83 | double use_s = ((double)use_time/1000000.0); 84 | double rate = ((500*1024*1024*8.0)/use_s)/(1024*1024*1024.0); 85 | printf("500M Data Use time=%dus(%.2lfS) rate=%.2lfGbps\n", use_time, use_s, rate); 86 | 87 | #if ENABLE_WRITE_OUT_FILE 88 | fclose(fp); 89 | #endif 90 | return NULL; 91 | } 92 | 93 | int main(void) 94 | { 95 | pthread_t th[2]; 96 | s_ringbuffer_t* rb = create_single_ringbuffer(50*1024); 97 | 98 | srand(time(NULL)); //初始化随机数 99 | is_runing = 1; 100 | 101 | pthread_create(&th[0], NULL, write_data_task, rb); 102 | pthread_create(&th[1], NULL, read_data_task, rb); 103 | 104 | pthread_join(th[0], NULL); 105 | pthread_join(th[1], NULL); 106 | 107 | destory_single_ringbuffer(rb); 108 | 109 | printf("Finish Test Ringbuffer...\n"); 110 | 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_single/ringbuffer_single.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2024/4/25 4 | * 作者:(c)小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | 8 | #include /* memcpy memset */ 9 | #include /* malloc free */ 10 | #include "ringbuffer_single.h" 11 | 12 | #define _max(x, y) ( x>y ? x : y ) 13 | #define _min(x, y) ( xr_pos, wpos=skb->w_pos; 33 | free_len = (rpos - wpos + skb->skb_size)&skb->skb_size_mask; 34 | 35 | if( unlikely(rpos==wpos && 0==free_len) ) free_len=skb->skb_size; 36 | 37 | if( unlikely(free_len <= len) ){ /* 空间不够,记录 */ 38 | ++skb->skb_overflow_cnt; 39 | return -2; 40 | } 41 | 42 | right_len = skb->skb_size - wpos; 43 | right_len = _min(right_len, len); 44 | memcpy(skb->srb_buffer+wpos, buffer, right_len); 45 | memcpy(skb->srb_buffer, buffer+right_len, len-right_len); 46 | 47 | /* 更新写指针位置 */ 48 | skb->w_pos = (skb->w_pos+len)&skb->skb_size_mask; 49 | 50 | return 0; 51 | } 52 | 53 | /** 54 | * @brief 从循环buffer空间读取数据 55 | * @param pthis 循环buffer句柄 56 | * @param buffer 要的数据指针的地址 57 | * @param len 要读取数据的长度 58 | * @return -1:参数错误 -2:可读空间不够 len:读取的数据长度 59 | */ 60 | static int skb_read(void* pthis, uint8_t **buffer, int len) 61 | { 62 | s_ringbuffer_t* skb = (s_ringbuffer_t*)pthis; 63 | int free_len, right_len, tmp_rpos, wpos; 64 | 65 | if( unlikely(!pthis || !buffer || len<1) ) return -1; 66 | 67 | wpos = skb->w_pos; 68 | tmp_rpos = (skb->r_pos + skb->r_lastlen)&skb->skb_size_mask; 69 | free_len = (wpos - tmp_rpos+ skb->skb_size)&skb->skb_size_mask; 70 | 71 | if( unlikely(free_len < len) ) return -2; 72 | 73 | skb->r_pos = tmp_rpos;/* 更新上次的读指针 */ 74 | 75 | right_len = skb->skb_size - tmp_rpos; 76 | right_len = _min(right_len, len); 77 | 78 | *buffer = (skb->srb_buffer + tmp_rpos); 79 | 80 | skb->r_lastlen = right_len; /* 记录本次读写的长度 */ 81 | 82 | return right_len; 83 | } 84 | 85 | /** 86 | * @brief 处理数的值为2的次幂 87 | * @param num 数组的数字 88 | * @return 返回最接近num的2的次幂数 89 | */ 90 | int _pow_num(int num) 91 | { 92 | int cnt=0, retn=1; 93 | 94 | while(num){ 95 | num>>=1; 96 | ++cnt; 97 | } 98 | 99 | cnt = cnt>31 ? 31 : cnt; 100 | 101 | while(cnt--) retn *= 2; 102 | 103 | return retn; 104 | } 105 | 106 | /** 107 | * @brief 创建一个循环buffer句柄 108 | * @param buf_size缓冲区大小 109 | * @return 循环buffer句柄 110 | */ 111 | s_ringbuffer_t* create_single_ringbuffer(int buf_size) 112 | { 113 | s_ringbuffer_t* skb; 114 | 115 | if(buf_size<1) return NULL; 116 | 117 | skb = (s_ringbuffer_t*)malloc(sizeof(s_ringbuffer_t)); 118 | if(!skb) return NULL; 119 | 120 | memset(skb, 0, sizeof(s_ringbuffer_t)); 121 | skb->skb_size = _pow_num(buf_size); 122 | skb->skb_size_mask = skb->skb_size - 1; 123 | skb->srb_buffer = (uint8_t*)malloc( skb->skb_size ); 124 | if(!skb->srb_buffer){ 125 | free(skb); 126 | return NULL; 127 | } 128 | skb->read = skb_read; 129 | skb->write = skb_write; 130 | 131 | return skb; 132 | } 133 | 134 | /** 135 | * @brief 销毁循环buffer 136 | * @param srb循环buffer句柄 137 | * @return -1:err 0:ok 138 | */ 139 | int destory_single_ringbuffer(s_ringbuffer_t* srb) 140 | { 141 | if(!srb) return -1; 142 | if(srb->srb_buffer) free(srb->srb_buffer); 143 | free(srb); 144 | return 0; 145 | } -------------------------------------------------------------------------------- /ringbuffer/ringbuffer_single/ringbuffer_single.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 简介:测试循环buffer 3 | * 时间:2024/4/25 4 | * 作者:(c)小C 5 | * Note: 欢迎关注微信公众号[Linux编程用C] 6 | */ 7 | 8 | #ifndef __RINGBUFFER_SINGLE_H___ 9 | #define __RINGBUFFER_SINGLE_H___ 10 | 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | typedef struct s_ringbuffer 18 | { 19 | volatile int w_pos; /* 写入数据指针位置 */ 20 | volatile int r_pos; /* 读取数据指针位置 */ 21 | volatile int r_lastlen; /* 记录上一次读取数据的长度 */ 22 | int skb_overflow_cnt; /* 记录缓冲区溢出的次数 */ 23 | int skb_size, skb_size_mask; /* 缓冲区空间大小 */ 24 | uint8_t* srb_buffer; /* 缓存数据空间 */ 25 | int (*write)(void* pthis, const uint8_t* buffer, int len); /* 写数据函数 */ 26 | int (*read)(void* pthis, uint8_t **buffer, int len); /* 读数据函数 */ 27 | }s_ringbuffer_t; 28 | 29 | 30 | /** 31 | * @brief 创建一个循环buffer句柄 32 | * @param buf_size缓冲区大小 33 | * @return 循环buffer句柄 34 | */ 35 | s_ringbuffer_t* create_single_ringbuffer(int buf_size); 36 | 37 | /** 38 | * @brief 销毁循环buffer 39 | * @param srb循环buffer句柄 40 | * @return -1:err 0:ok 41 | */ 42 | int destory_single_ringbuffer(s_ringbuffer_t* srb); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif // !__RINGBUFFER_SINGLE_H___ 49 | -------------------------------------------------------------------------------- /ringbuffer/testfile/generate_bin_file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int main(void) 10 | { 11 | uint8_t buffer[1024]={0}; 12 | srand(time(NULL)); 13 | ofstream wfile("./src.dat", ios::out|ios::binary|ios::trunc); 14 | 15 | int cnt=1024*500; //500M 16 | while(cnt--){ 17 | for(int i=0; i<1024; i++){ 18 | buffer[i]=rand()%256; 19 | } 20 | wfile.write((char*)buffer, sizeof(buffer)); 21 | } 22 | 23 | wfile.close(); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /slist/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "slist.h" 4 | 5 | typedef struct info_t 6 | { 7 | int age; 8 | char name[32]; 9 | }info_t; 10 | 11 | int main(void) 12 | { 13 | slist_t *node, *tmp, *prev, *head = slist_new_node(info_t); 14 | slist_get_elem(head, info_t)->age = -1; 15 | snprintf(slist_get_elem(head, info_t)->name, 32, "tom"); 16 | 17 | for(int i=0; i<10; ++i){ 18 | node = slist_new_node(info_t); 19 | 20 | slist_get_elem(node, info_t)->age = 10+i; 21 | snprintf(slist_get_elem(node, info_t)->name, 32, "tom%d", i); 22 | 23 | slist_insert_back(head, node); 24 | } 25 | 26 | printf("----------split-------------\n"); 27 | slist_foreach(head, node){ 28 | printf("name=%s age=%d\n", slist_get_elem(node, info_t)->name, slist_get_elem(node, info_t)->age); 29 | } 30 | 31 | printf("----------split-------------\n"); 32 | slist_foreach_safe(head, prev, node){ 33 | if(slist_get_elem(node, info_t)->age<15){ 34 | tmp = slist_erase_node(prev); 35 | 36 | free(tmp); 37 | tmp = NULL; 38 | 39 | slist_erase_reset(prev, node); 40 | } 41 | } 42 | 43 | printf("----------split-------------\n"); 44 | slist_foreach(head, node){ 45 | printf("name=%s age=%d\n", slist_get_elem(node, info_t)->name, slist_get_elem(node, info_t)->age); 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /slist/slist.h: -------------------------------------------------------------------------------- 1 | #ifndef __SLIST_H__ 2 | #define __SLIST_H__ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * @brief 实现C语言泛型单链表 9 | * @author young 【微信公众号: Linux编程用C】 10 | * @mail estyoung71@gmail.com 11 | */ 12 | 13 | 14 | /** 15 | * @brief 定义链表节点 16 | */ 17 | typedef struct slist_s 18 | { 19 | struct slist_s *next; 20 | }slist_t; 21 | 22 | /** 23 | * @brief 创建一个链表节点 24 | * @param _type 链表中元素的类型 25 | */ 26 | #define slist_new_node(_type) (slist_t*)malloc(sizeof(slist_t)+sizeof(_type)) 27 | 28 | /** 29 | * @brief 传入链表节点,获取节点的元素 30 | * @param _node 传入的链表节点指针 31 | * @param _type 链表元素的类型 32 | * @return 返回节点元素的指针 33 | */ 34 | #define slist_get_elem(_node, _type) ( (_type*)(((char*)_node)+sizeof(slist_t)) ) 35 | 36 | /** 37 | * @brief 在指定节点位置前插入一个节点 38 | * @param _pos 节点位置指针 39 | * @param _node 要插入的节点指针 40 | */ 41 | #define slist_insert_front(_pos, _node) ({ _node->next = _pos; _pos = _node; }) 42 | 43 | /** 44 | * @brief 在指定节点位置后插入一个节点 45 | * @param _pos 节点位置指针 46 | * @param _node 要插入的节点指针 47 | */ 48 | #define slist_insert_back(_pos, _node) ({ _node->next = _pos->next; _pos->next = _node; }) 49 | 50 | /** 51 | * @brief 删除链表节点 52 | * @param _prev 要删除的前一个节点 53 | */ 54 | #define slist_erase_node(_prev) ({ slist_t* tmp = _prev->next; _prev->next = tmp->next; tmp; }) 55 | 56 | /** 57 | * @brief 删除节点后重新复位 58 | * @param _prev 被删除节点前一个节点指针 59 | * @param _node 要删除节点的指针 60 | */ 61 | #define slist_erase_reset(_prev, _node) ({ _node = _prev; }) 62 | 63 | /** 64 | * @brief 遍历链表 65 | * @param head 链表头节点 66 | * @param node 当前节点指针 67 | */ 68 | #define slist_foreach(head, node) \ 69 | for(node=head; node; node=node->next) 70 | 71 | /** 72 | * @brief 遍历并删除节点 73 | * @param head 链表头节点 74 | * @param prev 保存节点的前一个节点 75 | * @param node 当前节点 76 | */ 77 | #define slist_foreach_safe(head, prev, node) \ 78 | for(prev=head, node=prev->next; node; prev=node, node=node->next) 79 | 80 | #endif /* end slist */ 81 | --------------------------------------------------------------------------------