跟一下wpa_supplicant(1) 初始化

news/2024/11/29 22:45:38/
环境:
  android 2.3.4 
  wpa_supplicant 0.8
一切从 main.c 开始: (=>表示第1级, 那么==>表示下一级,类推)
os_program_init => 参数解析& 获取
=> wpa_supplicant_init(&params)
   ==> eap_register_methods /* 注册EAP method ,比如EAP-PSK, EAP-TLS */
   ==> global->params获取, 比如daemonize-是否在后台运行wpa,
                               ctrl_interface-wpa_cli 命名socket
   ==> eloop_init , static struct eloop_data eloop; 结构清0
   ==> wpa_supplicant_global_ctrl_iface_init
           (init.rc wpa socket file regist to eloop table)
           在init.rc 中wpa service 启动命令中声明的socket如下:
    service wpa_supplicant /system/bin/wpa_supplicant
             socket wpa_wlan0:0
           通过 android_get_control_socket 函数(android 特有的)和socket名
    获得socket 句柄,放入struct wpa_global 的 ctrl_iface 变量中
           
   ==> wpas_notify_supplicant_initialized 
          其中进行 dbus init  但CONFIG_CTRL_IFACE_DBUS 没有设置! 什么也不做
   ==> wpa_drivers[i]->global_init(); 
          目前wpa_drivers 包含wext,和nl80211 其中nl80211 
   是nl80211_global_init 分配生成
   struct nl80211_global { struct dl_list interfaces; };
   接口双向list init ,然后给出pointer
   ==> 最后返回前面已经init 的struct wpa_global *global
=> wpa_supplicant_add_iface (如其名,添加接口,就是wlan0)
   ==> struct wpa_supplicant  wpa_s = wpa_supplicant_alloc();
       给struct wpa_supplicant *wpa_s 分配内存,并对下面这些变量init
        /* scan_req =1,表示手动scan ,即使没有网络在conf文件中配置
     除了0, 还可以设置为2,好象设置2时不做关联请求(associate req)*/
        wpa_s->scan_req = 1;
        /* time in sec between scans to find suitable AP 
   可见这个参数决定了ap 是否在线的判断,但是
   要省电时可以设置了长点*/
 wpa_s->scan_interval = 5;
 /* driver 参数,可见 kerneldoc 解释如下:
http://linuxwireless.org/en/developers/Documentation/nl80211/kerneldoc
 NL80211_ATTR_SCHED_SCAN_INTERVAL 
          Interval between scheduled scan cycles, in msecs. 
        这个参数看来必须小于上面的 scan_interval*/
 wpa_s->sched_scan_interval = 3;
 wpa_s->new_connection = 1;
 wpa_s->parent = wpa_s;
 wpa_s->sched_scanning = 0;
 wpa_s->override_sched_scan = 0;
scan_interval 就是设置driver 调度scan 的间隔时间
 scan_req 就是wpa 定时去读driver scan 到的结果
 但是eloop 中scan 多播的事件,这个又如何解释???
==> wpa_supplicant_init_iface
       ===> struct wpa_config * wpa_config_read(wpa_s->confname);  
            读/data/misc/wifi/wpa_supplicant.conf 并解析到wpa_config 结构
            config.h 有default 设置,某些可以通过wpa_cli 设置
         全部读到 struct wpa_supplicant结构的wpa_s->conf
  (命令行-c /data/misc/wifi/wpa_supplicant.conf)
       ===> eapol_sm_notify_portEnabled, eapol_sm_notify_portValid 
            init eapol state machine ,但是目前sm==NULL,什么也没做
===> wpa_supplicant_set_driver (确定 wpa_s->driver = wpa_drivers[i];)
            根据driver name = 'nl80211'  查到 wpa_drivers中的某1个做下面动作:
       wpa_s->driver = wpa_drivers[i]; /* 指向某个struct wpa_driver_ops */
     
     /*drv_priv 是前面wpa_drivers[i]->global_init()时获得的 
     struct nl80211_global {struct dl_list interfaces;};
     以后driver init 时将init 好的driver data挂到该双向list 上
            可参考 wpa_drv_init wpa_driver_nl80211_init,
            其实不用以后,下面马上开始wpa_drv_init
            */ 
     wpa_s->global_drv_priv = wpa_s->global->drv_priv[i];
