Chinaunix首页 | 论坛 | 博客
  • 博客访问: 962613
  • 博文数量: 109
  • 博客积分: 554
  • 博客等级: 中士
  • 技术积分: 2577
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-04 12:49
文章分类

全部博文(109)

文章存档

2019年(5)

2016年(7)

2015年(9)

2014年(1)

2013年(71)

2012年(16)

分类: 嵌入式

2013-06-22 17:45:47

在2.6内核中可以通过用户空间的udev/mdev自动为设备建立节点,省去了手工建立节点的麻烦

1. 传统的手动建立设备节点方法

其实也不是很麻烦,写个建立节点的脚本就行,LDD3中有很多例子

  1. #!/bin/sh
  2. module="scullp"
  3. device="scullp"
  4. mode="664"

  5. # Group: since distributions do it differently, look for wheel or use staff
  6. if grep '^staff:' /etc/group > /dev/null; then
  7. group="staff"
  8. else
  9. group="wheel"
  10. fi

  11. # remove stale nodes
  12. rm -f /dev/${device}?

  13. # invoke insmod with all arguments we got
  14. # and use a pathname, as newer modutils don't look in . by default
  15. /sbin/insmod -f ./$module.ko $* || exit 1

  16. major=`cat /proc/devices | awk "\\$2==\"$module\" {print \\$1}"`

  17. mknod /dev/${device}0 c $major 0
  18. mknod /dev/${device}1 c $major 1
  19. mknod /dev/${device}2 c $major 2
  20. mknod /dev/${device}3 c $major 3
  21. ln -sf ${device}0 /dev/${device}

  22. # give appropriate group/permissions
  23. chgrp $group /dev/${device}[0-3]
  24. chmod $mode /dev/${device}[0-3]

2. 使用udev/mdev机制自动建立节点

2.1 内核API
 1.

点击(此处)折叠或打开

  1. #define class_create(owner, name) \
  2. ({ \
  3.          static struct lock_class_key __key; \
  4.          __class_create(owner, name, &__key); \
  5. })
 /* This is a #define to keep the compiler from merging different
  * instances of the __key variable */

2.

点击(此处)折叠或打开

  1. extern struct device *device_create(struct class *cls, struct device *parent,
  2.                                     dev_t devt, void *drvdata,
  3.                                     const char *fmt, ...)
  4.                                     __attribute__((format(printf, 5, 6)));
/**
 * device_create - creates a device and registers it with sysfs
 * @class: pointer to the struct class that this device should be registered to
 * @parent: pointer to the parent struct device of this new device, if any
 * @devt: the dev_t for the char device to be added
 * @drvdata: the data to be added to the device for callbacks
 * @fmt: string for the device's name
 *
 * This function can be used by char device classes.  A struct device
 * will be created in sysfs, registered to the specified class.
 *
 * A "dev" file will be created, showing the dev_t for the device, if
 * the dev_t is not 0,0.
 * If a pointer to a parent struct device is passed in, the newly created
 * struct device will be a child of that device in sysfs.
 * The pointer to the struct device will be returned from the call.
 * Any further sysfs files that might be required can be created using this
 * pointer.
 *
 * Note: the struct class passed to this function must have previously
 * been created with a call to class_create().
 */
3

点击(此处)折叠或打开

  1. extern void class_destroy(struct class *cls);
/**
 * class_destroy - destroys a struct class structure
 * @cls: pointer to the struct class that is to be destroyed
 *
 * Note, the pointer to be destroyed must have been created with a call
 * to class_create().
 */
4

点击(此处)折叠或打开

  1. extern void device_destroy(struct class *cls, dev_t devt);
参数含义:
/**
 * device_destroy - removes a device that was created with device_create()
 * @class: pointer to the struct class that this device was registered with
 * @devt: the dev_t of the device that was previously registered
 *
 * This call unregisters and cleans up a device that was created with a
 * call to device_create().
 */

