usb

1. usb hub

 以前不太了解hub,一直认为它只是一个可选设备,和网络集线器类似,有它不多,少它也可;
太低调了,以至于都不晓得它长在哪里,今天在网上百度了一下,发现它是window和linux系统上一个必备的设备;是EHCI/UHCI的私生子,一直躺在妈妈的怀里;

设备部分:<usb_device_type 篇>
hub是usb控制器的私生子,那么他就在hcd.c中生成:
usb_add_hcd()
{
...
rhdev = usb_alloc_dev(NULL, &hcd->self, 0);
hcd->self.root_hub = rhdev;
register_root_hub(hcd);//完成设备添加了;
...
}
下面中的介绍usb_alloc_dev和register_root_hub
函数一

点击(此处)折叠或打开

  1. /**
  2. * usb_add_hcd - finish generic HCD structure initialization and register
  3. * @hcd: the usb_hcd structure to initialize
  4. * @irqnum: Interrupt line to allocate
  5. * @irqflags: Interrupt type flags
  6. *
  7. * Finish the remaining parts of generic HCD initialization: allocate the
  8. * buffers of consistent memory, register the bus, request the IRQ line,
  9. * and call the driver's reset() and start() routines.
  10. */
  11. int usb_add_hcd(struct usb_hcd *hcd,
  12.         unsigned int irqnum, unsigned long irqflags)
  13. {
  14.     int retval;
  15.     struct usb_device *rhdev;

  16.     dev_info(hcd->self.controller, "%s\n", hcd->product_desc);

  17.     hcd->authorized_default = hcd->wireless? 0 : 1;
  18.     set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

  19.     /* HC is in reset state, but accessible. Now do the one-time init,
  20.      * bottom up so that hcds can customize the root hubs before khubd
  21.      * starts talking to them. (Note, bus id is assigned early too.)
  22.      */
  23.     if ((retval = hcd_buffer_create(hcd)) != 0) {
  24.         dev_dbg(hcd->self.controller, "pool alloc failed\n");
  25.         return retval;
  26.     }

  27.     if ((retval = usb_register_bus(&hcd->self)) < 0)
  28.         goto err_register_bus;

  29.     if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
  30.         dev_err(hcd->self.controller, "unable to allocate root hub\n");
  31.         retval = -ENOMEM;
  32.         goto err_allocate_root_hub;
  33.     }

  34.     switch (hcd->driver->flags & HCD_MASK) {
  35.     case HCD_USB11:
  36.         rhdev->speed = USB_SPEED_FULL;
  37.         break;
  38.     case HCD_USB2:
  39.         rhdev->speed = USB_SPEED_HIGH;
  40.         break;
  41.     case HCD_USB3:
  42.         rhdev->speed = USB_SPEED_SUPER;
  43.         break;
  44.     default:
  45.         goto err_allocate_root_hub;
  46.     }
  47.     hcd->self.root_hub = rhdev;//设备

  48.     /* wakeup flag init defaults to "everything works" for root hubs,
  49.      * but drivers can override it in reset() if needed, along with
  50.      * recording the overall controller's system wakeup capability.
  51.      */
  52.     device_init_wakeup(&rhdev->dev, 1);

  53.     /* "reset" is misnamed; its role is now one-time init. the controller
  54.      * should already have been reset (and boot firmware kicked off etc).
  55.      */
  56.      //控制器复位:ehci_pci_setup
  57.     if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
  58.         dev_err(hcd->self.controller, "can't setup\n");
  59.         goto err_hcd_driver_setup;
  60.     }

  61.     /* NOTE: root hub and controller capabilities may not be the same */
  62.     if (device_can_wakeup(hcd->self.controller)
  63.             && device_can_wakeup(&hcd->self.root_hub->dev))
  64.         dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
  65. //控制器中断处理接口
  66.     /* enable irqs just before we start the controller */
  67.     if (hcd->driver->irq) {

  68.         /* IRQF_DISABLED doesn't work as advertised when used together
  69.          * with IRQF_SHARED. As usb_hcd_irq() will always disable
  70.          * interrupts we can remove it here.
  71.          */
  72.         if (irqflags & IRQF_SHARED)
  73.             irqflags &= ~IRQF_DISABLED;

  74.         snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
  75.                 hcd->driver->description, hcd->self.busnum);
  76.         if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
  77.                 hcd->irq_descr, hcd)) != 0) {
  78.             dev_err(hcd->self.controller,
  79.                     "request interrupt %d failed\n", irqnum);
  80.             goto err_request_irq;
  81.         }
  82.         hcd->irq = irqnum;
  83.         dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
  84.                 (hcd->driver->flags & HCD_MEMORY) ?
  85.                     "io mem" : "io base",
  86.                     (unsigned long long)hcd->rsrc_start);
  87.     } else {
  88.         hcd->irq = -1;
  89.         if (hcd->rsrc_start)
  90.             dev_info(hcd->self.controller, "%s 0x%08llx\n",
  91.                     (hcd->driver->flags & HCD_MEMORY) ?
  92.                     "io mem" : "io base",
  93.                     (unsigned long long)hcd->rsrc_start);
  94.     }
  95. //控制器run:ehci_run
  96.     if ((retval = hcd->driver->start(hcd)) < 0) {
  97.         dev_err(hcd->self.controller, "startup error %d\n", retval);
  98.         goto err_hcd_driver_start;
  99.     }

  100.     /* starting here, usbcore will pay attention to this root hub */
  101.     rhdev->bus_mA = min(500u, hcd->power_budget);
  102.     if ((retval = register_root_hub(hcd)) != 0)//设备添加到内核中了;
  103.         goto err_register_root_hub;

  104.     retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
  105.     if (retval < 0) {
  106.         printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
  107.                retval);
  108.         goto error_create_attr_group;
  109.     }
  110.     if (hcd->uses_new_polling && hcd->poll_rh)
  111.         usb_hcd_poll_rh_status(hcd);
  112.     return retval;

  113. error_create_attr_group:
  114.     mutex_lock(&usb_bus_list_lock);
  115.     usb_disconnect(&hcd->self.root_hub);
  116.     mutex_unlock(&usb_bus_list_lock);
  117. err_register_root_hub:
  118.     hcd->driver->stop(hcd);
  119. err_hcd_driver_start:
  120.     if (hcd->irq >= 0)
  121.         free_irq(irqnum, hcd);
  122. err_request_irq:
  123. err_hcd_driver_setup:
  124.     hcd->self.root_hub = NULL;
  125.     usb_put_dev(rhdev);
  126. err_allocate_root_hub:
  127.     usb_deregister_bus(&hcd->self);
  128. err_register_bus:
  129.     hcd_buffer_destroy(hcd);
  130.     return retval;
  131. }