===> wpa_drv_init ====> init2 (wpa_driver_nl80211_init)
            分配内存给struct wpa_driver_nl80211_data * drv
     然后对各结构成员init :
            drv->global = global_priv; 还记得前面那个dl list 挂接口用的
     有了这个参数传入,driver 就可以访问该list ,做接口init 后挂表动作了
            drv->ctx = ctx; /* ctx 就是struct wpa_supplicant *wpa_s
                     这样driver opt function 中也能访问到 此结构*/
           
            ====> wpa_driver_nl80211_init_nl
               这部分主要是生成两个结构指针:
     struct nl_handle * nl_hanlde  nl_handle和nl_handle_event
     nl_handle用于向nl80211 netlink 写, 
     nl_handle_event表示接收,scan,mlme,regulatory等多播包,并把
   nl_handle_event  注册到eloop reads table
            ====> /sys/class/net/wlan0/phy80211/name   去读drv->phyname
            ====> drv->ioctl_sock  创建用于 访问网络接口kernel ioctl socket
                  看下下面这段注释:(比如up,down 接口使用该socket 去做)
/*The usual method in Unix to set and get parameters from a network device is through ioctl. 
  Ioctl are usually operations performed on a file descriptor, but they also apply on network sockets. 
  The ioctl is a kernel system call. The arguments of the ioctl define the operations to be done, 
  the parameters of these operations and the device they applies to.
*/
            ====> drv->netlink = netlink_init(cfg) 
          进行driver data部分的 netlink config 设置
                 netlink_init 注册NETLINK_ROUTE socket 到
       eloop reads table,其中handle cb func 为 netlink_receive
                 netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);  
   创建用于NETLINK_ROUTE socket
                 netlink目前使用最广泛的是通过NETLINK_ROUTE 这个选项来获取
       网络设备或者网址的一些信息,比如获得接口状态: IFF_RUNNING
接收newlink, dellink 两个event ,然后使用cfg  
  设置的 callback 函数:
  * wpa_driver_nl80211_event_rtm_newlink :
                如果是if disable 到 enable 就执行wpa_supplicant_event
        (drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
  该事件发生,引发 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
  还有就是请求 scan (wpa_supplicant_req_scan), 要等待iface up时
  
  * wpa_driver_nl80211_event_rtm_dellink, 
       处理iface down 的event,并更新wpa_s 的状态
            ====> rfkill_init /dev/rfkill 不存在,什么也没做
            ====> wpa_driver_nl80211_finish_drv_init
        wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION)  
               通过 NL80211_CMD_SET_INTERFACE 设置compat driver 接口为station,
       
               如果wlan0 没有up 就linux_set_iface_flags 让它up)
               netlink_send_oper_ifla 设置接口连接mode=1, operstate =5 
        (operstate 参考 RFC 2863 operational status)
        可以通过/sys/class/net/wlan0(也与可能是其他名字)/operstate 查看
        operstate的可能取值如下:
                   IF_OPER_UNKNOWN, 
                   IF_OPER_NOTPRESENT, 
                   IF_OPER_DOWN, 
                   IF_OPER_LOWERLAYERDOWN, 
                   IF_OPER_TESTING, 
                   IF_OPER_DORMANT, =5 表示休眠的操作状态
                   IF_OPER_UP, 
               对应到RFC2863兼容状态的策略link_mode
           IF_LINK_MODE_DEFAULT, 
                  IF_LINK_MODE_DORMANT,   =1 对应上面的5 -> IF_OPER_DORMANT
