LinuxÄÚºËÖг£ÓõÄÊý¾Ý½á¹¹ºÍËã·¨
LinuxÄں˴úÂëÖÐÆÕ±éʹÓÃÁËÊý¾Ý½á¹¹ºÍËã·¨£¬ÆäÖÐ×î³£ÓõÄÁ½¸öÊÇÁ´±íºÍºìºÚÊ÷¡£
Á´±í
LinuxÄں˴úÂë´ó×ÚʹÓÃÁËÁ´±íÕâÖÖÊý¾Ý½á¹¹¡£Á´±íÊÇÔÚ½â¾öÊý×é²»¿É¶¯Ì¬À©Õ¹Õâ¸öȱÏݶø±¬·¢µÄÒ»ÖÖÊý¾Ý½á¹¹¡£Á´±íËù°üÀ¨µÄÔªËØ¿ÉÒÔ¶¯Ì¬½¨Éè²¢²åÈëºÍɾ³ý¡£Á´±íµÄÿ¸öÔªËض¼ÊÇÀëÉ¢´æ·ÅµÄ£¬Òò´Ë²»ÐèÒªÕ¼ÓÃÒ»Á¬µÄÄÚ´æ¡£Á´±íͨ³£ÓÉÈô¸É½Úµã×é³É£¬Ã¿¸ö½ÚµãµÄ½á¹¹¶¼ÊÇÒ»ÑùµÄ£¬ÓÉÓÐÓÃÊý¾ÝÇøºÍÖ¸ÕëÇøÁ½²¿·Ö×é³É¡£ÓÐÓÃÊý¾ÝÇøÓÃÀ´´æ´¢ÓÐÓÃÊý¾ÝÐÅÏ¢£¬¶øÖ¸ÕëÇøÓÃÀ´Ö¸ÏòÁ´±íµÄÇ°¼Ì½Úµã»òÕߺó¼Ì½Úµã¡£Òò´Ë£¬Á´±í¾ÍÊÇʹÓÃÖ¸Õ뽫¸÷¸ö½Úµã´®ÁªÆðÀ´µÄÒ»ÖÖ´æ´¢½á¹¹¡£
£¨1£©µ¥ÏòÁ´±í
µ¥ÏòÁ´±íµÄÖ¸ÕëÇøÖ»°üÀ¨Ò»¸öÖ¸ÏòÏÂÒ»¸ö½ÚµãµÄÖ¸Õ룬Òò´Ë»áÐγÉÒ»¸ö¼òµ¥Æ«ÏòµÄÁ´±í£¬ÈçÏ´úÂëËùʾ¡£
struct list { int data; /*ÓÐÓÃÊý¾Ý*/ struct list *next; /*Ö¸ÏòÏÂÒ»¸öÔªËصÄÖ¸Õë*/ };
µÇ¼ºó¸´ÖÆ
ÈçͼËùʾ£¬µ¥ÏòÁ´±í¾ßÓе¥ÏòÒƶ¯ÐÔ£¬Ò²¾ÍÊÇÖ»ÄÜ»á¼ûÄ¿½ñµÄ½ÚµãµÄºó¼Ì½Úµã£¬¶øÎÞ·¨»á¼ûÄ¿½ñ½ÚµãµÄÇ°¼Ì½Úµã£¬Òò´ËÔÚÏÖʵÏîÄ¿ÖÐÔËÓõýÏÁ¿ÉÙ¡£
µ¥ÏòÁ´ÌåÏÖÒâͼ
£¨2£©Ë«ÏòÁ´±í
ÈçͼËùʾ£¬Ë«ÏòÁ´±íºÍµ¥ÏòÁ´±íµÄÇø±ðÊÇÖ¸ÕëÇø°üÀ¨ÁËÁ½¸öÖ¸Õ룬һ¸öÖ¸ÏòÇ°¼Ì½Úµã£¬ÁíÒ»¸öÖ¸Ïòºó¼Ì½Úµã£¬ÈçÏ´úÂëËùʾ¡£
struct list { int data; /*ÓÐÓÃÊý¾Ý*/ struct list *next; /*Ö¸ÏòÏÂÒ»¸öÔªËصÄÖ¸Õë*/ struct list *prev; /*Ö¸ÏòÉÏÒ»¸öÔªËصÄÖ¸Õë*/ };
µÇ¼ºó¸´ÖÆ
Ë«ÏòÁ´ÌåÏÖÒâͼ
£¨3£©LinuxÄÚºËÁ´±íʵÏÖ
µ¥ÏòÁ´±íºÍË«ÏòÁ´±íÔÚÏÖʵʹÓÃÖÐÓÐһЩ¾ÖÏÞÐÔ£¬ÈçÊý¾ÝÇø±ØÐèÊÇÀο¿Êý¾Ý£¬¶øÏÖʵÐèÇóÊǶàÖÖ¶àÑùµÄ¡£ÕâÖÖÒªÁìÎÞ·¨¹¹½¨Ò»Ì×ͨÓõÄÁ´±í£¬ÓÉÓÚÿ¸ö²î±ðµÄÊý¾ÝÇøÐèÒªÒ»Ì×Á´±í¡£Îª´Ë£¬LinuxÄں˰ÑËùÓÐÁ´±í²Ù×÷ÒªÁìµÄÅäºÏ²¿·ÖÌáÈ¡³öÀ´£¬°Ñ²î±ðµÄ²¿·ÖÁô¸ø´úÂë±à³ÌÕß×Ô¼ºÐÐÖ¹Öá£LinuxÄÚºËʵÏÖÁËÒ»Ì×´¿Á´±íµÄ·â×°£¬Á´±í½ÚµãÊý¾Ý½á¹¹Ö»ÓÐÖ¸ÕëÇø¶øûÓÐÊý¾ÝÇø£¬ÁíÍ⻹·â×°ÁËÖݪֲÙ×÷º¯Êý£¬È罨Éè½Úµãº¯Êý¡¢²åÈë½Úµãº¯Êý¡¢É¾³ý½Úµãº¯Êý¡¢±éÀú½Úµãº¯ÊýµÈ¡£
LinuxÄÚºËÁ´±íʹÓÃstruct list_headÊý¾Ý½á¹¹À´ÐÎò¡£
<include/linux/types.h> struct list_head { struct list_head *next, *prev; };
µÇ¼ºó¸´ÖÆ
struct list_headÊý¾Ý½á¹¹²»°üÀ¨Á´±í½ÚµãµÄÊý¾ÝÇø£¬Í¨³£ÊÇǶÈëÆäËûÊý¾Ý½á¹¹£¬Èçstruct pageÊý¾Ý½á¹¹ÖÐǶÈëÁËÒ»¸ölruÁ´±í½Úµã£¬Í¨³£ÊÇ°ÑpageÊý¾Ý½á¹¹¹ÒÈëLRUÁ´±í¡£
<include/linux/mm_types.h> struct page { ... struct list_head lru; ... }
µÇ¼ºó¸´ÖÆ
Á´±íÍ·µÄ³õʼ»¯ÓÐÁ½ÖÖÒªÁ죬һÖÖÊǾ²Ì¬³õʼ»¯£¬ÁíÒ»ÖÖ¶¯Ì¬³õʼ»¯¡£
°ÑnextºÍprevÖ¸Õ붼³õʼ»¯²¢Ö¸Ïò×Ô¼º£¬ÕâÑù±ã³õʼ»¯ÁËÒ»¸ö´ø¶¯½ÚµãµÄ¿ÕÁ´±í¡£
<include/linux/list.h> /*¾²Ì¬³õʼ»¯*/ #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) /*¶¯Ì¬³õʼ»¯*/ static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; }
µÇ¼ºó¸´ÖÆ
Ìí¼Ó½Úµãµ½Ò»¸öÁ´±íÖУ¬ÄÚºËÌṩÁ˼¸¸ö½Ó¿Úº¯Êý£¬Èçlist_add()ÊÇ°ÑÒ»¸ö½ÚµãÌí¼Óµ½±íÍ·£¬list_add_tail()ÊDzåÈë±íβ¡£
<include/linux/list.h> void list_add(struct list_head *new, struct list_head *head) list_add_tail(struct list_head *new, struct list_head *head)
µÇ¼ºó¸´ÖÆ
±éÀú½ÚµãµÄ½Ó¿Úº¯Êý¡£
#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)
µÇ¼ºó¸´ÖÆ
Õâ¸öºêÖ»ÊDZéÀúÒ»¸öÒ»¸ö½ÚµãµÄÄ¿½ñλÖã¬ÄÇôÔõÑù»ñÈ¡½Úµã×Ô¼ºµÄÊý¾Ý½á¹¹ÄØ£¿ÕâÀﻹÐèҪʹÓÃlist_entry()ºê¡£
#define list_entry(ptr, type, member) \ container_of(ptr, type, member) container_of()ºêµÄ½ç˵ÔÚkernel.hÍ·ÎļþÖС£ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
µÇ¼ºó¸´ÖÆ
ÆäÖÐoffsetof()ºêÊÇͨ¹ý°Ñ0µØµãת»»ÎªtypeÀàÐ͵ÄÖ¸Õ룬ȻºóÈ¥»ñÈ¡¸Ã½á¹¹ÌåÖÐmember³ÉÔ±µÄÖ¸Õ룬Ҳ¾ÍÊÇ»ñÈ¡ÁËmemberÔÚtype½á¹¹ÌåÖеÄÆ«ÒÆÁ¿¡£×îºóÓÃÖ¸Õëptr¼õÈ¥offset£¬¾Í»ñµÃtype½á¹¹ÌåµÄÕæʵµØµãÁË¡£
ÏÂÃæÊDZéÀúÁ´±íµÄÒ»¸öÀý×Ó¡£
<drivers/block/osdblk.c> static ssize_t class_osdblk_list(struct class *c, struct class_attribute *attr, char *data) { int n = 0; struct list_head *tmp; list_for_each(tmp, &osdblkdev_list) { struct osdblk_device *osdev; osdev = list_entry(tmp, struct osdblk_device, node); n += sprintf(data+n, "%d %d %llu %llu %s\n", osdev->id, osdev->major, osdev->obj.partition, osdev->obj.id, osdev->osd_path); } return n; }
µÇ¼ºó¸´ÖÆ
ºìºÚÊ÷
ºìºÚÊ÷£¨Red Black Tree£©±»ÆÕ±éÓ¦ÓÃÔÚÄں˵ÄÄÚ´æÖÎÀíºÍÀú³Ìµ÷ÀíÖУ¬ÓÃÓÚ½«ÅÅÐòµÄÔªËØ×éÖ¯µ½Ê÷ÖС£ºìºÚÊ÷±»ÆÕ±éÓ¦ÓÃÔÚÅÌËã»ú¿ÆѧµÄ¸÷¸öÁìÓòÖУ¬ËüÔÚËÙÂʺÍʵÏÖÖØƯºóÖ®¼äÌṩһ¸öºÜºÃµÄƽºâ¡£
ºìºÚÊ÷ÊǾßÓÐÒÔÏÂÌØÕ÷µÄ¶þ²æÊ÷¡£
ÿ¸ö½Úµã»òºì»òºÚ¡£
ÿ¸öÒ¶½ÚµãÊÇÐþÉ«µÄ¡£
ÈôÊǽáµã¶¼ÊǺìÉ«£¬ÄÇôÁ½¸ö×Ó½áµã¶¼ÊÇÐþÉ«¡£
´ÓÒ»¸öÄÚ²¿½áµãµ½Ò¶½áµãµÄ¼òÆÓ·¾¶ÉÏ£¬¶ÔËùÓÐÒ¶½ÚµãÀ´Ëµ£¬ÐþÉ«½áµãµÄÊýÄ¿¶¼ÊÇÏàͬµÄ¡£
ºìºÚÊ÷µÄÒ»¸öÓŵãÊÇ£¬ËùÓÐÖ÷ÒªµÄ²Ù×÷£¨ÀýÈç²åÈ롢ɾ³ý¡¢ËÑË÷£©¶¼¿ÉÒÔÔÚO(log n)ʱ¼äÄÚÍê³É£¬nΪÊ÷ÖÐÔªËصÄÊýÄ¿¡£¾µäµÄËã·¨½Ì¿ÆÊ鶼»á½â˵ºìºÚÊ÷µÄʵÏÖ£¬ÕâÀïÖ»ÊÇÁгöÒ»¸öÄÚºËÖÐʹÓúìºÚÊ÷µÄÀý×Ó£¬¹©¶ÁÕßÔÚÏÖʵµÄÇý¶¯ºÍÄں˱à³ÌÖвο¼¡£Õâ¸öÀý×Ó¿ÉÒÔÔÚÄں˴úÂëµÄdocumentation/Rbtree.txtÎļþÖÐÕÒµ½¡£
#include <linux/init.h> #include <linux/list.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/rbtree.h> MODULE_AUTHOR("figo.zhang"); MODULE_DESCRIPTION(" "); MODULE_LICENSE("GPL"); struct mytype { struct rb_node node; int key; }; /*ºìºÚÊ÷¸ù½Úµã*/ struct rb_root mytree = RB_ROOT; /*ƾ֤keyÀ´²éÕÒ½Úµã*/ struct mytype *my_search(struct rb_root *root, int new) { struct rb_node *node = root->rb_node; while (node) { struct mytype *data = container_of(node, struct mytype, node); if (data->key > new) node = node->rb_left; else if (data->key < new) node = node->rb_right; else return data; } return NULL; } /*²åÈëÒ»¸öÔªËص½ºìºÚÊ÷ÖÐ*/ int my_insert(struct rb_root *root, struct mytype *data) { struct rb_node **new = &(root->rb_node), *parent=NULL; /* Ñ°ÕÒ¿ÉÒÔÌí¼ÓнڵãµÄµØ·½ */ while (*new) { struct mytype *this = container_of(*new, struct mytype, node); parent = *new; if (this->key > data->key) new = &((*new)->rb_left); else if (this->key < data->key) { new = &((*new)->rb_right); } else return -1; } /* Ìí¼ÓÒ»¸öнڵã */ rb_link_node(&data->node, parent, new); rb_insert_color(&data->node, root); return 0; } static int __init my_init(void) { int i; struct mytype *data; struct rb_node *node; /*²åÈëÔªËØ*/ for (i =0; i < 20; i+=2) { data = kmalloc(sizeof(struct mytype), GFP_KERNEL); data->key = i; my_insert(&mytree, data); } /*±éÀúºìºÚÊ÷£¬´òÓ¡ËùÓнڵãµÄkeyÖµ*/ for (node = rb_first(&mytree); node; node = rb_next(node)) printk("key=%d\n", rb_entry(node, struct mytype, node)->key); return 0; } static void __exit my_exit(void) { struct mytype *data; struct rb_node *node; for (node = rb_first(&mytree); node; node = rb_next(node)) { data = rb_entry(node, struct mytype, node); if (data) { rb_erase(&data->node, &mytree); kfree(data); } } } module_init(my_init); module_exit(my_exit);
µÇ¼ºó¸´ÖÆ
mytreeÊǺìºÚÊ÷µÄ¸ù½Úµã£¬my_insert()ʵÏÖ²åÈëÒ»¸öÔªËص½ºìºÚÊ÷ÖУ¬my_search()ƾ֤keyÀ´²éÕҽڵ㡣Äں˴ó×ÚʹÓúìºÚÊ÷£¬ÈçÐéÄâµØµã¿Õ¼äVMAµÄÖÎÀí¡£
ÎÞËø»·Ðλº³åÇø
Éú²úÕߺÍÏûºÄÕßÄ£×ÓÊÇÅÌËã»ú±à³ÌÖÐ×î³£¼ûµÄÒ»ÖÖÄ£×Ó¡£Éú²úÕß±¬·¢Êý¾Ý£¬¶øÏûºÄÕßÏûºÄÊý¾Ý£¬ÈçÒ»¸öÍøÂç×°±¸£¬Ó²¼þ×°±¸ÎüÊÕÍøÂç°ü£¬È»ºóÓ¦ÓóÌÐò¶ÁÈ¡ÍøÂç°ü¡£»·Ðλº³åÇøÊÇʵÏÖÉú²úÕߺÍÏûºÄÕßÄ£×ӵľµäËã·¨¡£»·Ðλº³åÇøͨ³£ÓÐÒ»¸ö¶ÁÖ¸ÕëºÍÒ»¸öдָÕë¡£¶ÁÖ¸ÕëÖ¸Ïò»·Ðλº³åÇøÖпɶÁµÄÊý¾Ý£¬Ð´Ö¸ÕëÖ¸Ïò»·Ðλº³åÇø¿ÉдµÄÊý¾Ý¡£Í¨¹ýÒƶ¯¶ÁÖ¸ÕëºÍдָÕëʵÏÖ»º³åÇøÊý¾ÝµÄ¶ÁÈ¡ºÍдÈë¡£
ÔÚLinuxÄÚºËÖУ¬KFIFOÊǽÓÄÉÎÞËø»·Ðλº³åÇøµÄʵÏÖ¡£FIFOµÄÈ«³ÆÊÇ¡°First In First Out¡±£¬¼´ÏȽøÏȳöµÄÊý¾Ý½á¹¹£¬Ëü½ÓÄÉ»·Ðλº³åÇøµÄÒªÁìÀ´ÊµÏÖ£¬²¢Ìṩһ¸öÎÞ½çÏßµÄ×Ö½ÚԼЧÀÍ¡£½ÓÄÉ»·Ðλº³åÇøµÄÀûÒæÊÇ£¬µ±Ò»¸öÊý¾ÝÔªËر»ÏûºÄÖ®ºó£¬ÆäÓàÊý¾ÝÔªËز»ÐèÒªÒƶ¯Æä´æ´¢Î»Ö㬴ӶøïÔ̸´ÖÆ£¬Ìá¸ßЧÂÊ¡£
£¨1£©½¨ÉèKFIFO
ÔÚʹÓÃKFIFO֮ǰÐèÒª¾ÙÐгõʼ»¯£¬ÕâÀïÓо²Ì¬³õʼ»¯ºÍ¶¯Ì¬³õʼ»¯Á½ÖÖ·½·¨¡£
<include/linux/kfifo.h> int kfifo_alloc(fifo, size, gfp_mask)
µÇ¼ºó¸´ÖÆ
¸Ãº¯Êý½¨Éè²¢·ÖÅÉÒ»¸ö¾ÞϸΪsizeµÄKFIFO»·Ðλº³åÇø¡£µÚÒ»¸ö²ÎÊýfifoÊÇÖ¸Ïò¸Ã»·Ðλº³åÇøµÄstruct kfifoÊý¾Ý½á¹¹£»µÚ¶þ¸ö²ÎÊýsizeÊÇÖ¸¶¨»º³åÇøÔªËصÄÊýÄ¿£»µÚÈý¸ö²ÎÊýgfp_maskÌåÏÖ·ÖÅÉKFIFOÔªËØʹÓõķÖÅÉÑÚÂë¡£
¾²Ì¬·ÖÅÉ¿ÉÒÔʹÓÃÈçϵĺꡣ
#define DEFINE_KFIFO(fifo, type, size) #define INIT_KFIFO(fifo)
µÇ¼ºó¸´ÖÆ
£¨2£©ÈëÁÐ
°ÑÊý¾ÝдÈëKFIFO»·Ðλº³åÇø¿ÉÒÔʹÓÃkfifo_in()º¯Êý½Ó¿Ú¡£
int kfifo_in(fifo, buf, n)
µÇ¼ºó¸´ÖÆ
¸Ãº¯Êý°ÑbufÖ¸ÕëÖ¸ÏòµÄn¸öÊý¾Ý¸´ÖƵ½KFIFO»·Ðλº³åÇøÖС£µÚÒ»¸ö²ÎÊýfifoÖ¸µÄÊÇKFIFO»·Ðλº³åÇø£»µÚ¶þ¸ö²ÎÊýbufÖ¸ÏòÒª¸´ÖƵÄÊý¾ÝµÄbuffer£»µÚÈý¸öÊý¾ÝÊÇÒª¸´ÖÆÊý¾ÝÔªËصÄÊýÄ¿¡£
£¨3£©³öÁÐ
´ÓKFIFO»·Ðλº³åÇøÖÐÁгö»òÕßժȡÊý¾Ý¿ÉÒÔʹÓÃkfifo_out()º¯Êý½Ó¿Ú¡£
#define kfifo_out(fifo, buf, n)
µÇ¼ºó¸´ÖÆ
¸Ãº¯ÊýÊÇ´ÓfifoÖ¸ÏòµÄ»·Ðλº³åÇøÖи´ÖÆn¸öÊý¾ÝÔªËص½bufÖ¸ÏòµÄ»º³åÇøÖС£ÈôÊÇKFIFO»·Ðλº³åÇøµÄÊý¾ÝÔªËØСÓÚn¸ö£¬ÄÇô¸´ÖƳöÈ¥µÄÊý¾ÝÔªËØСÓÚn¸ö¡£
£¨4£©»ñÈ¡»º³åÇø¾Þϸ
KFIFOÌṩÁ˼¸¸ö½Ó¿Úº¯ÊýÀ´ÅÌÎÊ»·Ðλº³åÇøµÄ״̬¡£
#define kfifo_size(fifo) #define kfifo_len(fifo) #define kfifo_is_empty(fifo) #define kfifo_is_full(fifo)
µÇ¼ºó¸´ÖÆ
kfifo_size()ÓÃÀ´»ñÈ¡»·Ðλº³åÇøµÄ¾Þϸ£¬Ò²¾ÍÊÇ×î´ó¿ÉÒÔÈÝÄɼ¸¶à¸öÊý¾ÝÔªËØ¡£kfifo_len()ÓÃÀ´»ñÈ¡Ä¿½ñ»·Ðλº³åÇøÖÐÓм¸¶à¸öÓÐÓÃÊý¾ÝÔªËØ¡£kfifo_is_empty()Åжϻ·Ðλº³åÇøÊÇ·ñΪ¿Õ¡£kfifo_is_full()Åжϻ·Ðλº³åÇøÊÇ·ñΪÂú¡£
£¨5£©ÓëÓû§¿Õ¼äÊý¾Ý½»»¥
KFIFO»¹·â×°ÁËÁ½¸öº¯ÊýÓëÓû§¿Õ¼äÊý¾Ý½»»¥¡£
#define kfifo_from_user(fifo, from, len, copied) #define kfifo_to_user(fifo, to, len, copied)
µÇ¼ºó¸´ÖÆ
kfifo_from_user()ÊÇ°ÑfromÖ¸ÏòµÄÓû§¿Õ¼äµÄlen¸öÊý¾ÝÔªËظ´ÖƵ½KFIFOÖУ¬×îºóÒ»¸ö²ÎÊýcopiedÌåÏÖÀֳɸ´ÖÆÁ˼¸¸öÊý¾ÝÔªËØ¡£
kfifo_to_user()ÔòÏà·´£¬°ÑKFIFOµÄÊý¾ÝÔªËظ´ÖƵ½Óû§¿Õ¼ä¡£ÕâÁ½¸öºêÍŽáÁËcopy_to_user()¡¢copy_from_user()ÒÔ¼°KFIFOµÄ»úÖÆ£¬¸øÇý¶¯¿ª·¢ÕßÌṩÁËÀû±ã¡£
ÒÔÉϾÍÊÇLinuxÄÚºËÖг£ÓõÄÊý¾Ý½á¹¹ºÍËã·¨µÄÏêϸÄÚÈÝ£¬¸ü¶àÇë¹Ø×¢±¾ÍøÄÚÆäËüÏà¹ØÎÄÕ£¡