Linux Wireless架构总结

1、无线网络驱动(ath9k_htc)

ath9k_htc是一个基于USB接口的SoftMAC无线网络适配器。为了其驱动能正常工作,首先必须调用usb_register来注册驱动定义的usb_driver,以借助USB Core的力量来处理与USB协议相关的事件。其代码如下:
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static struct usb_driver ath9k_hif_usb_driver = {    
  2.     .name = KBUILD_MODNAME,    
  3.     .probe = ath9k_hif_usb_probe,    
  4.     .disconnect = ath9k_hif_usb_disconnect,    
  5. #ifdef CONFIG_PM    
  6.     .suspend = ath9k_hif_usb_suspend,    
  7.     .resume = ath9k_hif_usb_resume,    
  8.     .reset_resume = ath9k_hif_usb_resume,    
  9. #endif    
  10.     .id_table = ath9k_hif_usb_ids,    
  11.     .soft_unbind = 1,    
  12. };    


2. 关键数据结构

1) struct ieee80211_hw: 它包含802.11 PHY的配置和硬件信息





2.1 各层间关键数据接口




3、USB无线适配器枚举过程 

     当此基于USB接口的无线网络适配器被枚举时,ath9k_hif_usb_probe将被调用。其调用流程如下图所示:




3.1 struct ieee80211_ops 实例 ath9k_htc_ops(驱动实现)

       ath9k_htc_ops: mac80211通过这些回调函数回调driver的处理函数。ath9k_htc为了接受mac80211的管理,它必须首先向mac80211注册,以申明自己的存在,从而可以接受mac80211的调用。

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. struct ieee80211_ops ath9k_htc_ops = {    
  2.     .tx                 = ath9k_htc_tx,  // 发送mac80211要求发送的帧    
  3.     .start              = ath9k_htc_start, // 第一个被attach到此硬件的net_device被enable之前被调用,之后,可以接收帧数据    
  4.     .stop               = ath9k_htc_stop,  // 最后一个被attach到此硬件的net_device被disable之后被调用,之后,不可以接收帧数据    
  5.     .add_interface      = ath9k_htc_add_interface, // 当一个被attach到此硬件的net_device被enable时被调用    
  6.     .remove_interface   = ath9k_htc_remove_interface, // 通知driver一个接口将要going down    
  7.     .config             = ath9k_htc_config,           // mac802.11调用它修改硬件配置    
  8.     .configure_filter   = ath9k_htc_configure_filter, // 配置设备的接收过滤器    
  9.     .sta_add            = ath9k_htc_sta_add,    
  10.     .sta_remove         = ath9k_htc_sta_remove,    
  11.     .conf_tx            = ath9k_htc_conf_tx,    
  12.     .bss_info_changed   = ath9k_htc_bss_info_changed,    
  13.     .set_key            = ath9k_htc_set_key,    
  14.     .get_tsf            = ath9k_htc_get_tsf,    
  15.     .set_tsf            = ath9k_htc_set_tsf,    
  16.     .reset_tsf          = ath9k_htc_reset_tsf,    
  17.     .ampdu_action       = ath9k_htc_ampdu_action,    
  18.     .sw_scan_start      = ath9k_htc_sw_scan_start,    
  19.     .sw_scan_complete   = ath9k_htc_sw_scan_complete,    
  20.     .set_rts_threshold  = ath9k_htc_set_rts_threshold,    
  21.     .rfkill_poll        = ath9k_htc_rfkill_poll_state,    
  22.     .set_coverage_class = ath9k_htc_set_coverage_class,    
  23.     .set_bitrate_mask   = ath9k_htc_set_bitrate_mask,    
  24. };    