wpa_driver_nl80211_capa :
                   设置 key manager 能力,比如有WAP2,WPA_PSK,WAP2_PSK
                   设置 加密方法 : WEP40, TKIP,CCMP
                   设置 设置802.11 认证方式,比如open,(注意不是802.1X认证)
                   接下来通过 wpa_driver_nl80211_get_info 获取driver的
                   max_scan_ssids, max_sched_scan_ssids
                   sched_scan_supported等等 ,
                   还有其他WPA_DRIVER_FLAGS_SME, WPA_DRIVER_FLAGS_P2P_CAPABLE
              通过SIOCGIFHWADDR 获得 mac addr (记住在这里获得mac地址)
                   所以你可以不改driver ,在这里修改mac addr
              nl80211_register_action_frame :
              NL80211_CMD_REGISTER_ACTION 
              NL80211_CMD_REGISTER_FRAME  看下面注释就知道该函数做了什么
                Register for receiving certain mgmt frames (via NL80211_CMD_FRAME) for processing in userspace. 
                This command requires an interface index, a frame type attribute (optional for backward compatibility reasons, 
                if not given assumes action frames) and a match attribute containing 
                the first few bytes of the frame that should match, e.g. 
                a single byte for only a category match or four bytes for vendor frames including the OUI. 
                The registration cannot be dropped, but is removed automatically when the netlink socket is closed. Multiple registrations can be made.
注册user层接收的一些管理帧,注册后由user 层处理
                  主要有P2P 的 Generic Advertisement Services frame , P2P Action
                  802.11W 部分相关的 SA Query Response
                  FT Action frames ,Fast BSS Transition 相关(802.11r),用于VOIP的多点
                  AP ,快速漫游,小于50ms VOIP设备不会掉线
====> driver init 完成了,通过 struct wpa_driver_nl80211_data 中的
                  成员list,将driver data 挂到前面所讲的global->drv_priv
    在wpa_supplicant_set_driver 函数中
           
    最后返回1个struct i802_bss *bss 主要包含struct wpa_driver_nl80211_data
===> wpa_drv_set_param -> nl80211_set_param 
            可以通过命令行-p ,或者conf文件来设置
Driver interface parameters:
  This field can be used to configure arbitrary driver interace parameters. The
  format is specific to the selected driver interface. This field is not used
  in most cases.  driver_param="field=value"
如果p2p 支持 就处理 use_p2p_group_interface=1,
      其他情况什么也不做,代码注释如下:
       /*When this is added(use_p2p_group_interface=1), start the supplicant normally on wlan0 like above. 
          Then, when P2P negotiation finishes, it will create a new interface for the group (called "p2p-wlan0-0") 
         and put it into the appropriate mode (GO or P2P client). */
===> wpa_supplicant_init_wpa 
            设置struct wpa_sm_ctx  相关function  (处理wpa状态机变化的func !!!)
            ====>wpa_sm_init(ctx);  wpa state machine 初始化 
          =====> pmksa_cache_init ( 专门有show PMKSA cache的命令 ???)
下面聊下PMKSA
The Pairwise Master Key Security Association (PMKSA)
成对主蜜钥安全关联
  在802.11i 中成对主蜜钥是工作站和AP 成功认证产生的结果.
PMK的生命周期和唯一标识被称为PMKID。 这些信息的集合被称为成对主蜜钥安全关联
工作站判断是否是1个有效的目标AP的PMK,通过检查是否PMKSA 和目标AP 的mac 地址匹配,如果这样的PMK不存在,就和AP 使用EAP 进行认证
如果存在这样1个目标AP的PMK,那么工作站就试图使用PMK,通过将PMKID放入到关联请求消息的RSN IE中,当AP接收到关联请求中包含PMKID,AP就检查是否是1个有效的PMKSA,其中有
相同的PMKID,如果有,开始的4次握手就使用已经协商的PMKSA.
  
      根据上面解释下面这3个pmksa_cache_init参数,应就可以理解了
      sm->dot11RSNAConfigPMKLifetime = 43200; /*生命周期*/
      /* 超过生命周期的%70,需要进行re auth */
   sm->dot11RSNAConfigPMKReauthThreshold = 70;
      /*Security association timeout
            就是进行上面说的安全关联的建立应该在60s内完成*/
   sm->dot11RSNAConfigSATimeout = 60;
           
       ===> wpa_sm_set_ifname, wpa_sm_set_fast_reauth
       ===>  wpa_sm_set_param 
         1.RSNA_PMK_LIFETIME 2. RSNA_PMK_REAUTH_THRESHOLD 3. RSNA_SA_TIMEOUT
               这3个参数前面已经解释过了,同样设置和上面wpa_drv_set_param
        不同处是现在只是将这些参数保存到wpa_sm 结构中
