• 代码示例_网络编程_select_内核链表


    select_list


     1.头文件

     1 #pragma once
     2 
     3 #include <stdio.h>
     4 #include <stdlib.h>
     5 #include <sys/types.h>
     6 #include <sys/select.h>
     7 #include <sys/time.h>
     8 #include <sys/socket.h>
     9 #include <strings.h>
    10 #include <string.h>
    11 #include <arpa/inet.h>
    12 #include "list.h"
    13 
    14 #define IP "192.168.2.150"
    15 #define PORT 9999
    16 #define SIZE 128
    17 
    18 struct cli_info
    19 {
    20     struct list_head list;
    21     int cli_fd;
    22 };

    2.client_delect.c

     1 #include "net.h"
     2 
     3 int main(void)
     4 {
     5     //1.创建套接字
     6     int fd = socket(AF_INET,SOCK_STREAM,0);
     7     if(fd<0){
     8         perror("socket failed");
     9         exit(1);
    10     }
    11 
    12 
    13     //2.初始服务器地址
    14     struct sockaddr_in cli;
    15     cli.sin_family = AF_INET;
    16     cli.sin_port = htons(PORT);
    17     cli.sin_addr.s_addr=inet_addr(IP);
    18 
    19 
    20     //3.发送连接请求
    21     if(  connect(fd,(struct sockaddr*)&cli,sizeof(cli))<0  ){
    22         perror("connect failed");
    23         exit(1);
    24     }
    25 
    26 
    27     //4.写
    28     char buf[SIZE];
    29     while(1){
    30     bzero(buf,SIZE);
    31     printf("please input:	");
    32     fgets(buf,SIZE,stdin);
    33     write(fd,buf,strlen(buf));
    34         if(!strncmp(buf,"quit",4))
    35             break;
    36     }
    37 
    38 
    39     //5.关闭
    40     close(fd);
    41 
    42 
    43     return 0 ;
    44 }

    3.server_select.c

      1 #include "net.h"
      2 
      3 int main(void)
      4 {
      5     char buf[SIZE];
      6     int newfd = -1;
      7 
      8 
      9     //*****定义初始头结点
     10     struct cli_info head;
     11     INIT_LIST_HEAD(&head.list);
     12 
     13 
     14     //1.创建套接字
     15     int fd = socket(AF_INET,SOCK_STREAM,0);
     16     if(fd<0){
     17         perror("socket failed");
     18         exit(1);
     19     }
     20 
     21 
     22     //2.初始本地地址
     23     struct sockaddr_in ser;
     24     bzero(&ser,sizeof(ser));
     25     ser.sin_family = AF_INET;
     26     ser.sin_port = htons(PORT);
     27     ser.sin_addr.s_addr=htonl(INADDR_ANY);
     28 
     29 
     30     //3.绑定
     31     if(  bind(fd,(struct sockaddr*)&ser,sizeof(ser))<0  ){
     32         perror("bind failed");
     33         exit(1);
     34     }
     35 
     36 
     37     //4.监听
     38     if(  listen(fd,5)<0  ){
     39         perror("listen failed");
     40         exit(1);
     41     }
     42 
     43     int len = sizeof(ser);
     44     int maxfd = -1;
     45 
     46     //5.多路复用
     47     fd_set read_fds;    //定义读集合
     48     FD_ZERO(&read_fds); //清空读集合
     49     maxfd = fd;            //最大描述符
     50 
     51 
     52     //*****
     53     struct cli_info *cur=NULL;
     54     struct list_head *ptr,*q;
     55 
     56 
     57     //6.加入监听处理 读集合
     58     while(1){
     59     FD_SET(0,&read_fds);  //将标准输入加入读集合
     60     FD_SET(fd,&read_fds); //将fd加入读集合
     61     maxfd = fd;              //表示最大读集合
     62 
     63 #if 0
     64     if(maxfd < newfd){
     65         FD_SET(newfd,&read_fds);
     66         maxfd=newfd;
     67     }
     68 #endif
     69     
     70     //*****将文件描述符加入到读集合
     71     list_for_each(ptr,&head.list){
     72         cur = list_entry(ptr,struct cli_info,list);
     73         FD_SET(cur->cli_fd,&read_fds);
     74         if(maxfd<cur->cli_fd)
     75         maxfd = cur->cli_fd;
     76     }
     77 
     78 
     79     int ret = select(maxfd+1,&read_fds,NULL,NULL,NULL);
     80     if(ret<0){
     81         perror("select failed");
     82         exit(1);
     83     }
     84     else if(ret==0){
     85         perror("time out");
     86         exit(1);
     87     }
     88     else{
     89         //6.1 判断输入端是否有相应
     90         if(FD_ISSET(0,&read_fds)){
     91             bzero(buf,SIZE);
     92             fgets(buf,SIZE,stdin);
     93             printf("shell :%s",buf);
     94         }
     95 
     96 
     97         //6.2 判断客户端是否有相应
     98         if(FD_ISSET(fd,&read_fds)){
     99             //*****给新节点申请空间
    100             struct cli_info *temp=(struct cli_info*)malloc(sizeof(struct cli_info));
    101             if(temp==NULL){
    102                 perror("malloc failed");
    103                 exit(1);
    104             }
    105             //接收
    106             newfd=accept(fd,(struct sockaddr*)&ser,&len);
    107             if(newfd<0){
    108                 perror("accept failed");
    109                 exit(1);
    110             }
    111             printf("client connect succsee :  ip=%s   port=%d  用户上线啦 ^.^ ...
    ",inet_ntoa(ser.sin_addr),ntohs(ser.sin_port));
    112             //*****将连接的新客户文件描述符加入到新节点
    113             temp->cli_fd=newfd;
    114             //*****把新节点插入到链表
    115             list_add(&temp->list,&head.list);
    116             }
    117 
    118 
    119         //6.3 判断客户端是否有数据
    120         list_for_each_safe(ptr,q,&head.list){
    121             cur = list_entry(ptr,struct cli_info,list);
    122             if(FD_ISSET(cur->cli_fd,&read_fds)){
    123                 bzero(buf,SIZE);
    124                 int val = read(cur->cli_fd,buf,SIZE);
    125                 if(val<0){
    126                     perror("read failed");
    127                     exit(1);
    128                 }
    129                 else if(val==0){
    130                 FD_CLR(cur->cli_fd,&read_fds);
    131                 list_del(&cur->list);
    132                 close(cur->cli_fd);
    133                 free(cur);
    134                 cur->cli_fd = -1;
    135                 }
    136                 else{
    137                     printf("client info :
    ip=%s  port=%d
    data=%s
    ",inet_ntoa(ser.sin_addr),ntohs(ser.sin_port),buf);
    138                     if(!strncmp(buf,"quit",4))
    139                         printf("client info :
    ip=%s  port=%d  用户下线啦 ^.^ ...
    ",inet_ntoa(ser.sin_addr),ntohs(ser.sin_port));
    140 
    141 }   
    142             }
    143             }    
    144         }
    145         }
    146 
    147 
    148     return 0 ;
    149 }

    4.list.h

      1 #ifndef _LINUX_LIST_H
      2 #define _LINUX_LIST_H
      3 
      4 /*
      5  * Simple doubly linked list implementation.
      6  *
      7  * Some of the internal functions ("__xxx") are useful when
      8  * manipulating whole lists rather than single entries, as
      9  * sometimes we already know the next/prev entries and we can
     10  * generate better code by using them directly rather than
     11  * using the generic single-entry routines.
     12  */
     13 
     14 struct list_head{
     15     struct list_head *next,*prev;
     16 };
     17 
     18 #define LIST_POISON1  ((void *) 0x00100100 + 0)
     19 #define LIST_POISON2  ((void *) 0x00200200 + 0)
     20 
     21 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
     22 #define container_of(ptr, type, member) ({            
     23         const typeof( ((type *)0)->member ) *__mptr = (ptr);    
     24         (type *)( (char *)__mptr - offsetof(type,member) );})
     25 #define LIST_HEAD_INIT(name) { &(name), &(name) }
     26 
     27 #define LIST_HEAD(name) 
     28     struct list_head name = LIST_HEAD_INIT(name)
     29 
     30 static inline void INIT_LIST_HEAD(struct list_head *list)
     31 {
     32     list->next = list;
     33     list->prev = list;
     34 }
     35 
     36 /*
     37  * Insert a new entry between two known consecutive entries.
     38  *
     39  * This is only for internal list manipulation where we know
     40  * the prev/next entries already!
     41  */
     42 #ifndef CONFIG_DEBUG_LIST
     43 static inline void __list_add(struct list_head *new,
     44         struct list_head *prev,
     45         struct list_head *next)
     46 {
     47     next->prev = new;
     48     new->next = next;
     49     new->prev = prev;
     50     prev->next = new;
     51 }
     52 #else
     53 extern void __list_add(struct list_head *new,
     54         struct list_head *prev,
     55         struct list_head *next);
     56 #endif
     57 
     58 /**
     59  * list_add - add a new entry
     60  * @new: new entry to be added
     61  * @head: list head to add it after
     62  *
     63  * Insert a new entry after the specified head.
     64  * This is good for implementing stacks.
     65  */
     66 static inline void list_add(struct list_head *new, struct list_head *head)
     67 {
     68     __list_add(new, head, head->next);
     69 }
     70 
     71 
     72 /**
     73  * list_add_tail - add a new entry
     74  * @new: new entry to be added
     75  * @head: list head to add it before
     76  *
     77  * Insert a new entry before the specified head.
     78  * This is useful for implementing queues.
     79  */
     80 static inline void list_add_tail(struct list_head *new, struct list_head *head)
     81 {
     82     __list_add(new, head->prev, head);
     83 }
     84 
     85 /*
     86  * Delete a list entry by making the prev/next entries
     87  * point to each other.
     88  *
     89  * This is only for internal list manipulation where we know
     90  * the prev/next entries already!
     91  */
     92 static inline void __list_del(struct list_head * prev, struct list_head * next)
     93 {
     94     next->prev = prev;
     95     prev->next = next;
     96 }
     97 
     98 /**
     99  * list_del - deletes entry from list.
    100  * @entry: the element to delete from the list.
    101  * Note: list_empty() on entry does not return true after this, the entry is
    102  * in an undefined state.
    103  */
    104 #ifndef CONFIG_DEBUG_LIST
    105 static inline void __list_del_entry(struct list_head *entry)
    106 {
    107     __list_del(entry->prev, entry->next);
    108 }
    109 
    110 static inline void list_del(struct list_head *entry)
    111 {
    112     __list_del(entry->prev, entry->next);
    113     entry->next = LIST_POISON1;
    114     entry->prev = LIST_POISON2;
    115 }
    116 #else
    117 extern void __list_del_entry(struct list_head *entry);
    118 extern void list_del(struct list_head *entry);
    119 #endif
    120 
    121 /**
    122  * list_replace - replace old entry by new one
    123  * @old : the element to be replaced
    124  * @new : the new element to insert
    125  *
    126  * If @old was empty, it will be overwritten.
    127  */
    128 static inline void list_replace(struct list_head *old,
    129         struct list_head *new)
    130 {
    131     new->next = old->next;
    132     new->next->prev = new;
    133     new->prev = old->prev;
    134     new->prev->next = new;
    135 }
    136 
    137 static inline void list_replace_init(struct list_head *old,
    138         struct list_head *new)
    139 {
    140     list_replace(old, new);
    141     INIT_LIST_HEAD(old);
    142 }
    143 
    144 /**
    145  * list_del_init - deletes entry from list and reinitialize it.
    146  * @entry: the element to delete from the list.
    147  */
    148 static inline void list_del_init(struct list_head *entry)
    149 {
    150     __list_del_entry(entry);
    151     INIT_LIST_HEAD(entry);
    152 }
    153 
    154 /**
    155  * list_move - delete from one list and add as another's head
    156  * @list: the entry to move
    157  * @head: the head that will precede our entry
    158  */
    159 static inline void list_move(struct list_head *list, struct list_head *head)
    160 {
    161     __list_del_entry(list);
    162     list_add(list, head);
    163 }
    164 
    165 /**
    166  * list_move_tail - delete from one list and add as another's tail
    167  * @list: the entry to move
    168  * @head: the head that will follow our entry
    169  */
    170 static inline void list_move_tail(struct list_head *list,
    171         struct list_head *head)
    172 {
    173     __list_del_entry(list);
    174     list_add_tail(list, head);
    175 }
    176 
    177 /**
    178  * list_is_last - tests whether @list is the last entry in list @head
    179  * @list: the entry to test
    180  * @head: the head of the list
    181  */
    182 static inline int list_is_last(const struct list_head *list,
    183         const struct list_head *head)
    184 {
    185     return list->next == head;
    186 }
    187 
    188 /**
    189  * list_empty - tests whether a list is empty
    190  * @head: the list to test.
    191  */
    192 static inline int list_empty(const struct list_head *head)
    193 {
    194     return head->next == head;
    195 }
    196 
    197 /**
    198  * list_empty_careful - tests whether a list is empty and not being modified
    199  * @head: the list to test
    200  *
    201  * Description:
    202  * tests whether a list is empty _and_ checks that no other CPU might be
    203  * in the process of modifying either member (next or prev)
    204  *
    205  * NOTE: using list_empty_careful() without synchronization
    206  * can only be safe if the only activity that can happen
    207  * to the list entry is list_del_init(). Eg. it cannot be used
    208  * if another CPU could re-list_add() it.
    209  */
    210 static inline int list_empty_careful(const struct list_head *head)
    211 {
    212     struct list_head *next = head->next;
    213     return (next == head) && (next == head->prev);
    214 }
    215 
    216 /**
    217  * list_rotate_left - rotate the list to the left
    218  * @head: the head of the list
    219  */
    220 static inline void list_rotate_left(struct list_head *head)
    221 {
    222     struct list_head *first;
    223 
    224     if (!list_empty(head)) {
    225         first = head->next;
    226         list_move_tail(first, head);
    227     }
    228 }
    229 
    230 /**
    231  * list_is_singular - tests whether a list has just one entry.
    232  * @head: the list to test.
    233  */
    234 static inline int list_is_singular(const struct list_head *head)
    235 {
    236     return !list_empty(head) && (head->next == head->prev);
    237 }
    238 
    239 static inline void __list_cut_position(struct list_head *list,
    240         struct list_head *head, struct list_head *entry)
    241 {
    242     struct list_head *new_first = entry->next;
    243     list->next = head->next;
    244     list->next->prev = list;
    245     list->prev = entry;
    246     entry->next = list;
    247     head->next = new_first;
    248     new_first->prev = head;
    249 }
    250 
    251 /**
    252  * list_cut_position - cut a list into two
    253  * @list: a new list to add all removed entries
    254  * @head: a list with entries
    255  * @entry: an entry within head, could be the head itself
    256  *    and if so we won't cut the list
    257  *
    258  * This helper moves the initial part of @head, up to and
    259  * including @entry, from @head to @list. You should
    260  * pass on @entry an element you know is on @head. @list
    261  * should be an empty list or a list you do not care about
    262  * losing its data.
    263  *
    264  */
    265 static inline void list_cut_position(struct list_head *list,
    266         struct list_head *head, struct list_head *entry)
    267 {
    268     if (list_empty(head))
    269         return;
    270     if (list_is_singular(head) &&
    271             (head->next != entry && head != entry))
    272         return;
    273     if (entry == head)
    274         INIT_LIST_HEAD(list);
    275     else
    276         __list_cut_position(list, head, entry);
    277 }
    278 
    279 static inline void __list_splice(const struct list_head *list,
    280         struct list_head *prev,
    281         struct list_head *next)
    282 {
    283     struct list_head *first = list->next;
    284     struct list_head *last = list->prev;
    285 
    286     first->prev = prev;
    287     prev->next = first;
    288 
    289     last->next = next;
    290     next->prev = last;
    291 }
    292 
    293 /**
    294  * list_splice - join two lists, this is designed for stacks
    295  * @list: the new list to add.
    296  * @head: the place to add it in the first list.
    297  */
    298 static inline void list_splice(const struct list_head *list,
    299         struct list_head *head)
    300 {
    301     if (!list_empty(list))
    302         __list_splice(list, head, head->next);
    303 }
    304 
    305 /**
    306  * list_splice_tail - join two lists, each list being a queue
    307  * @list: the new list to add.
    308  * @head: the place to add it in the first list.
    309  */
    310 static inline void list_splice_tail(struct list_head *list,
    311         struct list_head *head)
    312 {
    313     if (!list_empty(list))
    314         __list_splice(list, head->prev, head);
    315 }
    316 
    317 /**
    318  * list_splice_init - join two lists and reinitialise the emptied list.
    319  * @list: the new list to add.
    320  * @head: the place to add it in the first list.
    321  *
    322  * The list at @list is reinitialised
    323  */
    324 static inline void list_splice_init(struct list_head *list,
    325         struct list_head *head)
    326 {
    327     if (!list_empty(list)) {
    328         __list_splice(list, head, head->next);
    329         INIT_LIST_HEAD(list);
    330     }
    331 }
    332 
    333 /**
    334  * list_splice_tail_init - join two lists and reinitialise the emptied list
    335  * @list: the new list to add.
    336  * @head: the place to add it in the first list.
    337  *
    338  * Each of the lists is a queue.
    339  * The list at @list is reinitialised
    340  */
    341 static inline void list_splice_tail_init(struct list_head *list,
    342         struct list_head *head)
    343 {
    344     if (!list_empty(list)) {
    345         __list_splice(list, head->prev, head);
    346         INIT_LIST_HEAD(list);
    347     }
    348 }
    349 
    350 /**
    351  * list_entry - get the struct for this entry
    352  * @ptr:    the &struct list_head pointer.
    353  * @type:    the type of the struct this is embedded in.
    354  * @member:    the name of the list_struct within the struct.
    355  */
    356 #define list_entry(ptr, type, member) 
    357     container_of(ptr, type, member)
    358 
    359 /**
    360  * list_first_entry - get the first element from a list
    361  * @ptr:    the list head to take the element from.
    362  * @type:    the type of the struct this is embedded in.
    363  * @member:    the name of the list_struct within the struct.
    364  *
    365  * Note, that list is expected to be not empty.
    366  */
    367 #define list_first_entry(ptr, type, member) 
    368     list_entry((ptr)->next, type, member)
    369 
    370 /**
    371  * list_for_each    -    iterate over a list
    372  * @pos:    the &struct list_head to use as a loop cursor.
    373  * @head:    the head for your list.
    374  */
    375 #define list_for_each(pos, head) 
    376     for (pos = (head)->next; pos != (head); pos = pos->next)
    377 
    378 /**
    379  * __list_for_each    -    iterate over a list
    380  * @pos:    the &struct list_head to use as a loop cursor.
    381  * @head:    the head for your list.
    382  *
    383  * This variant doesn't differ from list_for_each() any more.
    384  * We don't do prefetching in either case.
    385  */
    386 #define __list_for_each(pos, head) 
    387     for (pos = (head)->next; pos != (head); pos = pos->next)
    388 
    389 /**
    390  * list_for_each_prev    -    iterate over a list backwards
    391  * @pos:    the &struct list_head to use as a loop cursor.
    392  * @head:    the head for your list.
    393  */
    394 #define list_for_each_prev(pos, head) 
    395     for (pos = (head)->prev; pos != (head); pos = pos->prev)
    396 
    397 /**
    398  * list_for_each_safe - iterate over a list safe against removal of list entry
    399  * @pos:    the &struct list_head to use as a loop cursor.
    400  * @n:        another &struct list_head to use as temporary storage
    401  * @head:    the head for your list.
    402  */
    403 #define list_for_each_safe(pos, n, head) 
    404     for (pos = (head)->next, n = pos->next; pos != (head); 
    405             pos = n, n = pos->next)
    406 
    407 /**
    408  * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
    409  * @pos:    the &struct list_head to use as a loop cursor.
    410  * @n:        another &struct list_head to use as temporary storage
    411  * @head:    the head for your list.
    412  */
    413 #define list_for_each_prev_safe(pos, n, head) 
    414     for (pos = (head)->prev, n = pos->prev; 
    415             pos != (head); 
    416             pos = n, n = pos->prev)
    417 
    418 /**
    419  * list_for_each_entry    -    iterate over list of given type
    420  * @pos:    the type * to use as a loop cursor.
    421  * @head:    the head for your list.
    422  * @member:    the name of the list_struct within the struct.
    423  */
    424 #define list_for_each_entry(pos, head, member)                
    425     for (pos = list_entry((head)->next, typeof(*pos), member);    
    426             &pos->member != (head);     
    427             pos = list_entry(pos->member.next, typeof(*pos), member))
    428 
    429 /**
    430  * list_for_each_entry_reverse - iterate backwards over list of given type.
    431  * @pos:    the type * to use as a loop cursor.
    432  * @head:    the head for your list.
    433  * @member:    the name of the list_struct within the struct.
    434  */
    435 #define list_for_each_entry_reverse(pos, head, member)            
    436     for (pos = list_entry((head)->prev, typeof(*pos), member);    
    437             &pos->member != (head);     
    438             pos = list_entry(pos->member.prev, typeof(*pos), member))
    439 
    440 /**
    441  * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
    442  * @pos:    the type * to use as a start point
    443  * @head:    the head of the list
    444  * @member:    the name of the list_struct within the struct.
    445  *
    446  * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
    447  */
    448 #define list_prepare_entry(pos, head, member) 
    449     ((pos) ? : list_entry(head, typeof(*pos), member))
    450 
    451 /**
    452  * list_for_each_entry_continue - continue iteration over list of given type
    453  * @pos:    the type * to use as a loop cursor.
    454  * @head:    the head for your list.
    455  * @member:    the name of the list_struct within the struct.
    456  *
    457  * Continue to iterate over list of given type, continuing after
    458  * the current position.
    459  */
    460 #define list_for_each_entry_continue(pos, head, member)         
    461     for (pos = list_entry(pos->member.next, typeof(*pos), member);    
    462             &pos->member != (head);    
    463             pos = list_entry(pos->member.next, typeof(*pos), member))
    464 
    465 /**
    466  * list_for_each_entry_continue_reverse - iterate backwards from the given point
    467  * @pos:    the type * to use as a loop cursor.
    468  * @head:    the head for your list.
    469  * @member:    the name of the list_struct within the struct.
    470  *
    471  * Start to iterate over list of given type backwards, continuing after
    472  * the current position.
    473  */
    474 #define list_for_each_entry_continue_reverse(pos, head, member)        
    475     for (pos = list_entry(pos->member.prev, typeof(*pos), member);    
    476             &pos->member != (head);    
    477             pos = list_entry(pos->member.prev, typeof(*pos), member))
    478 
    479 /**
    480  * list_for_each_entry_from - iterate over list of given type from the current point
    481  * @pos:    the type * to use as a loop cursor.
    482  * @head:    the head for your list.
    483  * @member:    the name of the list_struct within the struct.
    484  *
    485  * Iterate over list of given type, continuing from current position.
    486  */
    487 #define list_for_each_entry_from(pos, head, member)             
    488     for (; &pos->member != (head);    
    489             pos = list_entry(pos->member.next, typeof(*pos), member))
    490 
    491 /**
    492  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
    493  * @pos:    the type * to use as a loop cursor.
    494  * @n:        another type * to use as temporary storage
    495  * @head:    the head for your list.
    496  * @member:    the name of the list_struct within the struct.
    497  */
    498 #define list_for_each_entry_safe(pos, n, head, member)            
    499     for (pos = list_entry((head)->next, typeof(*pos), member),    
    500             n = list_entry(pos->member.next, typeof(*pos), member);    
    501             &pos->member != (head);                     
    502             pos = n, n = list_entry(n->member.next, typeof(*n), member))
    503 
    504 /**
    505  * list_for_each_entry_safe_continue - continue list iteration safe against removal
    506  * @pos:    the type * to use as a loop cursor.
    507  * @n:        another type * to use as temporary storage
    508  * @head:    the head for your list.
    509  * @member:    the name of the list_struct within the struct.
    510  *
    511  * Iterate over list of given type, continuing after current point,
    512  * safe against removal of list entry.
    513  */
    514 #define list_for_each_entry_safe_continue(pos, n, head, member)         
    515     for (pos = list_entry(pos->member.next, typeof(*pos), member),         
    516             n = list_entry(pos->member.next, typeof(*pos), member);        
    517             &pos->member != (head);                        
    518             pos = n, n = list_entry(n->member.next, typeof(*n), member))
    519 
    520 /**
    521  * list_for_each_entry_safe_from - iterate over list from current point safe against removal
    522  * @pos:    the type * to use as a loop cursor.
    523  * @n:        another type * to use as temporary storage
    524  * @head:    the head for your list.
    525  * @member:    the name of the list_struct within the struct.
    526  *
    527  * Iterate over list of given type from current point, safe against
    528  * removal of list entry.
    529  */
    530 #define list_for_each_entry_safe_from(pos, n, head, member)             
    531     for (n = list_entry(pos->member.next, typeof(*pos), member);        
    532             &pos->member != (head);                        
    533             pos = n, n = list_entry(n->member.next, typeof(*n), member))
    534 
    535 /**
    536  * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
    537  * @pos:    the type * to use as a loop cursor.
    538  * @n:        another type * to use as temporary storage
    539  * @head:    the head for your list.
    540  * @member:    the name of the list_struct within the struct.
    541  *
    542  * Iterate backwards over list of given type, safe against removal
    543  * of list entry.
    544  */
    545 #define list_for_each_entry_safe_reverse(pos, n, head, member)        
    546     for (pos = list_entry((head)->prev, typeof(*pos), member),    
    547             n = list_entry(pos->member.prev, typeof(*pos), member);    
    548             &pos->member != (head);                     
    549             pos = n, n = list_entry(n->member.prev, typeof(*n), member))
    550 
    551 /**
    552  * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
    553  * @pos:    the loop cursor used in the list_for_each_entry_safe loop
    554  * @n:        temporary storage used in list_for_each_entry_safe
    555  * @member:    the name of the list_struct within the struct.
    556  *
    557  * list_safe_reset_next is not safe to use in general if the list may be
    558  * modified concurrently (eg. the lock is dropped in the loop body). An
    559  * exception to this is if the cursor element (pos) is pinned in the list,
    560  * and list_safe_reset_next is called after re-taking the lock and before
    561  * completing the current iteration of the loop body.
    562  */
    563 #define list_safe_reset_next(pos, n, member)                
    564     n = list_entry(pos->member.next, typeof(*pos), member)
    565 
    566 /*
    567  * Double linked lists with a single pointer list head.
    568  * Mostly useful for hash tables where the two pointer list head is
    569  * too wasteful.
    570  * You lose the ability to access the tail in O(1).
    571  */
    572 #endif

    测试:


    success !

    Stay hungry, stay foolish 待续。。。
  • 相关阅读:
    2017-2018-2 20165207 实验四《Android开发基础》实验报告
    2017-2018-2 20165207 实验三《敏捷开发与XP实践》实验报告
    20165207 第九周学习总结
    20165328 实验四《Andriid应用开发》实验报告
    20165328 第十二周课上补做
    20165328 课下作业补做
    20165328 第九周学习总结
    2017-2018-2 20165328 实验三《敏捷开发与XP实践》实验报告
    20165328 结对编程第二周整体总结
    20165328课上补做
  • 原文地址:https://www.cnblogs.com/panda-w/p/11068140.html
Copyright © 2020-2023  润新知