21 November 2012

Линус делится передовым опытом

Папа ОС Linux и git делится с общественностью передовыми методологиями программирования:

"git actually has a simple design, with stable and reasonably well-documented data structures. In fact, I'm a huge proponent of designing your code around the data, rather than the other way around, and I think it's one of the reasons git has been fairly successful […] I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships."


Куда ведет этот путь? Очевидно, к такому вот коду, который легко читается, надежен, и который очень легко сопровождать.

struct sk_buff {
 /* These two members must be first. */
 struct sk_buff  *next;
 struct sk_buff  *prev;

 struct sk_buff_head *list;
 struct sock  *sk;
 struct timeval  stamp;
 struct net_device *dev;
 struct net_device *input_dev;
 struct net_device *real_dev;

 union {
  struct tcphdr *th;
  struct udphdr *uh;
  struct icmphdr *icmph;
  struct igmphdr *igmph;
  struct iphdr *ipiph;
  struct ipv6hdr *ipv6h;
  unsigned char *raw;
 } h;

 union {
  struct iphdr *iph;
  struct ipv6hdr *ipv6h;
  struct arphdr *arph;
  unsigned char *raw;
 } nh;

 union {
    unsigned char  *raw;
 } mac;

 struct  dst_entry *dst;
 struct sec_path *sp;

 /*
  * This is the control buffer. It is free to use for every
  * layer. Please put your private variables there. If you
  * want to keep them across layers you have to do a skb_clone()
  * first. This is owned by whoever has the skb queued ATM.
  */
 char   cb[40];

 unsigned int  len,
    data_len,
    mac_len,
    csum;
 unsigned char  local_df,
    cloned,
    pkt_type,
    ip_summed;
 __u32   priority;
 unsigned short  protocol,
    security;

 void   (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
        unsigned long  nfmark;
 __u32   nfcache;
 __u32   nfctinfo;
 struct nf_conntrack *nfct;
#ifdef CONFIG_NETFILTER_DEBUG
        unsigned int  nf_debug;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
 struct nf_bridge_info *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
#if defined(CONFIG_HIPPI)
 union {
  __u32  ifield;
 } private;
#endif
#ifdef CONFIG_NET_SCHED
       __u32   tc_index;        /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
 __u32           tc_verd;               /* traffic control verdict */
 __u32           tc_classid;            /* traffic control classid */
#endif

#endif


 /* These elements must be at the end, see alloc_skb() for details.  */
 unsigned int  truesize;
 atomic_t  users;
 unsigned char  *head,
    *data,
    *tail,
    *end;
}; 

И, разумеется, все вокруг точно такое же. Взять тот же net_device -- компактная, очень понятная структура. 

struct net_device
{

 /*
  * This is the first field of the "visible" part of this structure
  * (i.e. as seen by users in the "Space.c" file).  It is the name
  * the interface.
  */
 char   name[IFNAMSIZ];
 /* device name hash chain */
 struct hlist_node name_hlist;

 /*
  * I/O specific fields
  * FIXME: Merge these and struct ifmap into one
  */
 unsigned long  mem_end; /* shared mem end */
 unsigned long  mem_start; /* shared mem start */
 unsigned long  base_addr; /* device I/O address */
 unsigned int  irq;  /* device IRQ number */

 /*
  * Some hardware also needs these fields, but they are not
  * part of the usual set specified in Space.c.
  */

 unsigned char  if_port; /* Selectable AUI, TP,..*/
 unsigned char  dma;  /* DMA channel  */

 unsigned long  state;

 struct list_head dev_list;
 
 /* The device initialization function. Called only once. */
 int   (*init)(struct net_device *dev);

 /* ------- Fields preinitialized in Space.c finish here ------- */

 /* Net device features */
 unsigned long  features;
#define NETIF_F_SG  1 /* Scatter/gather IO. */
#define NETIF_F_IP_CSUM  2 /* Can checksum TCP/UDP over IPv4. */
#define NETIF_F_NO_CSUM  4 /* Does not require checksum. F.e. loopack. */
#define NETIF_F_HW_CSUM  8 /* Can checksum all the packets. */
#define NETIF_F_IPV6_CSUM 16 /* Can checksum TCP/UDP over IPV6 */
#define NETIF_F_HIGHDMA  32 /* Can DMA to high memory. */
#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */
#define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */
#define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_GSO  2048 /* Enable software GSO. */
#define NETIF_F_LLTX  4096 /* LockLess TX */
#define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */

 /* Segmentation offload features */
#define NETIF_F_GSO_SHIFT 16
#define NETIF_F_GSO_MASK 0xffff0000
#define NETIF_F_TSO  (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO  (SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO_ECN  (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO6  (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)

 /* List of features with software fallbacks. */
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)


#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
#define NETIF_F_V4_CSUM  (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
#define NETIF_F_V6_CSUM  (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)

 struct net_device *next_sched;

 /* Interface index. Unique device identifier */
 int   ifindex;
 int   iflink;


 struct net_device_stats* (*get_stats)(struct net_device *dev);
 struct net_device_stats stats;

#ifdef CONFIG_WIRELESS_EXT
 /* List of functions to handle Wireless Extensions (instead of ioctl).
  * See <net/iw_handler.h> for details. Jean II */
 const struct iw_handler_def * wireless_handlers;
 /* Instance data managed by the core of Wireless Extensions. */
 struct iw_public_data * wireless_data;
#endif
 const struct ethtool_ops *ethtool_ops;

 /*
  * This marks the end of the "visible" part of the structure. All
  * fields hereafter are internal to the system, and may change at
  * will (read: may be cleaned up at will).
  */


 unsigned int  flags; /* interface flags (a la BSD) */
 unsigned short  gflags;
        unsigned short          priv_flags; /* Like 'flags' but invisible to userspace. */
 unsigned short  padded; /* How much padding added by alloc_netdev() */

 unsigned char  operstate; /* RFC2863 operstate */
 unsigned char  link_mode; /* mapping policy to operstate */

 unsigned  mtu; /* interface MTU value  */
 unsigned short  type; /* interface hardware type */
 unsigned short  hard_header_len; /* hardware hdr length */

 struct net_device *master; /* Pointer to master device of a group,
       * which this device is member of.
       */

 /* Interface address info. */
 unsigned char  perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
 unsigned char  addr_len; /* hardware address length */
 unsigned short          dev_id;  /* for shared network cards */

 struct dev_addr_list *uc_list; /* Secondary unicast mac addresses */
 int   uc_count; /* Number of installed ucasts */
 int   uc_promisc;
 struct dev_addr_list *mc_list; /* Multicast mac addresses */
 int   mc_count; /* Number of installed mcasts */
 int   promiscuity;
 int   allmulti;


 /* Protocol specific pointers */
 
 void    *atalk_ptr; /* AppleTalk link  */
 void   *ip_ptr; /* IPv4 specific data */  
 void                    *dn_ptr;        /* DECnet specific data */
 void                    *ip6_ptr;       /* IPv6 specific data */
 void   *ec_ptr; /* Econet specific data */
 void   *ax25_ptr; /* AX.25 specific data */
 struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
         assign before registering */

/*
 * Cache line mostly used on receive path (including eth_type_trans())
 */
 struct list_head poll_list ____cacheline_aligned_in_smp;
     /* Link to poll list */

 int   (*poll) (struct net_device *dev, int *quota);
 int   quota;
 int   weight;
 unsigned long  last_rx; /* Time of last Rx */
 /* Interface address info used in eth_type_trans() */
 unsigned char  dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast 
       because most packets are unicast) */

 unsigned char  broadcast[MAX_ADDR_LEN]; /* hw bcast add */

/*
 * Cache line mostly used on queue transmit path (qdisc)
 */
 /* device queue lock */
 spinlock_t  queue_lock ____cacheline_aligned_in_smp;
 struct Qdisc  *qdisc;
 struct Qdisc  *qdisc_sleeping;
 struct list_head qdisc_list;
 unsigned long  tx_queue_len; /* Max frames per queue allowed */

 /* Partially transmitted GSO packet. */
 struct sk_buff  *gso_skb;

 /* ingress path synchronizer */
 spinlock_t  ingress_lock;
 struct Qdisc  *qdisc_ingress;