===> wpa_drv_get_capa 取 driver 的 capability 然后设置到
               struct wpa_supplicant 的 max_scan_ssids 等member
        ===> wpa_supplicant_driver_init
             ====> l2_packet_init (ifname,macaddr,ETH_P_PAE,
                                    wpa_supplicant_rx_eapol(rx cb)
                    直接看代码:
/* create l2 socket fd!!!
 l2 就是链路层,所以上面init 传了mac 地址
*/
l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,htons(protocol));
ll.sll_family = PF_PACKET;   
ll.sll_ifindex = ifr.ifr_ifindex;  
ll.sll_protocol = htons(protocol);
/* l2 socket addr !!! */
if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {    
     /* 注册eloop 读入 l2 packet 事件,callback l2_packet_receive!!! */
    eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);

             ====> wpa_clear_keys 
           =====> wpa_drv_set_key
          ======> wpa_driver_nl80211_set_key
           清除key key-index 0-3 ??? why 4key
             ====> wpa_drv_set_countermeasures /*  TKIP countermeasures*/
             ====> wpa_drv_flush_pmkid -> nl80211 driver 没有该接口???
             ====> wpa_supplicant_delayed_sched_scan 对conf 文件中的network设置
             进行扫描调度,如果不支持(sched_scan_supported==0)
                    100ms 后wpa_supplicant_req_scan,如果conf没有 network ,
                    那么需要设置 inactive state如下:
             ====> /* Inactive state (wpa_supplicant disabled)*/
                    wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 
                   /* 上面函数中 后台scan 进行的判断标准是:4-Way Handshake
           结束后就是wpa_complete ,这之前停止后台scan !!! */
                   =====> netlink_send_oper_ifla (??????)
                   =====> wpas_notify_state_changed
       ===> wpa_drv_set_country(wpa_s, wpa_s->conf->country)
             ====>wpa_driver_nl80211_set_country
         if (wpa_s->conf->country[0] && wpa_s->conf->country[1]  
         /* 上面这句的意思 country已经通过CRDA获得了才设置 */
       ===> wpa_sm_set_own_addr
       ===> wpa_supplicant_init_eapol(struct wpa_supplicant *wps)
                  和wpa_supplicant_init_wpa 类似
           设置struct eapol_ctx  相关function  (处理eapol 状态机变化的func !!!)
            ====> eapol_sm_init  Initialize EAPOL state machine
         (RFC4137,)
            ====> eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf); 
               =====> tls_init (tls openssl 的init)
            ====> eloop_register_timeout(1, 0, eapol_port_timers_tick
                /* PAE 端口认证实体,EAP 端口超时处理 */, NULL, sm);
        ===> wpa_sm_set_eapol (/* wpa-sm 与 eapol -sm 关联起来*/)
===> wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); 
     (wpa_cli)
            1. 根据conf ctrl_iface=wlan0:0设置 在/data/misc/wifi/wlan0:0 
            (android init.rc 中已经做了)
            2. eloop_register_read_sock(priv->sock, 
                wpa_supplicant_ctrl_iface_receive, wpa_s, priv);
            3. wpa_msg_register_cb (wpa_supplicant_ctrl_iface_msg_cb);
        /* 注册msg debug call back func*/
  由 wpa_msg_ctrl 回调 wpa_supplicant_ctrl_iface_msg_cb 
                             -> wpa_supplicant_ctrl_iface_send
                ( Send a control interface packet to monitors)
   发给V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 3 04:21:b0:e0:20:20]
                sendmsg(priv->sock, &msg, 0) ,priv 就是init.rc 中
                priv->sock = android_get_control_socket(addr.sun_path);
      socket wpa_wlan0:0 dgram 660 wifi wifi
       ===>  wpas_p2p_init (struct wpa_global * (wpa_s->global), 
                         struct wpa_supplicant * wpa_s) 
     p2p 相关,以后再看,已经不行了
       ===>  wpa_bss_init 
    eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0, 
                 wpa_bss_timeout, wpa_s, NULL);
           关于上面看下面这段话,可能和bss(网络或AP)的过期与定期更新有关