2.2 使用方法

加载驱动时
struct class *myclass ;
class_create(THIS_MODULE, “my_device_driver”);
device_create(myclass, NULL, MKDEV(major_num, minor_num), NULL, “my_device”);

卸载驱动时:
device_destroy(myclass, MKDEV(major_num, minor_num));
class_destroy(my_class);

2.3 例子


  1. /*
  2.  * led.c
  3.  */
  4. #define DEBUG

  5. #include <linux/miscdevice.h>
  6. #include <linux/delay.h>
  7. #include <asm/irq.h>
  8. #include <mach/regs-gpio.h>
  9. #include <mach/hardware.h>
  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/mm.h>
  14. #include <linux/fs.h>
  15. #include <linux/types.h>
  16. #include <linux/delay.h>
  17. #include <linux/moduleparam.h>
  18. #include <linux/slab.h>
  19. #include <linux/errno.h>
  20. #include <linux/ioctl.h>
  21. #include <linux/cdev.h>
  22. #include <linux/string.h>
  23. #include <linux/list.h>
  24. #include <linux/pci.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/atomic.h>
  27. #include <asm/unistd.h>

  28. #ifdef DEBUG
  29. #define dbg(arg...) printk(KERN_DEBUG arg)
  30. #else
  31. #define dbg(arg...)
  32. #endif

  33. #define DEVICE_NAME "leds"

  34. #define NUM_LEDS (4)

  35. struct led_desc{
  36.     unsigned long pin;
  37.     unsigned long cfg;
  38.     char *name;
  39. };

  40. static struct led_desc leds[] = {
  41.     {S3C2410_GPB5, S3C2410_GPB5_OUTP, "LED1"},
  42.     {S3C2410_GPB6,S3C2410_GPB6_OUTP, "LED2"},
  43.     {S3C2410_GPB7,S3C2410_GPB7_OUTP, "LED3"},
  44.     {S3C2410_GPB8,S3C2410_GPB8_OUTP, "LED4"},
  45. };

  46. struct led_dev{
  47.     char *name;
  48.     unsigned long pin;
  49.     unsigned long cfg;
  50.     struct cdev cdev;
  51. } *led_devp[NUM_LEDS];

  52. struct class *led_class;
  53. static dev_t led_dev_number;

  54. static int mini2440_leds_open(struct inode *inode, struct file *filp)
  55. {

  56.     struct led_dev *dev;
  57.     dev = container_of(inode->i_cdev,struct led_dev,cdev);
  58.     filp->private_data = dev;
  59.     printk(KERN_DEBUG "%s", __FUNCTION__);
  60.     return 0;
  61. }

  62. static int mini2440_leds_close(struct inode *node, struct file *filp)
  63. {
  64.     printk(KERN_DEBUG "%s", __FUNCTION__);
  65.     return 0;
  66. }

  67. static int mini2440_leds_ioctl(struct inode *inode,struct file *filp,
  68.                                unsigned int cmd, unsigned long arg)
  69. {
  70.     struct led_dev *led_devp = filp->private_data;
  71.     switch(cmd) {
  72.     case 0:
  73.     case 1:
  74.         if (arg > 4) {
  75.             return -EINVAL;
  76.         }
  77.         s3c2410_gpio_setpin(led_devp->pin, !cmd);
  78.         return 0;
  79.     default:
  80.         return -EINVAL;
  81.     }
  82. }

  83. static struct file_operations led_fops = {
  84.     .owner    =    THIS_MODULE,
  85.     .open = mini2440_leds_open,
  86.     .release = mini2440_leds_close,
  87.     .ioctl    =    mini2440_leds_ioctl,
  88. };

  89. static int __init dev_init(void)
  90. {
  91.     int ret;
  92.     int i;
  93.     /* 注册设备,动态分配设备号 */
  94.     if(alloc_chrdev_region(&led_dev_number, 0, NUM_LEDS, DEVICE_NAME) < 0){
  95.         printk(KERN_DEBUG "Can't register device.\n");
  96.         return -1;
  97.     }
  98.     /* 创建sysfs 目录 */
  99.     led_class = class_create(THIS_MODULE, DEVICE_NAME);
  100.     /* 配置gpio */
  101.     for (i = 0; i < 4; i++) {
  102.         led_devp[i] = kmalloc(sizeof(struct led_dev),GFP_KERNEL);
  103.         if(!led_devp[i]){
  104.             printk("Bad Kmalloc.\n");
  105.             return -ENOMEM;
  106.         }
  107.         led_devp[i]->pin = leds[i].pin;
  108.         led_devp[i]->cfg = leds[i].cfg;
  109.         led_devp[i]->name = leds[i].name;
  110.         s3c2410_gpio_cfgpin(led_devp[i]->pin, led_devp[i]->cfg);
  111.         s3c2410_gpio_setpin(led_devp[i]->pin, 0);

  112.         /* 绑定fops与cdev */
  113.         cdev_init(&led_devp[i]->cdev, &led_fops);
  114.         led_devp[i]->cdev.owner = THIS_MODULE;
  115.         /* 绑定设备号与cdev */
  116.         ret = cdev_add(&led_devp[i]->cdev, led_dev_number + i, 1);
  117.         if(ret){
  118.             printk("Bad cdev\n");
  119.             return ret;
  120.         }

  121.         /* sysfs */
  122.         device_create(led_class, NULL, MKDEV(MAJOR(led_dev_number),i ), led_devp[i],"led%d" , i);
  123.     }
  124.     printk (DEVICE_NAME"\tinitialized\n");

  125.     return 0;
  126. }

  127. static void __exit dev_exit(void)
  128. {
  129.     int i;
  130.     unregister_chrdev_region(led_dev_number, NUM_LEDS);

  131.     for (i = 0; i < NUM_LEDS; ++i)
  132.     {
  133.         device_destroy(led_class, MKDEV(MAJOR(led_dev_number), i));
  134.         cdev_del(&led_devp[i]->cdev);
  135.         kfree(led_devp[i]);
  136.     }

  137.     class_destroy(led_class);

  138. }

  139. module_init(dev_init);
  140. module_exit(dev_exit);
  141. MODULE_LICENSE("GPL");
  142. MODULE_AUTHOR("EnzoFang");


  1. /*
  2.  * test_led.c
  3.  */

  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <sys/ioctl.h>
  8. #include <fcntl.h>
  9. #include <stdlib.h>
  10. struct bit{
  11.     unsigned bit:1;
  12. };
  13.     
  14. int main(int argc, char *argv[])
  15. {
  16.     struct bit a;
  17.     a.bit = 0;
  18.     int fd0 = open("/dev/led0", O_RDWR);
  19.     int fd1 = open("/dev/led1", O_RDWR);
  20.     int fd2 = open("/dev/led2", O_RDWR);
  21.     int fd3 = open("/dev/led3", O_RDWR);
  22.     while(1){
  23.         a.bit = ~a.bit;
  24.         ioctl(fd0, a.bit);
  25.         sleep(1);

  26.         ioctl(fd1, a.bit);
  27.         sleep(1);
  28.         
  29.         ioctl(fd2, a.bit);
  30.         sleep(1);
  31.         ioctl(fd3, a.bit);
  32.         sleep(1);

  33.     }

  34.     return 0;
  35. }

结果:
在使用busybox制作根文件系统需要支持mdev,并且在rcS中有以下语句
echo /sbin/mdev > /proc/sys/kernel/hotplug
        /sbin/mdev -s
才能在加载驱动时,自动生成节点

  1. # cd leds/
  2. # pwd
  3. /sys/class/leds
  4. # ls
  5. led0 led1 led2 led3

阅读(4956) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~