3.2 struct cfg80211_ops 实例 mac80211_config_ops(mac80211实现)  

   cfg80211_ops定义了无线配置的操作,在它的增加虚拟接口(ieee80211_add_iface)中,它将创建并注册net_device。在mac80211中,其定义如下所示:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. struct cfg80211_ops mac80211_config_ops = {    
  2.     .add_virtual_intf = ieee80211_add_iface, //使用给定的名字创建一个"虚拟接口",在wiphy的命名空间中创建net_device并返回    
  3.     .del_virtual_intf = ieee80211_del_iface, //删除由ifindex指定的"虚拟接口"    
  4.     .change_virtual_intf = ieee80211_change_iface,    
  5.     .add_key = ieee80211_add_key,    
  6.     .del_key = ieee80211_del_key,    
  7.     .get_key = ieee80211_get_key,    
  8.     .set_default_key = ieee80211_config_default_key,    
  9.     .set_default_mgmt_key = ieee80211_config_default_mgmt_key,    
  10.     .add_beacon = ieee80211_add_beacon,    
  11.     .set_beacon = ieee80211_set_beacon,    
  12.     .del_beacon = ieee80211_del_beacon,    
  13.     .add_station = ieee80211_add_station,    
  14.     .del_station = ieee80211_del_station,    
  15.     .change_station = ieee80211_change_station,    
  16.     .get_station = ieee80211_get_station,    
  17.     .dump_station = ieee80211_dump_station,    
  18.     .dump_survey = ieee80211_dump_survey,    
  19. #ifdef CONFIG_MAC80211_MESH    
  20.     .add_mpath = ieee80211_add_mpath,    
  21.     .del_mpath = ieee80211_del_mpath,    
  22.     .change_mpath = ieee80211_change_mpath,    
  23.     .get_mpath = ieee80211_get_mpath,    
  24.     .dump_mpath = ieee80211_dump_mpath,    
  25.     .update_mesh_config = ieee80211_update_mesh_config,    
  26.     .get_mesh_config = ieee80211_get_mesh_config,    
  27.     .join_mesh = ieee80211_join_mesh,    
  28.     .leave_mesh = ieee80211_leave_mesh,    
  29. #endif    
  30.     .change_bss = ieee80211_change_bss,    
  31.     .set_txq_params = ieee80211_set_txq_params,    
  32.     .set_channel = ieee80211_set_channel,    
  33.     .suspend = ieee80211_suspend,    
  34.     .resume = ieee80211_resume,    
  35.     .scan = ieee80211_scan,    
  36.     .sched_scan_start = ieee80211_sched_scan_start,    
  37.     .sched_scan_stop = ieee80211_sched_scan_stop,    
  38.     .auth = ieee80211_auth,    
  39.     .assoc = ieee80211_assoc,    
  40.     .deauth = ieee80211_deauth,    
  41.     .disassoc = ieee80211_disassoc,    
  42.     .join_ibss = ieee80211_join_ibss,    
  43.     .leave_ibss = ieee80211_leave_ibss,    
  44.     .set_wiphy_params = ieee80211_set_wiphy_params,    
  45.     .set_tx_power = ieee80211_set_tx_power,    
  46.     .get_tx_power = ieee80211_get_tx_power,    
  47.     .set_wds_peer = ieee80211_set_wds_peer,    
  48.     .rfkill_poll = ieee80211_rfkill_poll,    
  49.     CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)    
  50.     .set_power_mgmt = ieee80211_set_power_mgmt,    
  51.     .set_bitrate_mask = ieee80211_set_bitrate_mask,    
  52.     .remain_on_channel = ieee80211_remain_on_channel,    
  53.     .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,    
  54.     .mgmt_tx = ieee80211_mgmt_tx,    
  55.     .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,    
  56.     .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,    
  57.     .mgmt_frame_register = ieee80211_mgmt_frame_register,    
  58.     .set_antenna = ieee80211_set_antenna,    
  59.     .get_antenna = ieee80211_get_antenna,    
  60.     .set_ringparam = ieee80211_set_ringparam,    
  61.     .get_ringparam = ieee80211_get_ringparam,    
  62. }    