Currently, this is very simple: check every WPA_BSS_EXPIRATION_PERIOD
(10 sec by default) whether there are entries that are over
WPA_BSS_EXPIRATION_AGE (180 seconds) old and expire them if they are ot
in use (BSS entry age is the time from the last update in it, e.g.,
based on scan results). The other rule for expiring entries is based on
new scan results: expire an entry if it has not been seen in last
WPA_BSS_EXPIRATION_SCAN_COUNT (2). The latter one will eventually be
improved to handle partial scans (i.e., only some channels/SSIDs being
scanned; those should only expire matching BSS entries). In addition,
there is a maximum limit on the BSS entries (200) and new BSS entries
added above that will end up getting the oldest entry getting removed.
These values will likely end up being configurable at some point and I
have also considered providing options for controlling the BSS list
updating "mode". For example, wpa_supplicant could be requested to keep
the BSS table more frequently up-to-date for all BSSes or for specific
ESSes. This could have some connections with the bgscan mechanism. In
addition, this could get more input from things like Microsoft Wireless
Provisioning Services (multi-SSID/hidden SSID) and IEEE 802.11k neighbor
reports, etc.
      
   ==> wpas_notify_iface_added   /* 不支持dbus,什么也不做*/
   ==> 读init.rc 设置supplicant_scan_interval 
         wifi无线局域网扫描间隔时间,单位为秒。调大这个值可节约耗电。
         如果不设置,就用 wpa_supplicant_alloc 设置的5 秒 (wpa_s->scan_interval = 5;)
   ==> wpas_notify_network_addedstruct wpa_supplicant *wpa_s,struct wpa_ssid *ssid)
        把conf 文件中的 network {中的
=> wpa_supplicant_run  -> eloop_run();  开始epool 大循环 ,进行event 处理(callback)
下面简但列下 eloop_run 相关handle
        eloop_register_read_sock , eloop_register_timeout
 
1. nl_handle_event :
  注册nl_handle_event 的sock 到eloop reads table 而nl_handle_event  
  加入多播scan ,mlme,regulator组
  eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event), 
  wpa_driver_nl80211_event_receive, drv, drv->nl_handle_event);
  和compat driver 通讯 接收scan,mlme,regulator 多播
2.netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);  
 netlink目前使用最广泛的是通过NETLINK_ROUTE 这个选项来获取网络设备或者网址的一些信息
 注册到NETLINK_ROUTE socket 到eloop reads table
 eloop_register_read_sock(netlink->sock, netlink_receive, netlink, NULL);
3. l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, htons(protocol));   /* l2 socket !!! */
   eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); eloop 读l2 packet  进入 !!!
4. 每隔1s 执行eapol_port_timers_tick
  / * This statemachine is implemented as a function that will be called
      * once a second as a registered event loop timeout.
      */
   eloop_register_timeout(1, 0, eapol_port_timers_tick/*PAE 端口认证实体,EAP 端口超时*/, NULL, sm);
5. scan 结果,过期处理? 
  eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0, wpa_bss_timeout, wpa_s, NULL);
6.wpa ctrl 命令处理:
   eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv);

7. scan timeout when driver 
  eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,drv, drv->ctx);
  wpa_driver_nl80211_scan_timeout:
/* This function can be used as registered timeout when starting a scan to
 * generate a scan completed event if the driver does not report this.
 */