函数



点击(此处)折叠或打开

  1. /**
  2. * usb_alloc_dev - usb device constructor (usbcore-internal)
  3. * @parent: hub to which device is connected; null to allocate a root hub
  4. * @bus: bus used to access the device
  5. * @port1: one-based index of port; ignored for root hubs
  6. * Context: !in_interrupt()
  7. *
  8. * Only hub drivers (including virtual root hub drivers for host
  9. * controllers) should ever call this.
  10. *
  11. * This call may not be used in a non-sleeping context.
  12. */
  13. struct usb_device *usb_alloc_dev(struct usb_device *parent,
  14.                  struct usb_bus *bus, unsigned port1)
  15. {
  16.     struct usb_device *dev;
  17.     struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
  18.     unsigned root_hub = 0;
  19. //usb设备对象;
  20.     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  21.     if (!dev)
  22.         return NULL;

  23.     if (!usb_get_hcd(bus_to_hcd(bus))) {
  24.         kfree(dev);
  25.         return NULL;
  26.     }
  27.     /* Root hubs aren't true devices, so don't allocate HCD resources */
  28.     if (usb_hcd->driver->alloc_dev && parent &&
  29.         !usb_hcd->driver->alloc_dev(usb_hcd, dev)) {
  30.         usb_put_hcd(bus_to_hcd(bus));
  31.         kfree(dev);
  32.         return NULL;
  33.     }
  34.     //usb_device_type
  35. //usb设备的基本属性还是device;
  36.     device_initialize(&dev->dev);
  37.     dev->dev.bus = &usb_bus_type;//所属总线;
  38.     dev->dev.type = &usb_device_type;//usb设备类型,有别于usb_if_device_type;
  39.     dev->dev.groups = usb_device_groups;
  40.     dev->dev.dma_mask = bus->controller->dma_mask;
  41.     set_dev_node(&dev->dev, dev_to_node(bus->controller));
  42.     //USB设备的状态变化;表示已连接上(生来就是在一起的)
  43.     //后面这个状态会一直变化的;
  44.     dev->state = USB_STATE_ATTACHED;
  45.     atomic_set(&dev->urbnum, 0);

  46.     INIT_LIST_HEAD(&dev->ep0.urb_list);
  47.     //初始化端点信息
  48.     dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
  49.     dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
  50.     /* ep0 maxpacket comes later, from device descriptor */
  51.     //使能控制:ep->enabled = 1;
  52.     usb_enable_endpoint(dev, &dev->ep0, false);
  53.     dev->can_submit = 1;

  54.     /* Save readable and stable topology id, distinguishing devices
  55.      * by location for diagnostics, tools, driver model, etc.  The
  56.      * string is a path along hub ports, from the root.  Each device's
  57.      * dev->devpath will be stable until USB is re-cabled, and hubs
  58.      * are often labeled with these port numbers.  The name isn't
  59.      * as stable:  bus->busnum changes easily from modprobe order,
  60.      * cardbus or pci hotplugging, and so on.
  61.      */
  62.     if (unlikely(!parent)) {//hub就是这条路;
  63.         dev->devpath[0] = '0';
  64.         dev->route = 0;

  65.         dev->dev.parent = bus->controller;
  66.         dev_set_name(&dev->dev, "usb%d", bus->busnum);//设备名称usbXX
  67.         root_hub = 1;
  68.     } else {
  69.         /* match any labeling on the hubs; it's one-based */
  70.         if (parent->devpath[0] == '0') {
  71.             snprintf(dev->devpath, sizeof dev->devpath,
  72.                 "%d", port1);
  73.             /* Root ports are not counted in route string */
  74.             dev->route = 0;
  75.         } else {
  76.             snprintf(dev->devpath, sizeof dev->devpath,
  77.                 "%s.%d", parent->devpath, port1);
  78.             /* Route string assumes hubs have less than 16 ports */
  79.             if (port1 < 15)
  80.                 dev->route = parent->route +
  81.                     (port1 << ((parent->level - 1)*4));
  82.             else
  83.                 dev->route = parent->route +
  84.                     (15 << ((parent->level - 1)*4));
  85.         }

  86.         dev->dev.parent = &parent->dev;
  87.         dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);

  88.         /* hub driver sets up TT records */
  89.     }

  90.     dev->portnum = port1;
  91.     dev->bus = bus;
  92.     dev->parent = parent;
  93.     INIT_LIST_HEAD(&dev->filelist);

  94. #ifdef    CONFIG_PM
  95.     mutex_init(&dev->pm_mutex);
  96.     INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
  97.     INIT_WORK(&dev->autoresume, usb_autoresume_work);
  98.     dev->autosuspend_delay = usb_autosuspend_delay * HZ;
  99.     dev->connect_time = jiffies;
  100.     dev->active_duration = -jiffies;
  101. #endif
  102.     if (root_hub)    /* Root hub always ok [and always wired] */
  103.         dev->authorized = 1;//hub 默认;
  104.     else {
  105.         dev->authorized = usb_hcd->authorized_default;
  106.         dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
  107.     }
  108.     return dev;
  109. }



