\n\u5bfc\u8bfb<\/td>\n | Linux \u5185\u6838\u4e2d\u81ea\u5df1\u5b9e\u73b0\u4e86\u53cc\u5411\u94fe\u8868\uff0c\u53ef\u4ee5\u5728 include\/linux\/list.h \u627e\u5230\u5b9a\u4e49\u3002\u6211\u4eec\u5c06\u4f1a\u9996\u5148\u4ece\u53cc\u5411\u94fe\u8868\u6570\u636e\u7ed3\u6784\u5f00\u59cb\u4ecb\u7ecd\u5185\u6838\u91cc\u7684\u6570\u636e\u7ed3\u6784\u3002\u4e3a\u4ec0\u4e48\uff1f\u56e0\u4e3a\u5b83\u5728\u5185\u6838\u91cc\u4f7f\u7528\u7684\u5f88\u5e7f\u6cdb\uff0c\u4f60\u53ea\u9700\u8981\u5728 free-electrons.com \u68c0\u7d22\u4e00\u4e0b\u5c31\u77e5\u9053\u4e86\u3002<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n <\/p>\n \u9996\u5148\u8ba9\u6211\u4eec\u770b\u4e00\u4e0b\u5728 include\/linux\/types.h \u91cc\u7684\u4e3b\u7ed3\u6784\u4f53\uff1a<\/strong><\/div>\nstruct list_head { \r\n struct list_head *next, *prev;\r\n};<\/pre>\n\u4f60\u53ef\u80fd\u6ce8\u610f\u5230\u8fd9\u548c\u4f60\u4ee5\u524d\u89c1\u8fc7\u7684\u53cc\u5411\u94fe\u8868\u7684\u5b9e\u73b0\u65b9\u6cd5\u662f\u4e0d\u540c\u7684\u3002<\/strong><\/div>\n\u4e3e\u4e2a\u4f8b\u5b50\u6765\u8bf4\uff0c\u5728 glib \u5e93\u91cc\u662f\u8fd9\u6837\u5b9e\u73b0\u7684\uff1a<\/p>\n struct GList {\r\ngpointer data;\r\nGList *next;\r\nGList *prev;\r\n};<\/pre>\n\u901a\u5e38\u6765\u8bf4\u4e00\u4e2a\u94fe\u8868\u7ed3\u6784\u4f1a\u5305\u542b\u4e00\u4e2a\u6307\u5411\u67d0\u4e2a\u9879\u76ee\u7684\u6307\u9488\u3002<\/strong><\/div>\n\u4f46\u662f Linux \u5185\u6838\u4e2d\u7684\u94fe\u8868\u5b9e\u73b0\u5e76\u6ca1\u6709\u8fd9\u6837\u505a\u3002\u6240\u4ee5\u95ee\u9898\u6765\u4e86\uff1a\u94fe\u8868\u5728\u54ea\u91cc\u4fdd\u5b58\u6570\u636e\u5462\uff1f\u5b9e\u9645\u4e0a\uff0c\u5185\u6838\u91cc\u5b9e\u73b0\u7684\u94fe\u8868\u662f\u4fb5\u5165\u5f0f\u94fe\u8868\uff08Intrusive list\uff09\u3002\u4fb5\u5165\u5f0f\u94fe\u8868\u5e76\u4e0d\u5728\u8282\u70b9\u5185\u4fdd\u5b58\u6570\u636e-\u5b83\u7684\u8282\u70b9\u4ec5\u4ec5\u5305\u542b\u6307\u5411\u524d\u540e\u8282\u70b9\u7684\u6307\u9488\uff0c\u4ee5\u53ca\u6307\u5411\u94fe\u8868\u8282\u70b9\u6570\u636e\u90e8\u5206\u7684\u6307\u9488\u2014\u2014\u6570\u636e\u5c31\u662f\u8fd9\u6837\u9644\u52a0\u5728\u94fe\u8868\u4e0a\u7684\u3002\u8fd9\u5c31\u4f7f\u5f97\u8fd9\u4e2a\u6570\u636e\u7ed3\u6784\u662f\u901a\u7528\u7684\uff0c\u4f7f\u7528\u8d77\u6765\u5c31\u4e0d\u9700\u8981\u8003\u8651\u8282\u70b9\u6570\u636e\u7684\u7c7b\u578b\u4e86\u3002<\/p>\n \u6bd4\u5982\uff1a<\/strong><\/span><\/div>\nstruct nmi_desc {\r\nspinlock_t lock;\r\nstruct list_head head;\r\n};<\/pre>\n\u8ba9\u6211\u4eec\u770b\u51e0\u4e2a\u4f8b\u5b50\u6765\u7406\u89e3\u4e00\u4e0b\u5728\u5185\u6838\u91cc\u662f\u5982\u4f55\u4f7f\u7528 list_head \u7684\u3002<\/strong><\/div>\n\u5982\u4e0a\u6240\u8ff0\uff0c\u5728\u5185\u6838\u91cc\u6709\u5f88\u591a\u5f88\u591a\u4e0d\u540c\u7684\u5730\u65b9\u90fd\u7528\u5230\u4e86\u94fe\u8868\u3002\u6211\u4eec\u6765\u770b\u4e00\u4e2a\u5728\u6742\u9879\u5b57\u7b26\u9a71\u52a8\u91cc\u9762\u7684\u4f7f\u7528\u7684\u4f8b\u5b50\u3002\u5728 drivers\/char\/misc.c \u7684\u6742\u9879\u5b57\u7b26\u9a71\u52a8 API \u88ab\u7528\u6765\u7f16\u5199\u5904\u7406\u5c0f\u578b\u786c\u4ef6\u6216\u865a\u62df\u8bbe\u5907\u7684\u5c0f\u9a71\u52a8\u3002\u8fd9\u4e9b\u9a71\u52a8\u5171\u4eab\u76f8\u540c\u7684\u4e3b\u8bbe\u5907\u53f7\uff1a<\/p>\n #define MISC_MAJOR 10<\/pre>\n\u4f46\u662f\u90fd\u6709\u5404\u81ea\u4e0d\u540c\u7684\u6b21\u8bbe\u5907\u53f7\u3002<\/strong><\/div>\n\u6bd4\u5982\uff1a<\/strong><\/span><\/div>\nls -l \/dev | grep 10\r\ncrw------- 1 root root 10, 235 Mar 21 12:01 autofs\r\ndrwxr-xr-x 10 root root 200 Mar 21 12:01 cpu\r\ncrw------- 1 root root 10, 62 Mar 21 12:01 cpu_dma_latency\r\ncrw------- 1 root root 10, 203 Mar 21 12:01 cuse\r\ndrwxr-xr-x 2 root root 100 Mar 21 12:01 dri\r\ncrw-rw-rw- 1 root root 10, 229 Mar 21 12:01 fuse\r\ncrw------- 1 root root 10, 228 Mar 21 12:01 hpet\r\ncrw------- 1 root root 10, 183 Mar 21 12:01 hwrng\r\ncrw-rw----+ 1 root kvm 10, 232 Mar 21 12:01 kvm\r\ncrw-rw---- 1 root disk 10, 237 Mar 21 12:01 loop-control\r\ncrw------- 1 root root 10, 227 Mar 21 12:01 mcelog\r\ncrw------- 1 root root 10, 59 Mar 21 12:01 memory_bandwidth\r\ncrw------- 1 root root 10, 61 Mar 21 12:01 network_latency\r\ncrw------- 1 root root 10, 60 Mar 21 12:01 network_throughput\r\ncrw-r----- 1 root kmem 10, 144 Mar 21 12:01 nvram\r\nbrw-rw---- 1 root disk 1, 10 Mar 21 12:01 ram10\r\ncrw--w---- 1 root tty 4, 10 Mar 21 12:01 tty10\r\ncrw-rw---- 1 root dialout 4, 74 Mar 21 12:01 ttyS10\r\ncrw------- 1 root root 10, 63 Mar 21 12:01 vga_arbiter\r\ncrw------- 1 root root 10, 137 Mar 21 12:01 vhci<\/pre>\n\u73b0\u5728\u8ba9\u6211\u4eec\u770b\u770b\u5b83\u662f\u5982\u4f55\u4f7f\u7528\u94fe\u8868\u7684\u3002\u9996\u5148\u770b\u4e00\u4e0b\u7ed3\u6784\u4f53 miscdevice\uff1a<\/strong><\/div>\nstruct miscdevice\r\n{\r\nint minor;\r\nconst char *name;\r\nconst struct file_operations *fops;\r\nstruct list_head list;\r\nstruct device *parent;\r\nstruct device *this_device;\r\nconst char *nodename;\r\nmode_t mode;\r\n};<\/pre>\n\u53ef\u4ee5\u770b\u5230\u7ed3\u6784\u4f53miscdevice\u7684\u7b2c\u56db\u4e2a\u53d8\u91cflist \u662f\u6240\u6709\u6ce8\u518c\u8fc7\u7684\u8bbe\u5907\u7684\u94fe\u8868\u3002<\/strong><\/div>\n\u5728\u6e90\u4ee3\u7801\u6587\u4ef6\u7684\u5f00\u59cb\u53ef\u4ee5\u770b\u5230\u8fd9\u4e2a\u94fe\u8868\u7684\u5b9a\u4e49\uff1a<\/p>\n static LIST_HEAD(misc_list);<\/pre>\n\u5b83\u5b9e\u9645\u4e0a\u662f\u5bf9\u7528list_head \u7c7b\u578b\u5b9a\u4e49\u7684\u53d8\u91cf\u7684\u6269\u5c55\u3002<\/p>\n #define LIST_HEAD(name) \\\r\nstruct list_head name = LIST_HEAD_INIT(name)<\/pre>\n\u7136\u540e\u4f7f\u7528\u5b8f LIST_HEAD_INIT \u8fdb\u884c\u521d\u59cb\u5316\uff0c<\/strong><\/div>\n\u8fd9\u4f1a\u4f7f\u7528\u53d8\u91cfname \u7684\u5730\u5740\u6765\u586b\u5145prev\u548cnext \u7ed3\u6784\u4f53\u7684\u4e24\u4e2a\u53d8\u91cf\u3002<\/p>\n #define LIST_HEAD_INIT(name) { &(name), &(name) }<\/pre>\n\u73b0\u5728\u6765\u770b\u770b\u6ce8\u518c\u6742\u9879\u8bbe\u5907\u7684\u51fd\u6570misc_register\u3002<\/strong><\/div>\n\u5b83\u5728\u4e00\u5f00\u59cb\u5c31\u7528\u51fd\u6570 INIT_LIST_HEAD \u521d\u59cb\u5316\u4e86miscdevice->list\u3002<\/p>\n INIT_LIST_HEAD(&misc->list);<\/pre>\n\u4f5c\u7528\u548c\u5b8fLIST_HEAD_INIT\u4e00\u6837\u3002<\/strong><\/div>\nstatic inline void INIT_LIST_HEAD(struct list_head *list)\r\n{\r\nlist->next = list;\r\nlist->prev = list;\r\n}<\/pre>\n\u63a5\u4e0b\u6765\uff0c\u5728\u51fd\u6570device_create \u521b\u5efa\u4e86\u8bbe\u5907\u540e\uff0c<\/strong><\/div>\n\u6211\u4eec\u5c31\u7528\u4e0b\u9762\u7684\u8bed\u53e5\u5c06\u8bbe\u5907\u6dfb\u52a0\u5230\u8bbe\u5907\u94fe\u8868\uff1a<\/p>\n list_add(&misc->list, &misc_list);<\/pre>\n\u5185\u6838\u6587\u4ef6list.h \u63d0\u4f9b\u4e86\u5411\u94fe\u8868\u6dfb\u52a0\u65b0\u9879\u7684 API \u63a5\u53e3\u3002<\/strong><\/div>\n\u6211\u4eec\u6765\u770b\u770b\u5b83\u7684\u5b9e\u73b0\uff1a<\/p>\n static inline void list_add(struct list_head *new, struct list_head *head)\r\n{\r\n__list_add(new, head, head->next);\r\n}<\/pre>\n\u5b9e\u9645\u4e0a\u5c31\u662f\u4f7f\u75283\u4e2a\u6307\u5b9a\u7684\u53c2\u6570\u6765\u8c03\u7528\u4e86\u5185\u90e8\u51fd\u6570__list_add\uff1a \n<\/strong><\/div>\nnew - \u65b0\u9879\u3002 \nhead - \u65b0\u9879\u5c06\u4f1a\u63d2\u5728head\u7684\u540e\u9762 \nhead->next - \u63d2\u5165\u524d\uff0chead \u540e\u9762\u7684\u9879\u3002 \n__list_add\u7684\u5b9e\u73b0\u975e\u5e38\u7b80\u5355\uff1a<\/p>\n static inline void __list_add(struct list_head *new,\r\nstruct list_head *prev,\r\nstruct list_head *next)\r\n{\r\nnext->prev = new;\r\nnew->next = next;\r\nnew->prev = prev;\r\nprev->next = new;\r\n}<\/pre>\n\u8fd9\u91cc\uff0c\u6211\u4eec\u5728prev\u548cnext \u4e4b\u95f4\u6dfb\u52a0\u4e86\u4e00\u4e2a\u65b0\u9879\u3002<\/strong><\/div>\n\u6240\u4ee5\u6211\u4eec\u5f00\u59cb\u65f6\u7528\u5b8fLIST_HEAD_INIT\u5b9a\u4e49\u7684misc \u94fe\u8868\u4f1a\u5305\u542b\u6307\u5411miscdevice->list \u7684\u5411\u524d\u6307\u9488\u548c\u5411\u540e\u6307\u9488\u3002 \n\u8fd9\u513f\u8fd8\u6709\u4e00\u4e2a\u95ee\u9898\uff1a\u5982\u4f55\u5f97\u5230\u5217\u8868\u7684\u5185\u5bb9\u5462\uff1f\u8fd9\u91cc\u6709\u4e00\u4e2a\u7279\u6b8a\u7684\u5b8f\uff1a<\/p>\n #define list_entry(ptr, type, member) \\\r\ncontainer_of(ptr, type, member)<\/pre>\n\u4f7f\u7528\u4e86\u4e09\u4e2a\u53c2\u6570\uff1a<\/strong><\/div>\nptr - \u6307\u5411\u7ed3\u6784 list_head \u7684\u6307\u9488\uff1b \ntype - \u7ed3\u6784\u4f53\u7c7b\u578b; \nmember - \u5728\u7ed3\u6784\u4f53\u5185\u7c7b\u578b\u4e3alist_head \u7684\u53d8\u91cf\u7684\u540d\u5b57\uff1b<\/p>\n \u6bd4\u5982\uff1a<\/strong><\/span><\/div>\nconst struct miscdevice *p = list_entry(v, struct miscdevice, list)<\/pre>\n\u7136\u540e\u6211\u4eec\u5c31\u53ef\u4ee5\u4f7f\u7528p->minor \u6216\u8005 p->name\u6765\u8bbf\u95eemiscdevice\u3002\u8ba9\u6211\u4eec\u6765\u770b\u770blist_entry \u7684\u5b9e\u73b0\uff1a<\/p>\n #define list_entry(ptr, type, member) \\\r\ncontainer_of(ptr, type, member)<\/pre>\n\u5982\u6211\u4eec\u6240\u89c1\uff0c\u5b83\u4ec5\u4ec5\u4f7f\u7528\u76f8\u540c\u7684\u53c2\u6570\u8c03\u7528\u4e86\u5b8fcontainer_of\u3002\u521d\u770b\u8fd9\u4e2a\u5b8f\u633a\u5947\u602a\u7684\uff1a<\/p>\n #define container_of(ptr, type, member) ({ \\\r\nconst typeof( ((type *)0)->member ) *__mptr = (ptr); \\\r\n(type *)( (char *)__mptr - offsetof(type,member) );})<\/pre>\n |