3.3 struct iw_handler_def  实例 cfg80211_wext_handler(wireless实现)

      cfg80211_wext_handler实现了wext要求的ioctl操作,将通过net_device->wireless_handlers->standard[ioctl cmd- SIOCIWFIRST]来进行调用。在net/wireless/wext-compat.c中的定义如下所示:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. tatic const iw_handler cfg80211_handlers[] = {    
  2.     [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,    
  3.     [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,    
  4.     [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq,    
  5.     [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode,    
  6.     [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode,    
  7.     [IW_IOCTL_IDX(SIOCGIWRANGE)]    = (iw_handler) cfg80211_wext_giwrange,    
  8.     [IW_IOCTL_IDX(SIOCSIWAP)]   = (iw_handler) cfg80211_wext_siwap,    
  9.     [IW_IOCTL_IDX(SIOCGIWAP)]   = (iw_handler) cfg80211_wext_giwap,    
  10.     [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme,    
  11.     [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan,    
  12.     [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan,    
  13.     [IW_IOCTL_IDX(SIOCSIWESSID)]    = (iw_handler) cfg80211_wext_siwessid,    
  14.     [IW_IOCTL_IDX(SIOCGIWESSID)]    = (iw_handler) cfg80211_wext_giwessid,    
  15.     [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate,    
  16.     [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate,    
  17.     [IW_IOCTL_IDX(SIOCSIWRTS)]  = (iw_handler) cfg80211_wext_siwrts,    
  18.     [IW_IOCTL_IDX(SIOCGIWRTS)]  = (iw_handler) cfg80211_wext_giwrts,    
  19.     [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag,    
  20.     [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag,    
  21.     [IW_IOCTL_IDX(SIOCSIWTXPOW)]    = (iw_handler) cfg80211_wext_siwtxpower,    
  22.     [IW_IOCTL_IDX(SIOCGIWTXPOW)]    = (iw_handler) cfg80211_wext_giwtxpower,    
  23.     [IW_IOCTL_IDX(SIOCSIWRETRY)]    = (iw_handler) cfg80211_wext_siwretry,    
  24.     [IW_IOCTL_IDX(SIOCGIWRETRY)]    = (iw_handler) cfg80211_wext_giwretry,    
  25.     [IW_IOCTL_IDX(SIOCSIWENCODE)]   = (iw_handler) cfg80211_wext_siwencode,    
  26.     [IW_IOCTL_IDX(SIOCGIWENCODE)]   = (iw_handler) cfg80211_wext_giwencode,    
  27.     [IW_IOCTL_IDX(SIOCSIWPOWER)]    = (iw_handler) cfg80211_wext_siwpower,    
  28.     [IW_IOCTL_IDX(SIOCGIWPOWER)]    = (iw_handler) cfg80211_wext_giwpower,    
  29.     [IW_IOCTL_IDX(SIOCSIWGENIE)]    = (iw_handler) cfg80211_wext_siwgenie,    
  30.     [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,    
  31.     [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,    
  32.     [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,    
  33.     [IW_IOCTL_IDX(SIOCSIWPMKSA)]    = (iw_handler) cfg80211_wext_siwpmksa,    
  34.   [IW_IOCTL_IDX(SIOCSIWPRIV)] = (iw_handler)cfg80211_wext_setpriv    
  35. };    
  36.     
  37. const struct iw_handler_def cfg80211_wext_handler = {    
  38.     .num_standard       = ARRAY_SIZE(cfg80211_handlers),    
  39.     .standard       = cfg80211_handlers,    
  40.     .get_wireless_stats = cfg80211_wireless_stats,    


4、创建并注册net_device

             当执行mac80211_config_ops-> ieee80211_add_iface时,它将创建net_device和对应的ieee80211_sub_if_data, 然后主要做了以下几件事:

1) 把net_device对应的名字增加到/sys/class/net/目录下   
2) 把新创建的net_device插入到init_net->dev_base_head中
3) 通知上层协议,有一个新的net_device出现了,大家可以使用它了
4) 把新创建的ieee80211_sub_if_data增加到ieee80211_local的interfaces列表中        

其流程如下图所示:


  

mac80211中定义的net_device_ops ieee80211_dataif_ops,以下这些方法,都有一个struct net_device参数。其具体定义如下:   

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static const struct net_device_ops ieee80211_dataif_ops = {    
  2.     .ndo_open       = ieee80211_open,              // net_device变换到 UP 时被调用    
  3.     .ndo_stop       = ieee80211_stop,              // net_device变换到 Down 时被调用    
  4.     .ndo_uninit     = ieee80211_teardown_sdata,    // 取消注册或注册失败时调用    
  5.     .ndo_start_xmit     = ieee80211_subif_start_xmit,  // 需要发送包时被调用    
  6.     .ndo_set_multicast_list = ieee80211_set_multicast_list,// 多播地址列表变化时被调用    
  7.     .ndo_change_mtu     = ieee80211_change_mtu,        // 当用户想改变一个设备的MTU时被调用    
  8.     .ndo_set_mac_address    = ieee80211_change_mac,        // mac地址需要改变时被调用    
  9.     .ndo_select_queue   = ieee80211_netdev_select_queue, //当net_device支持多个发送队列时,用来决定使用哪个队列    
  10. };    


mac80211中初始化net_device->netdev_ops:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static void ieee80211_if_setup(struct net_device *dev)    
  2. {    
  3.     ether_setup(dev);    
  4.     dev->priv_flags &= ~IFF_TX_SKB_SHARING;    
  5.     dev->netdev_ops = &ieee80211_dataif_ops;    
  6.     dev->destructor = free_netdev;    
  7. }    


5. 数据接收(Data RX)流程

   数据接收流程如下图所示:



IP层与TCP/UDP层接口定义如下:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static const struct net_protocol tcp_protocol = {    
  2.     .handler =  tcp_v4_rcv,    
  3.     .err_handler =  tcp_v4_err,    
  4.     .gso_send_check = tcp_v4_gso_send_check,    
  5.     .gso_segment =  tcp_tso_segment,    
  6.     .gro_receive =  tcp4_gro_receive,    
  7.     .gro_complete = tcp4_gro_complete,    
  8.     .no_policy =    1,    
  9.     .netns_ok = 1,    
  10. };    
  11.     
  12. static const struct net_protocol udp_protocol = {    
  13.     .handler =  udp_rcv,    
  14.     .err_handler =  udp_err,    
  15.     .gso_send_check = udp4_ufo_send_check,    
  16.     .gso_segment = udp4_ufo_fragment,    
  17.     .no_policy =    1,    
  18.     .netns_ok = 1,    
  19. };    
  20.     
  21. static const struct net_protocol icmp_protocol = {    
  22.     .handler =  icmp_rcv,    
  23.     .err_handler =  ping_err,    
  24.     .no_policy =    1,    
  25.     .netns_ok = 1,    
  26. };    

IP层与net/core层接口定义如下
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static struct packet_type ip_packet_type __read_mostly = {    
  2.     .type = cpu_to_be16(ETH_P_IP),    
  3.     .func = ip_rcv,    
  4.     .gso_send_check = inet_gso_send_check,    
  5.     .gso_segment = inet_gso_segment,    
  6.     .gro_receive = inet_gro_receive,    
  7.     .gro_complete = inet_gro_complete,    
  8. };    




6、数据发送(Data TX)流珵

   数据发送流程如下图所示:



上半部分涉及到的相关代码如下所示(以上流程主要通过dump_stack获取):

     net/socket.c
     net/ipv4/af_net.c
     net/ipv4/tcp.c
     net/ipv4/tcp_output.c
     net/ipv4/ip_output.c
     net/core/neighbour.c
     net/core/dev.c


7、INET初始化

    INET为Linux OS实现了TCP/IP协议集,它使用BSD Socket接口作为与User通讯的方式。其初始化代码如下所示:

代码位于:net/ipv4/af_inet.c

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static int __init inet_init(void)    
  2. {    
  3.     struct sk_buff *dummy_skb;    
  4.     struct inet_protosw *q;    
  5.     struct list_head *r;    
  6.     int rc = -EINVAL;    
  7.     
  8.     BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));    
  9.     
  10.     sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);    
  11.     if (!sysctl_local_reserved_ports)    
  12.         goto out;    
  13.     
  14.     rc = proto_register(&tcp_prot, 1);    
  15.     if (rc)    
  16.         goto out_free_reserved_ports;    
  17.     
  18.     rc = proto_register(&udp_prot, 1);    
  19.     if (rc)    
  20.         goto out_unregister_tcp_proto;    
  21.     
  22.     rc = proto_register(&raw_prot, 1);    
  23.     if (rc)    
  24.         goto out_unregister_udp_proto;    
  25.     
  26.     rc = proto_register(&ping_prot, 1);    
  27.     if (rc)    
  28.         goto out_unregister_raw_proto;    
  29.     
  30.     /*  
  31.      *  Tell SOCKET that we are alive...  
  32.      */    
  33.     
  34.     (void)sock_register(&inet_family_ops);    
  35.     
  36. #ifdef CONFIG_SYSCTL    
  37.     ip_static_sysctl_init();    
  38. #endif    
  39.     
  40.     /*  
  41.      *  Add all the base protocols.  
  42.      */    
  43.     
  44.     if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)    
  45.         printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n");    
  46.     if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)    
  47.         printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n");    
  48.     if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)    
  49.         printk(KERN_CRIT "inet_init: Cannot add TCP protocol\n");    
  50. #ifdef CONFIG_IP_MULTICAST    
  51.     if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)    
  52.         printk(KERN_CRIT "inet_init: Cannot add IGMP protocol\n");    
  53. #endif    
  54.     
  55.     /* Register the socket-side information for inet_create. */    
  56.     for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)    
  57.         INIT_LIST_HEAD(r);    
  58.     
  59.     for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)    
  60.         inet_register_protosw(q);    
  61.     
  62.     /*  
  63.      *  Set the ARP module up  
  64.      */    
  65.     
  66.     arp_init();    
  67.     
  68.     /*  
  69.      *  Set the IP module up  
  70.      */    
  71.     
  72.     ip_init();    
  73.     
  74.     tcp_v4_init();    
  75.     
  76.     /* Setup TCP slab cache for open requests. */    
  77.     tcp_init();    
  78.     
  79.     /* Setup UDP memory threshold */    
  80.     udp_init();    
  81.     
  82.     /* Add UDP-Lite (RFC 3828) */    
  83.     udplite4_register();    
  84.     
  85.     ping_init();    
  86.     
  87.     /*  
  88.      *  Set the ICMP layer up  
  89.      */    
  90.     
  91.     if (icmp_init() < 0)    
  92.         panic("Failed to create the ICMP control socket.\n");    
  93.     
  94.     /*  
  95.      *  Initialise the multicast router  
  96.      */    
  97. #if defined(CONFIG_IP_MROUTE)    
  98.     if (ip_mr_init())    
  99.         printk(KERN_CRIT "inet_init: Cannot init ipv4 mroute\n");    
  100. #endif    
  101.     /*  
  102.      *  Initialise per-cpu ipv4 mibs  
  103.      */    
  104.     
  105.     if (init_ipv4_mibs())    
  106.         printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n");    
  107.     
  108.     ipv4_proc_init();    
  109.     
  110.     ipfrag_init();    
  111.     
  112.     dev_add_pack(&ip_packet_type);    
  113.     
  114.     rc = 0;    
  115. out:    
  116.     return rc;    
  117. out_unregister_raw_proto:    
  118.     proto_unregister(&raw_prot);    
  119. out_unregister_udp_proto:    
  120.     proto_unregister(&udp_prot);    
  121. out_unregister_tcp_proto:    
  122.     proto_unregister(&tcp_prot);    
  123. out_free_reserved_ports:    
  124.     kfree(sysctl_local_reserved_ports);    
  125.     goto out;    
  126. }    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 日志文件 说明

MySQL 5.5 官方文档上有关日志的分类&#xff1a;By default, nologs are enabled. The following log-specific sections provide information about the server options that enable logging.--默认情况下&#xff0c;没有启动任何log&#xff0c;可以通过如下log 选项来启动…

Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析

前面学习了SDIO接口的WiFi驱动&#xff0c;现在我们来学习一下USB接口的WiFi驱动&#xff0c;二者的区别在于接口不同。而USB接口的设备驱动&#xff0c;我们前面也有学习&#xff0c;比如USB摄像头驱动、USB鼠标驱动&#xff0c;同样都符合LinuxUSB驱动结构&#xff1a; USB设…

我的第一程序语言python

我接触的第一门语言是python,因此对python 可能有着更深厚的感情。感觉学的时间长了&#xff0c;就像是把把它当成是一个朋友&#xff0c;一个伴侣&#xff0c;想去读懂他&#xff0c;理解他&#xff0c;就像是自己的身体可以收放自如。从接触python 到现在也快有五个月了&…

Linux 下wifi 驱动开发(三)—— SDIO接口WiFi驱动浅析

SDIO-Wifi模块是基于SDIO接口的符合wifi无线网络标准的嵌入式模块&#xff0c;内置无线网络协议IEEE802.11协议栈以及TCP/IP协议栈&#xff0c;能够实现用户主平台数据通过SDIO口到无线网络之间的转换。SDIO具有传输数据快&#xff0c;兼容SD、MMC接口等特点。 对于SDIO接口的w…

2312llvm,09clang工具下

ClangQuery 在LLVM3.5中引入ClangQuery工具,它可读入一个源文件,交互查询它所关联的ClangAST节点.是帮助查看并学习前端如何表达每行代码的很好工具. 然而,它的主要目标是,你不但可查看程序的AST,而且可测试AST匹配器. 编写重构工具时,你会对使用,包含匹配感兴趣的ClangAST片…

Erlang并发机制 –进程调度

2019独角兽企业重金招聘Python工程师标准>>> Erlang调度器主要完成对Erlang进程的调度&#xff0c;它是Erlang实现软件实时和进程之间公平使用CPU的关键。Erlang运行时&#xff0c;有4种任务需要被调度&#xff1a;进程&#xff0c;Port&#xff0c;Linked-in drive…

Linux 下wifi 驱动开发(二)—— WiFi模块浅析

一、什么是wifi 模块 百度百科上这样定义&#xff1a; Wi-Fi模块又名串口Wi-Fi模块&#xff0c;属于物联网传输层&#xff0c;功能是将串口或TTL电平转为符合Wi-Fi无线网络通信标准的嵌入式模块&#xff0c;内置无线网络协议IEEE802.11b.g.n协议栈以及TCP/IP协议栈。传统的硬件…

VSS2005 上传pdf 空白

加补丁 VS80-KB943847-X86-INTL.exe

Linux 下wifi 驱动开发(一)—— WiFi基础知识解析

一、WiFi相关基础概念 1、什么是wifi 我们看一下百度百科是如何定义的&#xff1a; Wi-Fi是一种可以将个人电脑、手持设备&#xff08;如pad、手机&#xff09;等终端以无线方式互相连接的技术&#xff0c;事实上它是一个高频无线电信号。[1] 无线保真是一个无线网络通信技术…

poj 3348 Cows 求凸包以及凸包的面积

题目来源&#xff1a; http://poj.org/problem?id3348 1:任意多边形p[0,n-1]的面积为 for(int i0 ; i<n-1 ; i){ sum (sk[i]^sk[(i1)%(n) ] )*0.5; } 2: 求凸包&#xff0c; 用graham 模板 代码如下&#xff1a; #include <iostream> #include <algorithm> #in…

Linux 网络设备驱动开发(一) —— linux内核网络分层结构

Linux内核对网络驱动程序使用统一的接口&#xff0c;并且对于网络设备采用面向对象的思想设计。 Linux内核采用分层结构处理网络数据包。分层结构与网络协议的结构匹配&#xff0c;既能简化数据包处理流程&#xff0c;又便于扩展和维护。 一、内核网络结构 在Linux内核中&#…

windows清理剪切板

开始——运行——clipbrd &#xff08;WINR&#xff09;转载于:https://blog.51cto.com/eblog/1390662

Linux 网络设备驱动开发(二) —— Linux 网络栈剖析

一、协议简介 虽然对于网络的正式介绍一般都参考了 OSI&#xff08;Open Systems Interconnection&#xff09;模型&#xff0c;但是本文对 Linux 中基本网络栈的介绍分为四层的 Internet 模型&#xff08;如图 1 所示&#xff09;。 图 1. 网络栈的 Internet 模型 这个栈的最底…

Android之BroadcastReceiver 监听系统广播

绑定广播有两种方式 一.配置文件绑定&#xff0c;在程序未启动也能监听 二.代码方式绑定&#xff0c;在程序启动后才能监听 1.绑定和取消绑定广播 public class MainActivity extends Activity {private Button registerButtonnull;private Button unRegisterButtonnull;privat…

Linux 网络设备驱动开发(三) —— 网络设备驱动基本原理和框架

一、协议栈层次对比 二、Linux网络子系统 Linux网络子系统的顶部是系统调用接口层。它为用户空间提供的应用程序提供了一种访问内核网络子系统的方法&#xff08;socket&#xff09;。位于其下面是一个协议无关层&#xff0c;它提供一种通用的方法来使用传输层协议。然后是具…

国产杀毒软件也开始支持虚拟化

今天不小心看到一个较老的“新”闻&#xff0c;国产安全软件厂商瑞星已经推出支持VMware vshield Endpoint技术的防病毒产品&#xff0c;也就是说如果客户今天使用的是VMware的虚拟化软件&#xff0c;上面运行的所有虚拟机就不需要安装传统的防病毒软件程序&#xff0c;而可以直…

VRP平台基本操作

一、显示系统信息 <Huawei>display version 图上所示可以知道VRP平台信息&#xff0c;运行的版本&#xff0c;运行的时间 二、修改和查看设备系统时间参数 1.查看时间 <Huawei>display clock 2.修改系统日期和时间 三、进入系统视图界面 <Huawei>system-view…

Android中获取应用程序(包)的信息-----PackageManager的使用(一)

本节内容是如何获取Android系统中应用程序的信息&#xff0c;主要包括packagename、label、icon、占用大小等。具体分为两个 部分&#xff0c;计划如下&#xff1a; 第一部分&#xff1a; 获取应用程序的packagename、label、icon等 &#xff1b; 第二部分&#xff1a; 获取应用…

VRP平台总体介绍及基础配置

前言 1、VRP软件系统基础 VRP系统在启动时需要加载“系统软件”和“配置文件”两部分&#xff0c;这与其它品牌网络交换机的操作系统是一样的。如果指定了下次启动的补丁文件&#xff0c;还需加载补丁文件。修改VRP系统启动的场景一般有以下几种&#xff1a; a-- 对交换机进行升…

小强的HTML5移动开发之路(43)——JqueryMobile页眉、工具栏和标签栏导航

一、页眉1、添加页眉和页脚<div data-role"header"><h1>第 1 页</h1></div><div data-role"footer"><h4>页面脚注</h4></div>默认的页眉在屏幕的顶部边缘显示&#xff0c;而且在在屏幕滚动时&#xff0c;…