函数三


点击(此处)折叠或打开

  1. /**
  2. * register_root_hub - called by usb_add_hcd() to register a root hub
  3. * @hcd: host controller for this root hub
  4. *
  5. * This function registers the root hub with the USB subsystem. It sets up
  6. * the device properly in the device tree and then calls usb_new_device()
  7. * to register the usb device. It also assigns the root hub's USB address
  8. * (always 1).
  9. */
  10. static int register_root_hub(struct usb_hcd *hcd)
  11. {
  12.     struct device *parent_dev = hcd->self.controller;
  13.     struct usb_device *usb_dev = hcd->self.root_hub;
  14.     const int devnum = 1;
  15.     int retval;

  16.     usb_dev->devnum = devnum;
  17.     usb_dev->bus->devnum_next = devnum + 1;
  18.     memset (&usb_dev->bus->devmap.devicemap, 0,
  19.             sizeof usb_dev->bus->devmap.devicemap);
  20.     set_bit (devnum, usb_dev->bus->devmap.devicemap);
  21. //作为usb设备状态,第二种:USB_STATE_ADDRESS
  22.     usb_set_device_state(usb_dev, USB_STATE_ADDRESS);

  23.     mutex_lock(&usb_bus_list_lock);

  24.     usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
  25. //usb_get_descriptor--usb_control_msg--usb_start_wait_urb--usb_hcd_submit_urb--rh_urb_enqueue
  26. //其实只知道一点就好了,roothub的描述符都是不需要控制器帮忙的,
  27. //自带的;hub.c中有列出来;
  28.     retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
  29.     if (retval != sizeof usb_dev->descriptor) {
  30.         mutex_unlock(&usb_bus_list_lock);
  31.         dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
  32.                 dev_name(&usb_dev->dev), retval);
  33.         return (retval < 0) ? retval : -EMSGSIZE;
  34.     }
  35. //这里面就是很熟悉的代码了
  36. //device_add(dev);
  37.     retval = usb_new_device (usb_dev);
  38.     if (retval) {
  39.         dev_err (parent_dev, "can't register root hub for %s, %d\n",
  40.                 dev_name(&usb_dev->dev), retval);
  41.     }
  42.     mutex_unlock(&usb_bus_list_lock);

  43.     if (retval == 0) {
  44.         spin_lock_irq (&hcd_root_hub_lock);
  45.         hcd->rh_registered = 1;
  46.         spin_unlock_irq (&hcd_root_hub_lock);

  47.         /* Did the HC die before the root hub was registered? */
  48.         if (hcd->state == HC_STATE_HALT)
  49.             usb_hc_died (hcd);    /* This time clean up */
  50.     }

  51.     return retval;
  52. }

   hub的设备出生后,就要找驱动;哪里找呢?看关键字<usb_device_type,for_devices>
