wifi详解(四)

1        IOCTL的调用逻辑

之所以要分析这个,是因为上层wpa_supplicant和WIFI驱动打交道的方式,多半是通过ioctl的方式进行的,所以看看它的调用逻辑(这里只列出其主要的调用逻辑):

       上面便是用户ioctl调用的流程图,它最终分为两条线即有两种支持,选择那一条或两条都选(个人感觉最好选第2条线,因为它最后也是会调用到相应的函数的,而且还有其它更多的命令支持),从实际的代码来看,如果dev->netdev_ops

->ndo_do_ioctl被初始化了,那么它一定会被调用,是否被初始化,在前面选择对net结构变量的初始化方式中有讨论过。

       下面来具体看看该调用流程,首先说明下,上面的流程主要实现在kernel/net/wireless/wext_core.c文件中,这是wireless的协议层实现,恰好我们在wpa_supplicant中通常选择的驱动类型也是wext,它的入口函数是wext_ioctl_dispatch:

/* entry point from dev ioctl*/

static int wext_ioctl_dispatch(struct net *net, struct ifreq*ifr,

                              unsigned int cmd, struct iw_request_info *info,

                              wext_ioctl_func standard,

                               wext_ioctl_funcprivate)

{

        int ret = wext_permission_check(cmd);

 

        if (ret)

                return ret;

 

        dev_load(net, ifr->ifr_name);

        rtnl_lock();

        ret = wireless_process_ioctl(net, ifr, cmd, info, standard,private);

        rtnl_unlock();

 

        return ret;

}

      

它其实就是wireless_process_ioctl的封装函数,除了进行许可权限的确认,没有做什么其它内容,这里有standard和private两个函数指针的传递,其实就是两个回调函数,在后面会用到,它是由wext_handle_ioctl函数传递过来的:

int wext_handle_ioctl(structnet *net, struct ifreq *ifr, unsigned int cmd,

                      void __user *arg)

{

        struct iw_request_info info = { .cmd =cmd, .flags = 0 };

        int ret;

 

        ret = wext_ioctl_dispatch(net, ifr, cmd, &info,

                                 ioctl_standard_call,

                                 ioctl_private_call);     //这两个回调函数的定义之后再讨论,这里暂不理论

        if (ret >= 0 &&

            IW_IS_GET(cmd) &&

            copy_to_user(arg, ifr, sizeof(structiwreq)))

                return -EFAULT;

 

        return ret;

}

实际上传递的就是ioctl_standard_call和ioctl_private_call两个函数,在看看wireless_process_ioctl函数,这个函数很重要,下面做重点分析:

static intwireless_process_ioctl(struct net *net, struct ifreq *ifr,

                                  unsigned int cmd,

                                  structiw_request_info *info,

                                 wext_ioctl_func standard,

                                 wext_ioctl_func private)

{

        struct iwreq *iwr = (struct iwreq *)ifr;

        struct net_device *dev;

        iw_handler      handler;

 

        /* Permissions are already checked indev_ioctl() before calling us.

         * The copy_to/from_user() of ifr isalso dealt with in there */

 

        /* Make sure the device exist */

        if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)             //通过网络接口名获取net_device设备

                return -ENODEV;

 

        /* A bunch of special cases, then thegeneric case...

         * Note that 'cmd' is already filteredin dev_ioctl() with

         * (cmd >= SIOCIWFIRST &&cmd <= SIOCIWLAST) */

        if (cmd == SIOCGIWSTATS)

                returnstandard(dev, iwr, cmd, info,

                               &iw_handler_get_iwstats);   //如果是状态查询命令,调用该函数(回调函数中的一个)

 

#ifdef CONFIG_WEXT_PRIV

        if (cmd == SIOCGIWPRIV && dev->wireless_handlers)

                returnstandard(dev, iwr, cmd, info,

                               iw_handler_get_private);      //如果是专有命令,调用回调函数,同上

#endif

 

        /* Basic check */

        if (!netif_device_present(dev))

                return -ENODEV;

 

        /* New driver API : try to find thehandler */

        handler = get_handler(dev, cmd);              //根据cmd参数,从dev成员中查询相应的处理函数

        if (handler) {

                /* Standard and private are notthe same */

                if (cmd < SIOCIWFIRSTPRIV)

                        return standard(dev, iwr, cmd, info, handler);  //调用相应命令的处理函数

                else if (private)

                        return private(dev, iwr, cmd, info, handler);     //同上

        }

        /* Old driver API : call driver ioctlhandler */

        if(dev->netdev_ops->ndo_do_ioctl)

                return dev->netdev_ops->ndo_do_ioctl(dev,ifr, cmd);     //如果被设置就调用该函数

        return -EOPNOTSUPP;

}

该函数的大意是,通过网络接口名称获得一个网络设备,然后根据命令的类型调用相应的处理函数,特别的是当dev->netdev_ops->ndo_do_ioctl或dev->wireless_handlers被设置时,则会查找执行对应的处理函数。Get_handle函数用于查询处理函数使用:

static iw_handlerget_handler(struct net_device *dev, unsigned int cmd)

{

        /* Don't "optimise" thefollowing variable, it will crash */

        unsigned int    index;          /* *MUST* be unsigned */

        const struct iw_handler_def *handlers = NULL;

 

#ifdef CONFIG_CFG80211_WEXT

        if (dev->ieee80211_ptr &&dev->ieee80211_ptr->wiphy)

                handlers =dev->ieee80211_ptr->wiphy->wext;  //初始化默认的处理函数

#endif

#ifdef CONFIG_WIRELESS_EXT

        if (dev->wireless_handlers)

                handlers= dev->wireless_handlers;    //这里的dev->wireless_handlersnet初始化时被作为扩张功能选择性的设置,前面有提到过

#endif

 

        if (!handlers)

                return NULL;

 

        /* Try as a standard command */

        index = IW_IOCTL_IDX(cmd);

        if (index <handlers->num_standard)

                returnhandlers->standard[index];     //返回对应的标准函数

 

#ifdef CONFIG_WEXT_PRIV

        /* Try as a private command */

        index = cmd - SIOCIWFIRSTPRIV;

        if (index <handlers->num_private)

                return handlers->private[index];        //返回对应的专有函数

#endif

 

        /* Not found */

        return NULL;

}

那么这个dev->wire

  • 4
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值