/*
 * One part is mostly used on xmit path (device)
 */
 /* hard_start_xmit synchronizer */
 spinlock_t  _xmit_lock ____cacheline_aligned_in_smp;
 /* cpu id of processor entered to hard_start_xmit or -1,
    if nobody entered there.
  */
 int   xmit_lock_owner;
 void   *priv; /* pointer to private data */
 int   (*hard_start_xmit) (struct sk_buff *skb,
          struct net_device *dev);
 /* These may be needed for future network-power-down code. */
 unsigned long  trans_start; /* Time (in jiffies) of last Tx */

 int   watchdog_timeo; /* used by dev_watchdog() */
 struct timer_list watchdog_timer;

/*
 * refcnt is a very hot point, so align it on SMP
 */
 /* Number of references to this device */
 atomic_t  refcnt ____cacheline_aligned_in_smp;

 /* delayed register/unregister */
 struct list_head todo_list;
 /* device index hash chain */
 struct hlist_node index_hlist;

 struct net_device *link_watch_next;

 /* register/unregister state machine */
 enum { NETREG_UNINITIALIZED=0,
        NETREG_REGISTERED, /* completed register_netdevice */
        NETREG_UNREGISTERING, /* called unregister_netdevice */
        NETREG_UNREGISTERED, /* completed unregister todo */
        NETREG_RELEASED,  /* called free_netdev */
 } reg_state;

 /* Called after device is detached from network. */
 void   (*uninit)(struct net_device *dev);
 /* Called after last user reference disappears. */
 void   (*destructor)(struct net_device *dev);

 /* Pointers to interface service routines. */
 int   (*open)(struct net_device *dev);
 int   (*stop)(struct net_device *dev);
#define HAVE_NETDEV_POLL
 int   (*hard_header) (struct sk_buff *skb,
      struct net_device *dev,
      unsigned short type,
      void *daddr,
      void *saddr,
      unsigned len);
 int   (*rebuild_header)(struct sk_buff *skb);
#define HAVE_CHANGE_RX_FLAGS
 void   (*change_rx_flags)(struct net_device *dev,
         int flags);
#define HAVE_SET_RX_MODE
 void   (*set_rx_mode)(struct net_device *dev);
#define HAVE_MULTICAST    
 void   (*set_multicast_list)(struct net_device *dev);
#define HAVE_SET_MAC_ADDR     
 int   (*set_mac_address)(struct net_device *dev,
         void *addr);
#define HAVE_PRIVATE_IOCTL
 int   (*do_ioctl)(struct net_device *dev,
         struct ifreq *ifr, int cmd);
#define HAVE_SET_CONFIG
 int   (*set_config)(struct net_device *dev,
           struct ifmap *map);
#define HAVE_HEADER_CACHE
 int   (*hard_header_cache)(struct neighbour *neigh,
           struct hh_cache *hh);
 void   (*header_cache_update)(struct hh_cache *hh,
             struct net_device *dev,
             unsigned char *  haddr);
#define HAVE_CHANGE_MTU
 int   (*change_mtu)(struct net_device *dev, int new_mtu);

#define HAVE_TX_TIMEOUT
 void   (*tx_timeout) (struct net_device *dev);

 void   (*vlan_rx_register)(struct net_device *dev,
          struct vlan_group *grp);
 void   (*vlan_rx_add_vid)(struct net_device *dev,
         unsigned short vid);
 void   (*vlan_rx_kill_vid)(struct net_device *dev,
          unsigned short vid);

 int   (*hard_header_parse)(struct sk_buff *skb,
           unsigned char *haddr);
 int   (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
#ifdef CONFIG_NETPOLL
 struct netpoll_info *npinfo;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
 void                    (*poll_controller)(struct net_device *dev);
#endif

 /* bridge stuff */
 struct net_bridge_port *br_port;
 /* macvlan */
 struct macvlan_port *macvlan_port;

 /* class/net/name entry */
 struct device  dev;
 /* space for optional statistics and wireless sysfs groups */
 struct attribute_group  *sysfs_groups[3];

 /* rtnetlink link ops */
 const struct rtnl_link_ops *rtnl_link_ops;

 /* The TX queue control structures */
 unsigned int   egress_subqueue_count;
 struct net_device_subqueue egress_subqueue[1];
};

Читаю такой код и наслаждаюсь. 

No comments:

Post a Comment