看代码很多后,才发现,所谓usb驱动分为接口驱动和设备驱动,大多时候,网友口口相传驱动都指定为接口驱动;而我们这里讲的是设备驱动,据我对代码的查看,在usb hub驱动时找到一例;至于其他地方,我们不要去理会了,少则得,多则惑;

     后来,我界定,这种驱动还只是属于设备创建的一部分,它只是创建接口设备;
代码的起始点:retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);


点击(此处)折叠或打开

  1. struct usb_device_driver usb_generic_driver = {
  2.     .name = "usb",
  3.     .probe = generic_probe,
  4.     .disconnect = generic_disconnect,
  5. #ifdef    CONFIG_PM
  6.     .suspend = generic_suspend,
  7.     .resume = generic_resume,
  8. #endif
  9.     .supports_autosuspend = 1,
  10. }


 

点击(此处)折叠或打开

  1. /**
  2. * usb_register_device_driver - register a USB device (not interface) driver
  3. * @new_udriver: USB operations for the device driver
  4. * @owner: module owner of this driver.
  5. *
  6. * Registers a USB device driver with the USB core. The list of
  7. * unattached devices will be rescanned whenever a new driver is
  8. * added, allowing the new driver to attach to any recognized devices.
  9. * Returns a negative error code on failure and 0 on success.
  10. */
  11. int usb_register_device_driver(struct usb_device_driver *new_udriver,
  12.         struct module *owner)
  13. {
  14.     int retval = 0;

  15.     if (usb_disabled())
  16.         return -ENODEV;
  17. //对devices;主要是Mark一下,引起注意;
  18. //在总线匹配中,区分接口设备和usb设备<usb_device_type,>
  19.     new_udriver->drvwrap.for_devices = 1;
  20.     new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
  21.     new_udriver->drvwrap.driver.bus = &usb_bus_type;//所属总线;
  22.     new_udriver->drvwrap.driver.probe = usb_probe_device;
  23.     new_udriver->drvwrap.driver.remove = usb_unbind_device;
  24.     new_udriver->drvwrap.driver.owner = owner;
  25. //通用设备驱动的注册
  26.     retval = driver_register(&new_udriver->drvwrap.driver);

  27.     if (!retval) {
  28.         pr_info("%s: registered new device driver %s\n",
  29.             usbcore_name, new_udriver->name);
  30.         usbfs_update_special();
  31.     } else {
  32.         printk(KERN_ERR "%s: error %d registering device "
  33.             "    driver %s\n",
  34.             usbcore_name, retval, new_udriver->name);
  35.     }

  36.     return retval;
  37. }



