1# 内核数据结构 2 3  内核中实现了常用的几种数据结构,这里是他们的api文档。 4 5-------------- 6## kfifo先进先出缓冲区 7 8  kfifo先进先出缓冲区定义于`common/kfifo.h`中。您可以使用它,创建指定大小的fifo缓冲区(最大大小为4GB) 9 10### kfifo_alloc 11 12`int kfifo_alloc(struct kfifo_t *fifo, uint32_t size, uint64_t reserved)` 13 14#### 描述 15 16  通过动态方式初始化kfifo缓冲队列。fifo缓冲区的buffer将由该函数进行申请。 17 18#### 参数 19 20**fifo** 21 22  kfifo队列结构体的指针 23 24**size** 25 26  缓冲区大小(单位:bytes) 27 28**reserved** 29 30  当前字段保留,请将其置为0 31 32#### 返回值 33 34  当返回值为0时,表示正常初始化成功,否则返回对应的errno 35 36### kfifo_init 37 38`void kfifo_init(struct kfifo_t *fifo, void *buffer, uint32_t size)` 39 40#### 描述 41 42  使用指定的缓冲区来初始化kfifo缓冲队列 43 44#### 参数 45 46**fifo** 47 48  kfifo队列结构体的指针 49 50**buffer** 51 52  缓冲区基地址指针 53 54**size** 55 56  缓冲区大小(单位:bytes) 57 58### kfifo_free_alloc 59 60`void kfifo_free_alloc(struct kfifo_t* fifo)` 61 62#### 描述 63 64  释放通过kfifo_alloc创建的fifo缓冲区. 请勿通过该函数释放其他方式创建的kfifo缓冲区。 65 66#### 参数 67 68**fifo** 69 70  kfifo队列结构体的指针 71 72### kfifo_in 73 74`uint32_t kfifo_in(struct kfifo_t *fifo, const void *from, uint32_t size)` 75 76#### 描述 77 78  向kfifo缓冲区推入指定大小的数据。当队列中空间不足时,则不推入数据。 79 80#### 参数 81 82**fifo** 83 84  kfifo队列结构体的指针 85 86**from** 87 88  源数据基地址指针 89 90**size** 91 92  数据大小(单位:bytes) 93 94#### 返回值 95 96  返回成功被推入的数据的大小。 97 98### kfifo_out 99 100`uint32_t kfifo_out(struct kfifo_t *fifo, void *to, uint32_t size)` 101 102#### 描述 103 104  从kfifo缓冲区取出数据,并从队列中删除数据。当队列中数据量不足时,则不取出。 105 106#### 参数 107 108**fifo** 109 110  kfifo队列结构体的指针 111 112**to** 113 114  目标缓冲区基地址指针 115 116**size** 117 118  数据大小(单位:bytes) 119 120#### 返回值 121 122  返回成功被取出的数据的大小。 123 124### kfifo_out_peek 125 126`uint32_t kfifo_out_peek(struct kfifo_t *fifo, void *to, uint32_t size)` 127 128#### 描述 129 130  从kfifo缓冲区取出数据,但是不从队列中删除数据。当队列中数据量不足时,则不取出。 131 132#### 参数 133 134**fifo** 135 136  kfifo队列结构体的指针 137 138**to** 139 140  目标缓冲区基地址指针 141 142**size** 143 144  数据大小(单位:bytes) 145 146#### 返回值 147 148  返回成功被取出的数据的大小。 149 150### kfifo_reset 151 152`kfifo_reset(fifo)` 153 154#### 描述 155 156  忽略kfifo队列中的所有内容,并把输入和输出偏移量都归零 157 158#### 参数 159 160**fifo** 161 162  kfifo队列结构体的指针 163 164### kfifo_reset_out 165 166`kfifo_reset_out(fifo)` 167 168#### 描述 169 170  忽略kfifo队列中的所有内容,并将输入偏移量赋值给输出偏移量 171 172#### 参数 173 174**fifo** 175 176  kfifo队列结构体的指针 177 178### kfifo_total_size 179 180`kfifo_total_size(fifo)` 181 182#### 描述 183 184  获取kfifo缓冲区的最大大小 185 186#### 参数 187 188**fifo** 189 190  kfifo队列结构体的指针 191 192#### 返回值 193 194  缓冲区最大大小 195 196### kfifo_size 197 198`kfifo_size(fifo)` 199 200#### 描述 201 202  获取kfifo缓冲区当前已使用的大小 203 204#### 参数 205 206**fifo** 207 208  kfifo队列结构体的指针 209 210#### 返回值 211 212  缓冲区当前已使用的大小 213 214### kfifo_empty 215 216`kfifo_empty(fifo)` 217 218#### 描述 219 220  判断kfifo缓冲区当前是否为空 221 222#### 参数 223 224**fifo** 225 226  kfifo队列结构体的指针 227 228#### 返回值 229 230| 情况 | 返回值 | 231| ----------------------- | --- | 232| 空 | 1 | 233| 非空 | 0 | 234 235### kfifo_full 236 237`kfifo_full(fifo)` 238 239#### 描述 240 241  判断kfifo缓冲区当前是否为满 242 243#### 参数 244 245**fifo** 246 247  kfifo队列结构体的指针 248 249#### 返回值 250 251| 情况 | 返回值 | 252| ------| --- | 253| 满 | 1 | 254| 不满 | 0 | 255 256------------------ 257 258## ID Allocation 259 260   ida的主要作用是分配+管理id. 它能分配一个最小的, 未被分配出去的id. 当您需要管理某个数据结构时, 可能需要使用id来区分不同的目标. 这个时候, ida将会是很好的选择. 因为ida的十分高效, 运行常数相对数组更小, 而且提供了基本管理id需要用到的功能, 值得您试一试. 261 262  IDA定义于`idr.h`文件中. 您通过`DECLARE_IDA(my_ida)`来创建一个ida对象, 或者`struct ida my_ida; ida_init(&my_ida);`来初始化一个ida. 263 264### ida_init 265`void ida_init(struct ida *ida_p)` 266 267#### 描述 268 269  通初始化IDA, 你需要保证调用函数之前, ida的free_list为空, 否则会导致内存泄漏. 270#### 参数 271 272**ida_p** 273 274   指向ida的指针 275 276#### 返回值 277 278  无返回值 279 280### ida_preload 281`int ida_preload(struct ida *ida_p, gfp_t gfp_mask)` 282 283#### 描述 284 285  为ida预分配空间.您可以不自行调用, 因为当ida需要空间的时候, 内部会自行使用`kmalloc`函数获取空间. 当然, 设计这个函数的目的是为了让您有更多的选择. 当您提前调用这个函数, 可以避免之后在开辟空间上的时间开销. 286#### 参数 287 288**ida_p** 289 290   指向ida的指针 291 292**gfp_mask** 293 294   保留参数, 目前尚未使用. 295 296#### 返回值 297 298  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. 299 300 301### ida_alloc 302`int ida_alloc(struct ida *ida_p, int *p_id)` 303 304#### 描述 305 306  获取一个空闲ID. 您需要注意, 返回值是成功/错误码. 307#### 参数 308 309**ida_p** 310 311   指向ida的指针 312 313**p_id** 314 315   您需要传入一个int变量的指针, 如果成功分配ID, ID将会存储在该指针所指向的地址. 316 317#### 返回值 318 319  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. 320 321 322### ida_count 323`bool ida_count(struct ida *ida_p, int id)` 324 325#### 描述 326 327  查询一个ID是否被分配. 328#### 参数 329 330**ida_p** 331 332   指向ida的指针 333 334**id** 335 336   您查询该ID是否被分配. 337 338#### 返回值 339 340  如果分配,将返回true; 否则返回false. 341 342 343 344### ida_remove 345`void ida_remove(struct ida *ida_p, int id)` 346 347#### 描述 348 349  删除一个已经分配的ID. 如果该ID不存在, 该函数不会产生异常错误, 因为在检测到该ID不存在的时候, 函数将会自动退出. 350#### 参数 351 352**ida_p** 353 354   指向ida的指针 355 356**id** 357 358   您要删除的id. 359 360#### 返回值 361 362  无返回值. 363 364### ida_destroy 365`void ida_destroy(struct ida *ida_p)` 366 367#### 描述 368 369  释放一个IDA所有的空间, 同时删除ida的所有已经分配的id.(所以您不用担心删除id之后, ida还会占用大量空间.) 370#### 参数 371 372**ida_p** 373 374   指向ida的指针 375 376#### 返回值 377 378  无返回值 379 380### ida_empty 381`void ida_empty(struct ida *ida_p)` 382 383#### 描述 384 385   查询一个ida是否为空 386#### 参数 387 388**ida_p** 389 390   指向ida的指针 391 392#### 返回值 393 394  ida为空则返回true,否则返回false。 395 396 397-------------------- 398 399 400## IDR 401 402   idr是一个基于radix-tree的ID-pointer的数据结构. 该数据结构提供了建id与数据指针绑定的功能, 它的主要功能有以下4个: 4031. 获取一个ID, 并且将该ID与一个指针绑定 4042. 删除一个已分配的ID 4053. 根据ID查找对应的指针 4064. 根据ID使用新的ptr替换旧的ptr 407   您可以使用`DECLARE_idr(my_idr)`来创建一个idr。或者您也可以使用`struct idr my_idr; idr_init(my_idr);`这两句话创建一个idr。 408   至于什么是radix-tree,您可以把他简单理解为一个向上生长的多叉树,在实现中,我们选取了64叉树。 409 410### idr_init 411`void idr_init(struct idr *idp)` 412 413#### 描述 414 415  通初始化IDR, 你需要保证调用函数之前, idr的free_list为空, 否则会导致内存泄漏. 416#### 参数 417 418**idp** 419 420   指向idr的指针 421 422#### 返回值 423 424  无返回值 425 426### idr_preload 427`int idr_preload(struct idr *idp, gfp_t gfp_mask)` 428 429#### 描述 430 431  为idr预分配空间.您可以不自行调用, 因为当idr需要空间的时候, 内部会自行使用`kmalloc`函数获取空间. 当然, 设计这个函数的目的是为了让您有更多的选择. 当您提前调用这个函数, 可以避免之后在开辟空间上的时间开销. 432#### 参数 433 434**idp** 435 436   指向idr的指针 437 438**gfp_mask** 439 440   保留参数, 目前尚未使用. 441 442#### 返回值 443 444  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. 445 446 447### idr_alloc 448`int idr_alloc(struct idr *idp, void *ptr, int *id)` 449 450#### 描述 451 452   获取一个空闲ID. 您需要注意, 返回值是成功/错误码. 453   调用这个函数,需要您保证ptr是非空的,即: `ptr != NULL`, 否则将会影响 `idr_find/idr_find_next/idr_find_next_getid/...`等函数的使用。(具体请看这三个函数的说明,当然,只会影响到您的使用体验,并不会影响到idr内部函数的决策和逻辑) 454#### 参数 455 456**idp** 457 458   指向ida的指针 459 460**ptr** 461 462   指向数据的指针 463 464**id** 465 466   您需要传入一个int变量的指针, 如果成功分配ID, ID将会存储在该指针所指向的地址. 467 468#### 返回值 469 470  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. 471 472 473### idr_remove 474`void* idr_remove(struct idr *idp, int id)` 475 476#### 描述 477 478  删除一个id, 但是不释放对应的ptr指向的空间, 同时返回这个被删除id所对应的ptr。 479   如果该ID不存在, 该函数不会产生异常错误, 因为在检测到该ID不存在的时候, 函数将会自动退出,并返回NULL。 480#### 参数 481 482**idp** 483 484   指向idr的指针 485 486**id** 487 488   您要删除的id. 489 490#### 返回值 491 492  如果删除成功,就返回被删除id所对应的ptr;否则返回NULL。注意:如果这个id本来就和NULL绑定,那么也会返回NULL 493 494 495### idr_remove_all 496`void idr_remove_all(struct idr *idp)` 497 498#### 描述 499 500  删除idr的所有已经分配的id.(所以您不用担心删除id之后, idr还会占用大量空间。) 501 502   但是你需要注意的是,调用这个函数是不会释放数据指针指向的空间的。 所以您调用该函数之前, 确保IDR内部的数据指针被保存。否则当IDR删除所有ID之后, 将会造成内存泄漏。 503 504#### 参数 505 506**idp** 507 508   指向idr的指针 509 510#### 返回值 511 512  无返回值 513 514 515### idr_destroy 516`void idr_destroy(struct idr *idp)` 517 518#### 描述 519 520  释放一个IDR所有的空间, 同时删除idr的所有已经分配的id.(所以您不用担心删除id之后, ida还会占用大量空间.) - 和`idr_remove_all`的区别是, 释放掉所有的空间(包括free_list的预分配空间)。 521#### 参数 522 523**idp** 524 525   指向idr的指针 526 527#### 返回值 528 529  无返回值 530 531 532### idr_find 533`void *idr_find(struct idr *idp, int id)` 534 535#### 描述 536 537  查询一个ID所绑定的数据指针 538#### 参数 539 540**idp** 541 542   指向idr的指针 543 544**id** 545 546   您查询该ID的数据指针 547 548#### 返回值 549 550   如果分配,将返回该ID对应的数据指针; 否则返回NULL.(注意, 返回NULL不一定代表这ID不存在,有可能该ID就是与空指针绑定。) 551   当然,我们也提供了`idr_count`函数来判断id是否被分配,具体请查看idr_count介绍。 552 553### idr_find_next 554`void *idr_find_next(struct idr *idp, int start_id)` 555 556#### 描述 557 558  传进一个start_id,返回满足 "id大于start_id的最小id" 所对应的数据指针。 559#### 参数 560 561**idp** 562 563   指向idr的指针 564 565**start_id** 566 567  您提供的ID限制 568 569#### 返回值 570 571   如果分配,将返回该ID对应的数据指针; 否则返回NULL.(注意, 返回NULL不一定代表这ID不存在,有可能该ID就是与空指针绑定。) 572   当然,我们也提供了`idr_count`函数来判断id是否被分配,具体请查看idr_count介绍。 573 574 575### idr_find_next_getid 576`void *idr_find_next_getid(struct idr *idp, int start_id, int *nextid)` 577 578#### 描述 579 580  传进一个start_id,返回满足 "id大于start_id的最小id" 所对应的数据指针。同时,你获取到这个满足条件的最小id, 即参数中的 *nextid。 581#### 参数 582 583**idp** 584 585   指向idr的指针 586 587**start_id** 588 589   您提供的ID限制 590 591#### 返回值 592 593   如果分配,将返回该ID对应的数据指针; 否则返回NULL.(注意, 返回NULL不一定代表这ID不存在,有可能该ID就是与空指针绑定。) 594   当然,我们也提供了`idr_count`函数来判断id是否被分配,具体请查看idr_count介绍。 595 596 597### idr_replace 598`int idr_replace(struct idr *idp, void *ptr, int id)` 599 600#### 描述 601 602  传进一个ptr,使用该ptr替换掉id所对应的Old_ptr。 603#### 参数 604 605**idp** 606 607   指向idr的指针 608 609**ptr** 610 611  您要替换原来的old_ptr的新指针 612 613**id** 614 615   您要替换的指针所对应的id 616 617#### 返回值 618 619   0代表成功,否则就是错误码 - 代表错误。 620 621 622### idr_replace_get_old 623`int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **oldptr)` 624 625#### 描述 626 627  传进一个ptr,使用该ptr替换掉id所对应的Old_ptr,同时你可以获取到old_ptr。 628#### 参数 629 630**idp** 631 632   指向idr的指针 633 634**ptr** 635 636  您要替换原来的old_ptr的新指针 637 638**id** 639 640   您要替换的指针所对应的id 641 642 643**old_ptr** 644 645   您需要传进该(void**)指针,old_ptr将会存放在该指针所指向的地址。 646 647 648#### 返回值 649 650   0代表成功,否则就是错误码 - 代表错误。 651 652### idr_empty 653`void idr_empty(struct idr *idp)` 654 655#### 描述 656 657   查询一个idr是否为空 658#### 参数 659 660**idp** 661 662   指向idr的指针 663 664#### 返回值 665 666  idr为空则返回true,否则返回false。 667 668### idr_count 669`bool idr_count(struct idr *idp, int id)` 670 671#### 描述 672 673  查询一个ID是否被分配. 674#### 参数 675 676**ida_p** 677 678   指向idr的指针 679 680**id** 681 682   您查询该ID是否被分配. 683 684#### 返回值 685 686  如果分配,将返回true; 否则返回false.