8. P2P: 主要有下面这些
P2p.c (srcp2p):   eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
P2p.c (srcp2p):   eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL);
P2p.c (srcp2p):   eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
P2p.c (srcp2p):   eloop_register_timeout(timeout, 0, p2p_find_timeout,
P2p.c (srcp2p):   eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
P2p.c (srcp2p):   eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL);
P2p.c (srcp2p):   eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL);
P2p.c (srcp2p):   eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
P2p.c (srcp2p):   eloop_register_timeout(p2p->ext_listen_interval_sec,
P2p.c (srcp2p):   eloop_register_timeout(p2p->ext_listen_interval_sec,
P2p_supplicant.c:  eloop_register_timeout(0, 0, wpas_send_action_cb, wpa_s, NULL);
P2p_supplicant.c:  eloop_register_timeout(15 + res->peer_config_timeout / 100,
P2p_supplicant.c:  eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
P2p_supplicant.c:  eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
P2p_supplicant.c:  eloop_register_timeout(60, 0, wpas_p2p_group_formation_timeout,
P2p_supplicant.c:  eloop_register_timeout(timeout, 0,
P2p_supplicant.c:  eloop_register_timeout(wpa_s->conf->p2p_group_idle, 0,
画个结构关联图:
(*x) --表示注释
 


http://www.ppmy.cn/news/521432.html

相关文章

networkIssue

SFR: 1、Software #5892 【客户反馈】[SFR][ONEIDA][Bearer 4G] Info Trans Flag is set to 1 in PDN Connectivity Request Description ESM info trans flag should be set to 0. Steps to reproduce : Switch on the UE. UE performs a cell search procedure.Check the UE…

Wpa_supplicant工作流程分析之scan(从应用层到内核)(上)

Wpa_supplicant工作流程分析 wpa_supplicant官网&#xff1a;https://w1.fi/wpa_supplicant/ wpa_supplicant源码下载官网地址&#xff1a;https://w1.fi/releases/ 本文分析基于版本&#xff1a;V2.6 1. 初始化 wpa_supplicant/main.c 在main()中&#xff0c;完成了四件…

自制Linux功能板

Cloud 一、前言二、电源管理2.1 锂电池2.2 充放电路2.3 稳压电路&#xff08;5V->3.3V&#xff09; 三 、启动方式boot3.1 概述3.2 电路图 四、USB_HUB电路4.1 概述4.2 硬件电路 五、mpu6050设计及应用5.1 概述5.2 硬件电路5.3 软件编写 六、ipslcd设计及应用6.1 概述6.2 硬…

在Talon AD7200路由器移植LEDE环境

这个项目是本人对Talon Tools: Practical IEEE 802.11ad Research | talon-tools (seemoo-lab.github.io)上的一个项目&#xff1a;Talon Tools: Practical IEEE 802.11ad Research的实现&#xff0c;同时由于该项目中存在不少误区和省略掉的点&#xff0c;本人对其进行了进一步…

wiFI基础知识----wpa_supplicant

1 wpa_supplicant 源码下载地址&#xff1a; wpa_supplicant-2.10 下载地址&#xff1a;wpa_supplicant-2.10 2 wpa_supplicant 学习总结 wpa_supplicant 学习参考网址&#xff1a;wpa_supplicant 2.1 wpa_supplicant 基本概念&#xff1a; ** wpa_supplicant 是什么&…

Matlab实现电网仿真(附上完整仿真源码)

电网仿真是电力系统研究和设计中非常重要的一部分。Matlab作为一种高效的数值计算工具&#xff0c;已经成为电网仿真中不可或缺的工具之一。本文将介绍如何使用Matlab实现电网仿真。 文章目录 1. 电网模型建立2. 电网仿真参数设置3. 电网仿真结果分析4. 完整仿真源码下载 1. 电…

iCON艾肯五代声卡Dyna版本驱动(全系列)

iCON艾肯声卡第五代声卡驱动直发方官方还没有发布&#xff0c;这需要找经销商要才有。支持声卡型号&#xff1a;Icon Cube2Nano Dyna&#xff0c;Icon_Duo22 Dyna&#xff0c;Icon MicU Dyna&#xff0c;Icon MobileR Dyna&#xff0c;Icon MobileUmini Dyna&#xff0c;Icon U…

艾韵智能A1刷机的一些问题

随着艾韵智能服务器的关闭&#xff0c;A1也失去了用武之地&#xff0c;不过随着第三方固件的诞生&#xff0c;它又复活了&#xff0c;不过刷机过程中有点波折&#xff0c;现给出一些参考的解决方法。 首先刷机方法都是按照潘老师的方法&#xff0c;接入飞阳物联&#xff0c;不…