上面就是usb设备类型的驱动,只要是满足{usb_device_type,for_devices==1}的设备,都会来找他配对;然后生出{usb_if_device_type,for_devices==0}这样的设备;
usb_device_type,usb_if_device_type为usb设备的类型,用来总线匹配驱动。for_devices是驱动中设置,用来总线匹配匹配。
需要牢记一点,出生的设备最新还是需要在那根红线usb_bus_type上仔细找usb_device_match驱动usb_generic_driver;
usb hub 3 驱动的匹配:
只要是驱动,必然有一个标准的方式

按照驱动套路:
driver_register-->bus_add_driver-->driver_attach-->__driver_attach-->,(关键位置出来了,总线匹配)
-->driver_probe_device-->drv->probe==驱动(usb_probe_device)-->udriver->probe==通用驱动(generic_probe)。

驱动查找:

点击(此处)折叠或打开

  1. static int __driver_attach(struct device *dev, void *data)
  2. {
  3.     struct device_driver *drv = data;


  4. //这个时候就是总线找设备:usb_device_match,和
  5. //看之前的关键字关键字<usb_device_type,for_devices>

  6.     if (!driver_match_device(drv, dev))//总线匹配;见代码注释
  7.         return 0;

  8.     if (dev->parent) /* Needed for USB */
  9.         down(&dev->parent->sem);
  10.     down(&dev->sem);
  11.     if (!dev->driver)
  12.         driver_probe_device(drv, dev);//最终会调用的函数driver_probe_device;
  13.     up(&dev->sem);
  14.     if (dev->parent)
  15.         up(&dev->parent->sem);

  16.     return 0;
  17. }



//总线匹配:

点击(此处)折叠或打开

  1. static int usb_device_match(struct device *dev, struct device_driver *drv)
  2. {
  3.     /* devices and interfaces are handled separately */
  4.     if (is_usb_device(dev)) {//设备驱动的路口<usb_device_type>

  5.         /* interface drivers never match devices */
  6. //这里需要看usb.c里面的.
  7. //匹配到usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
  8.         if (!is_usb_device_driver(drv))//路口字<for_devices>
  9.             return 0;

  10.         /* TODO: Add real matching code */
  11.         return 1;//这里就告诉我们,这是usb_device_type,且for_devices==1;

  12.     } else if (is_usb_interface(dev)) {//接口设备的路口,后面再来弄;
  13.         struct usb_interface *intf;
  14.         struct usb_driver *usb_drv;
  15.         const struct usb_device_id *id;

  16.         /* device drivers never match interfaces */
  17.         if (is_usb_device_driver(drv))
  18.             return 0;

  19.         intf = to_usb_interface(dev);
  20.         usb_drv = to_usb_driver(drv);

  21.         id = usb_match_id(intf, usb_drv->id_table);
  22.         if (id)
  23.             return 1;

  24.         id = usb_match_dynamic_id(intf, usb_drv);
  25.         if (id)
  26.             return 1;
  27.     }

  28.     return 0;
  29. }

  30. //device的探测函数
  31. static int usb_probe_device(struct device *dev)
  32. {
  33.     struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
  34.     struct usb_device *udev = to_usb_device(dev);
  35.     int error = -ENODEV;

  36.     dev_dbg(dev, "%s\n", __func__);

  37.     /* TODO: Add real matching code */

  38.     /* The device should always appear to be in use
  39.      * unless the driver suports autosuspend.
  40.      */
  41.     udev->pm_usage_cnt = !(udriver->supports_autosuspend);

  42.     error = udriver->probe(udev);//usb_driver,回到通用驱动usb_generic_driver
  43.     return error;
  44. }




//通用驱动探测


点击(此处)折叠或打开

  1. static int generic_probe(struct usb_device *udev)
  2. {
  3.     int err, c;

  4.     /* Choose and set the configuration. This registers the interfaces
  5.      * with the driver core and lets interface drivers bind to them.
  6.      */
  7.     if (usb_device_is_owned(udev))
  8.         ; /* Don't configure if the device is owned */
  9.     else if (udev->authorized == 0)
  10.         dev_err(&udev->dev, "Device is not authorized for usage\n");
  11.     else {
  12.         c = usb_choose_configuration(udev);
  13.         if (c >= 0) {
  14. // 既然已经选好配置了,那就告诉设备选好的配置,这个过程是在usb_set_configuration()中完成的
  15. //控制器和外设(hub)的通讯
  16.             err = usb_set_configuration(udev, c);//这里又会生仔(设备)哟;
  17.             if (err) {
  18.                 dev_err(&udev->dev, "can't set config #%d, error %d\n",c, err);
  19.                 /* This need not be fatal. The user can try to
  20.                  * set other configurations. */
  21.             }
  22.         }
  23.     }
  24.     /* USB device state == configured ... usable */
  25.     usb_notify_add_device(udev);

  26.     return 0;
  27. }


流程走完了;

这里完成后,整个驱动到了一个新的阶段,usb的枚举阶段的设备配置就完成;配置设备的含义==控制器讲:"你这个设备能够提供这么强大的力量,我选择一种"。
真正usb的功能驱动才刚刚开始,通常讲mass storage,webcam,包括hub的真正的驱动。

之前讲的那些驱动,都是些皮毛,还没有到肉,至少我们还没有弄明白,我们没有学会真正地控制usb;其实里面有好多的usb设备信息读取,我都漏掉,再整理的时候,找个时间再补充上每一章上去;
在用户态下编程可以通过main()的来传递命令行参数,而编写一个内核模块则通过module_param()

module_param宏是Linux 2.6内核中新增的,该宏被定义在include/linux/moduleparam.h文件中,具体定义如下

#define module_param(name, type, perm)               
    module_param_named(name, name, type, perm)

其中使用了 3 个参数:要传递的参数变量名, 变量的数据类型, 以及访问参数的权限。

<<<

perm参数的作用是什么?

最后的 module_param 字段是一个权限值,表示此参数在sysfs文件系统中所对应的文件节点的属性。你应当使用 <linux/stat.h> 中定义的值. 这个值控制谁可以存取这些模块参数在 sysfs 中的表示.当perm为0时,表示此参数不存在 sysfs文件系统下对应的文件节点。 否则, 模块被加载后,在/sys/module/ 目录下将出现以此模块名命名的目录, 带有给定的权限.。
权限在include/linux/stat.h中有定义
比如:
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100

#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010

#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001

使 用 S_IRUGO 作为参数可以被所有人读取, 但是不能改变; S_IRUGO|S_IWUSR 允许 root 来改变参数. 注意, 如果一个参数被 sysfs 修改, 你的模块看到的参数值也改变了, 但是你的模块没有任何其他的通知. 你应当不要使模块参数可写, 除非你准备好检测这个改变并且因而作出反应.


这个宏定义应当放在任何函数之外, 典型地是出现在源文件的前面.定义如:

static char *whom = "world";
static int howmany = 1;
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);

模块参数支持许多类型:

bool
invbool 一个布尔型( true 或者 false)值(相关的变量应当是 int 类型). invbool 类型颠倒了值, 所以真值变成 false, 反之亦然. charp :一个字符指针值. 内存为用户提供的字串分配, 指针因此设置. int
long
short
uint
ulong
ushort 基本的变长整型值. 以 u 开头的是无符号值.
数组参数, 用逗号间隔的列表提供的值, 模块加载者也支持. 声明一个数组参数, 使用:
module_param_array(name,type,num,perm);
这里 name 是你的数组的名子(也是参数名), type 是数组元素的类型, num 是一个整型变量, perm 是通常的权限值. 如果数组参数在加载时设置, num 被设置成提供的数的个数. 模块加载者拒绝比数组能放下的多的值.


测试模块,源程序hello.c内容如下:
#include <linux/init.h> #include <linux/module.h>
#include <linux/moduleparam.h>       

MODULE_LICENSE("Dual BSD/GPL");    

static char *who= "world";            
static int times = 1;      
module_param(times,int,S_IRUSR);    
module_param(who,charp,S_IRUSR);  

static int hello_init(void)      
{
    int i;
    for(i=0;i<times;i++)
       printk(KERN_ALERT "(%d) hello, %s!\n",i,who);
     return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT"Goodbye, %s!\n",who);
}

module_init(hello_init);
module_exit(hello_exit);

编译生成可执行文件hello

插入:
# insmod hello who="world" times=5 出现5次"hello,world!":
#(1)hello,world!
#(2)hello,world!

#(3)hello,world!
#(4)hello,world!
#(5)hello,world!

卸载: # rmmod hello 出现:
#Goodbye,world!

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值