Chinaunix首页 | 论坛 | 博客
  • 博客访问: 371966
  • 博文数量: 50
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 641
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-09 22:35
个人简介

不怕你失败,就怕你爬不起来。

文章分类

全部博文(50)

文章存档

2014年(50)

我的朋友

分类: 嵌入式

2014-05-29 22:33:59

实现平台:Ubuntu 14.04  + TQ2440
实现工具:arm-linux-gcc + SecureCRT +
实现内容:
    用户空间                    内核空间                实现结果
    open                          led_open                led全亮
    close                          led_close                led全灭
    read                           led_read                读取led状态(亮或灭)
    write                          led_write                批量设置led状态
    ioctl                           led_ioctl                 逐个设置led状态

实现过程:
[1] 原材料:无非就是头文件了

点击(此处)折叠或打开

  1. #define _LED_H_

  2. #include <linux/kernel.h>
  3. #include <linux/module.h>
  4. #include <linux/fs.h>
  5. #include <linux/types.h>
  6. #include <linux/cdev.h>
  7. #include <linux/uaccess.h>
  8. #include <linux/device.h>
  9. #include <mach/regs-gpio.h>
  10. #include <mach/hardware.h>
  11. #include <linux/ioctl.h>

  12. #define LED_ON 1 //
  13. #define LED_OFF 0 //
  14. int nMajor = 0; //主设备号
  15. int nMinor = 0; //次设备号

  16. //led 端口表
  17. static unsigned long led_port_table[] =
  18. {
  19.   S3C2410_GPB5,
  20.   S3C2410_GPB6,
  21.   S3C2410_GPB7,
  22.   S3C2410_GPB8,
  23. };

  24. //led 输出状态表
  25. static unsigned int led_state_table[] =
  26. {
  27.   S3C2410_GPB5_OUTP,
  28.   S3C2410_GPB6_OUTP,
  29.   S3C2410_GPB7_OUTP,
  30.   S3C2410_GPB8_OUTP,
  31. };
  32.   
  33. //申请一个设备号
  34. dev_t dev;
  35.   
  36. //申请一个class设备类
  37. static struct class *led_class;
  38.    
  39. //申请一个cdev设备结构体
  40. struct cdev *led_cdev = NULL;

  41. /******************************************************************
  42.  *函数接口声明
  43.  ******************************************************************/
  44. static int led_open(struct inode *inode, struct file *filp);

  45. static ssize_t led_read(struct file *filp,char __user *buf,
  46.                         size_t nSize, loff_t * pos);
  47.                         
  48. static ssize_t led_write(struct file *filp, const char __user *buf,
  49.                         size_t size,loff_t *pos);
  50.                         
  51. static int led_ioctl(struct inode *inode, struct file *file,
  52.                           unsigned int cmd, unsigned long arg);
  53.                           
  54. static int led_close(struct inode *inode, struct file *filp);

  55. /******************************************************************
  56.  *led操作接口
  57.  ******************************************************************/
  58. struct file_operations led_fops =
  59. {
  60.   .owner = THIS_MODULE,
  61.   .open = led_open,
  62.   .read = led_read,
  63.   .write = led_write,
  64.   .ioctl = led_ioctl,
  65.   .release = led_close,
  66. };

  67. #endif // _LED_H_

[2] 模块框架

点击(此处)折叠或打开

  1. ;这个过程是必须要懂的,不会的请先学习基础,由于篇幅较长,就不贴出代码了
  2. static int __init led_module_init()
  3. {
  4. /*
  5. ;初始化led
  6. ;申请设备号
  7. ;注册设备
  8. ;绑定设备文件操作接口
  9. ;添加设备类
  10. ;在设备类下创建设备节点
  11. */
  12. }

  13. static void __exit led_module_exit()
  14. {
  15. /*
  16. ;删除设备节点
  17. ;删除设备类
  18. ;释放设备结构
  19. ;释放设备号
  20. */
  21. }

  22. module_init(led_module_init);
  23. module_exit(led_module_exit_;

  24. MODULE_LICENSE("GPL");
  25. MODULE_AUTHOR("Reyn");
  26. MODULE_DESCRIPTION("testing for led_driver")

[3] 操作接口设计

需要的函数接口:

点击(此处)折叠或打开

  1. struct file_operations led_fops =
  2. {
  3.   .owner = THIS_MODULE,
  4.   .open = led_open,
  5.   .read = led_read,
  6.   .write = led_write,
  7.   .ioctl = led_ioctl,
  8.   .release = led_close,
  9. };

函数接口原型:

点击(此处)折叠或打开

  1. static int led_open(struct inode *inode, struct file *filp);

  2. static ssize_t led_read(struct file *filp,char __user *buf, size_t nSize, loff_t *pos);
  3.                         
  4. static ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *pos);
  5.                         
  6. static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
  7.                           
  8. static int led_close(struct inode *inode, struct file *filp)

[4] 逐个说明:

    [+] led_open() 就是点亮四盏led,很简单,直接看代码,就不解释了:

点击(此处)折叠或打开

  1. /******************************************************************
  2.  *函数名称:led_open
  3.  *函数描述:打开led灯,全亮
  4.  *返回值     :void
  5.  ******************************************************************/

  6. static int led_open(struct inode *inode, struct file *filp)
  7. {
  8.   int nLedNb = 0;
  9.   for(; nLedNb<4; ++nLedNb)
  10.   {
  11.     s3c2410_gpio_setpin(led_port_table[nLedNb], ~(LED_ON)); //点亮一盏灯
  12.     printk(KERN_INFO "[Kernel] led%d on.\n", nLedNb);
  13.   }

  14.   return 0;
  15. }

    [+] led_close() 同样很简单,熄灭四盏灯即可,上代码:

点击(此处)折叠或打开

  1. /******************************************************************
  2.  *函数名称:led_close
  3.  *函数描述:关闭led灯,全灭
  4.  *返回值     :成功返回0,失败返回其他值
  5.  ******************************************************************/

  6. static int led_close(struct inode *inode, struct file *filp)
  7. {
  8.   int nLedNb = 0;
  9.   for(nLedNb = 0; nLedNb < 4; ++nLedNb)
  10.   {
  11.     s3c2410_gpio_setpin(led_port_table[nLedNb], ~(LED_OFF));
  12.   }
  13.   
  14.   printk(KERN_INFO "[Kernel] led all off.\n");
  15.   
  16.   return 0;
  17. }

    [+] led_read() 需要读取led管脚状态,根据s3c2410_gpio_getpin()的返回值可以判断:若返回值为0,则led灯是亮的,否则为灭。同时,led_read()接口要求将led灯总体的亮灭状态传送给用户空间,使用copy_to_user()可以做到这一点。

点击(此处)折叠或打开

  1. /******************************************************************
  2.  *函数名称:led_read
  3.  *函数描述:读取led灯状态
  4.  *返回值 :返回复制长度
  5.  ******************************************************************/
  6. static ssize_t led_read(struct file *filp,char __user *buf,
  7.                         size_t nSize, loff_t * pos)
  8. {
  9.   int nStatus = 0; //存储LED状态
  10.   int nLedNb = 0; //LED灯编号
  11.   int nCopyLen = 0;//复制信息的长度 
  12.   char status_buf[20] = {};

  13.   for(; nLedNb<4; ++nLedNb)
  14.   {
  15.     nStatus = s3c2410_gpio_getpin(led_port_table[nLedNb]);
  16.     if(nStatus == 0)
  17.     {
  18.       printk(KERN_INFO "[Kernel] led%d %s\n", nLedNb, "on");
  19.       strcat(status_buf, "on ");
  20.     }
  21.     else
  22.     {
  23.       printk(KERN_INFO "[Kernel] led%d %s\n", nLedNb, "off");
  24.       strcat(status_buf, "off ");
  25.     }
  26.   }

  27.   //将LED灯的状态传给用户空间
  28.   nCopyLen = strlen(status_buf);
  29.   copy_to_user(buf, status_buf, nCopyLen);
  30.   printk(KERN_INFO "[Kernel] copy to user:%d.\n", nCopyLen);
  31.   
  32.   return nCopyLen;
  33. }

    [+] led_write() 稍复杂一些,需要从用户空间接收参数(见参数说明)以设置led灯的状态,同时返回写入的长度。
    使用copy_from_user()可以接收参数,根据参数进行点灯操作。

点击(此处)折叠或打开

  1. /******************************************************************
  2.  *函数名称:led_write
  3.  *函数描述:批量设置led灯状态
  4.  * cStatus:[0/1/2/3/4]
  5.  * 0 - 1 - 2 - 3 - 4
  6.  * 全灭 1-on 1,2-on 1,2,3-on all-on
  7.  *返回值 :成功返回复制的长度,失败返回-1
  8.  ******************************************************************/
  9. static ssize_t led_write(struct file *filp, const char __user *buf,
  10.                         size_t size,loff_t *pos)
  11. {
  12.   char cStatus;
  13.   int nCopyLen = sizeof(char);
  14.  
  15.   //从用户空间接收参数
  16.   nCopyLen = copy_from_user(&cStatus, buf, nCopyLen) ? (-1) : nCopyLen;
  17.   printk(KERN_INFO "[Kernel] copy from user:%d.\n", nCopyLen);
  18.   printk(KERN_INFO "[Kernel] write led status %c.\n", cStatus);
  19.                                                       
  20.   switch(cStatus)
  21.   {
  22.       case '0':
  23.       {
  24.           s3c2410_gpio_setpin(led_port_table[0], ~(LED_OFF));
  25.           s3c2410_gpio_setpin(led_port_table[1], ~(LED_OFF));
  26.           s3c2410_gpio_setpin(led_port_table[2], ~(LED_OFF));
  27.           s3c2410_gpio_setpin(led_port_table[3], ~(LED_OFF));
  28.           printk(KERN_INFO "[Kernel] led all off.\n");
  29.       }
  30.       break;
  31.       
  32.       case '1':
  33.       {
  34.           s3c2410_gpio_setpin(led_port_table[0], ~(LED_ON));
  35.           s3c2410_gpio_setpin(led_port_table[1], ~(LED_OFF));
  36.           s3c2410_gpio_setpin(led_port_table[2], ~(LED_OFF));
  37.           s3c2410_gpio_setpin(led_port_table[3], ~(LED_OFF));
  38.           printk(KERN_INFO "[Kernel] led 1 on.\n");
  39.       }
  40.       break;
  41.       
  42.       case '2':
  43.       {
  44.           s3c2410_gpio_setpin(led_port_table[0], ~(LED_ON));
  45.           s3c2410_gpio_setpin(led_port_table[1], ~(LED_ON));
  46.           s3c2410_gpio_setpin(led_port_table[2], ~(LED_OFF));
  47.           s3c2410_gpio_setpin(led_port_table[3], ~(LED_OFF));
  48.           printk(KERN_INFO "[Kernel] led 1,2 on.\n");
  49.       }
  50.       break;
  51.       
  52.       case '3':
  53.       {
  54.           s3c2410_gpio_setpin(led_port_table[0], ~(LED_ON));
  55.           s3c2410_gpio_setpin(led_port_table[1], ~(LED_ON));
  56.           s3c2410_gpio_setpin(led_port_table[2], ~(LED_ON));
  57.           s3c2410_gpio_setpin(led_port_table[3], ~(LED_OFF));
  58.           printk(KERN_INFO "[Kernel] led 1,2,3 on.\n");
  59.       }
  60.       break;
  61.       
  62.       case '4':
  63.       {
  64.           s3c2410_gpio_setpin(led_port_table[0], ~(LED_ON));
  65.           s3c2410_gpio_setpin(led_port_table[1], ~(LED_ON));
  66.           s3c2410_gpio_setpin(led_port_table[2], ~(LED_ON));
  67.           s3c2410_gpio_setpin(led_port_table[3], ~(LED_ON));
  68.           printk(KERN_INFO "[Kernel] led all on.\n");
  69.       }
  70.       break;
  71.       
  72.       default:
  73.           printk(KERN_INFO "[Error] unrecognize status %c.\n", cStatus);
  74.           break;
  75.   }

  76.   return nCopyLen;
  77. }

    [+] led_ioctl() 同样根据用户空间的命令和参数进行操作,只不过不再使用copy_xxx_user()接口,因为不需要给用户空间传递信息,因此根据用户空间ioctl()传递进来的参数即可执行操作。


点击(此处)折叠或打开

  1. /******************************************************************
  2.  *函数名称:led_ioctl
  3.  *函数描述:逐个设置led灯的状态
  4.  *参数描述:cmd表示led状态,arg标识led编号
  5.  *返回值 :成功返回0,失败返回其他值
  6.  ******************************************************************/
  7. static int led_ioctl(struct inode *inode, struct file *file,
  8.                       unsigned int cmd, unsigned long arg)
  9. {
  10.   if(arg > 4 || arg < 0)
  11.   {
  12.     return -EINVAL;
  13.   }
  14.   
  15.   switch(cmd)
  16.   {
  17.     case LED_OFF:
  18.     {
  19.       s3c2410_gpio_setpin(led_port_table[arg], 1);
  20.       printk(KERN_INFO "[Kernel] led%ld off.\n", arg);
  21.       return 0;
  22.     }

  23.     case LED_ON:
  24.     {
  25.       s3c2410_gpio_setpin(led_port_table[arg], 0);
  26.       printk(KERN_INFO "[Kernel] led%ld on.\n", arg);
  27.       return 0;
  28.     }

  29.     default:
  30.       return -EINVAL;
  31.   }
  32. }

至此,全部操作接口设计完毕。


[4] 编译:

给模块写个Makefile:

点击(此处)折叠或打开

  1. # Led Module Makefile
  2. OBJ := led.o
  3. KERNDIR := /opt/EmbedSky/linux-2.6.30.4/
  4. INSTALL := /home/reyn/share/out/
  5. CC := arm-linux-gcc
  6. obj-m := $(OBJ)
  7. all:
  8.     $(MAKE) -C $(KERNDIR) M=$(PWD) modules
  9.     cp *.ko $(INSTALL)
  10. modules:
  11.     $(MAKE) -C $(KERNDIR) M=$(PWD) modules
  12. install:
  13.     cp *.ko $(INSTALL)
  14. .PHONY:modules clean
  15. clean:
  16.     rm *.mod.c *.o *.order *.ko *.symvers *~
  17.     rm $(INSTALL)*.ko

编译成模块:

点击(此处)折叠或打开

  1. reyn@ubuntu:led$ make
  2. make -C /opt/EmbedSky/linux-2.6.30.4/ M=/home/reyn/share/drivers/led modules
  3. make[1]: 正在进入目录 `/opt/EmbedSky/linux-2.6.30.4'
  4.   CC [M] /home/reyn/share/drivers/led/led.o
  5.   Building modules, stage 2.
  6.   MODPOST 1 modules
  7.   CC /home/reyn/share/drivers/led/led.mod.o
  8.   LD [M] /home/reyn/share/drivers/led/led.ko
  9. make[1]:正在离开目录 `/opt/EmbedSky/linux-2.6.30.4'
  10. cp *.ko /home/reyn/share/out/

  11. 编译成功的话,会生成一些中间文件和最重要的.ko内核模块文件

  12. reyn@ubuntu:led$ ls
  13. led.c led.ko led.mod.o Makefile Module.symvers
  14. led.h led.mod.c led.o modules.order test

再写个应用程序test_led.c做测试:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <malloc.h>
  8. #include <sys/ioctl.h>

  9. int main(int argc, char **argv)
  10. {
  11.     int nFd = 0;
  12.     char status;
  13.     int nRet = 0;
  14.     char *led_buf;
  15.     int cmd = 1;
  16.     unsigned long arg = 0;
  17.     int ch = 0;

  18. //open:
  19.     printf("[User] Open led, if succeed, all on.\n");
  20.     nFd = open("/dev/led_driver", O_RDWR);
  21.     if(nFd < 0)
  22.     {
  23.         printf("[User] Can't open %s\n", "led_driver");
  24.         return -1;
  25.     }

  26.     
  27. write:
  28.     printf("[User] Ready for writing. \n");
  29.     printf("[User] Please input [0/1/2/3/4]:\n");
  30.     while((status = getchar()) == '\n');
  31.     nRet = write(nFd, &status, sizeof(char));
  32.     if(nRet != 1)
  33.     {
  34.         printf("[User] Write error!\n");
  35.         return -1;
  36.     }
  37.     printf("[User] Write:%d.\n", nRet);
  38.   
  39.     if(ch==0 || ch==1 || ch==2 || ch==3)
  40.     {
  41.         ch++;
  42.         goto write;
  43.     }
  44.     else
  45.     {
  46.         ch = 0;
  47.     }

  48.         
  49. //read:
  50.     printf("[User] Ready for reading.\n");
  51.     getchar();
  52.     led_buf = (char *)malloc(16 * sizeof(char));
  53.     nRet = read(nFd, led_buf, sizeof(char));
  54.     if(nRet < 0)
  55.     {
  56.         printf("[User] Read error.\n");
  57.         return -1;
  58.     }
  59.     printf("[User] Read led status: %s.\n", led_buf);
  60.     free(led_buf);
  61.     
  62.     
  63. ioctl:
  64.     printf("[User] Ready for ioctl.\n");
  65.     for(arg=0; arg<4; arg++)
  66.     {
  67.         while((ch = getchar()) != '\n');
  68.         ioctl(nFd, cmd, arg);
  69.         printf("[User] ioctl%ld cmd:%d arg:%ld.\n", arg, cmd, arg);
  70.     }
  71.     cmd = !(cmd);
  72.     goto ioctl;

  73.     close(nFd);
  74.     
  75.     return 0;
  76. }

写个Makefile,也可以直接输入命令arm-linux-gcc test_led.c -o test_led:

点击(此处)折叠或打开

  1. CC:=arm-linux-gcc

  2. all:
  3.     $(CC) test_led.c -o test_led -Wall -std=c99
  4.     cp test_led /home/reyn/share/out/
  5.     
  6. clean:
  7.     rm *~ write_led
  8.     rm /home/reyn/share/out/test_led
编译:

点击(此处)折叠或打开

  1. reyn@ubuntu:test$ make
  2. arm-linux-gcc test_led.c -o test_led -Wall -std=c99
  3. cp test_led /home/reyn/share/out/

  4. 编译成功的话,会生成可执行二进制文件test_led

  5. reyn@ubuntu:test$ ls
  6. Makefile test_led test_led.c

[4] 测试运行:
    [+] 使用Samba方便快捷地将linux的上述生成的led.ko内核模块文件和test_led二进制文件文件传到windows;
    [+] 把文件拷贝到开发板,此过程可以使用secureCRT的rz命令(需要安装一个lrzsz包,请自行Google之);
    [+] 修改led.ko 和 test_led 的权限
        chmod 777 led.ko test_led
       {经测试,只要修改test_led的权限即可}
    [+] 插入模块:insmod led.ko

点击(此处)折叠或打开

  1. [root@EmbedSky /]# insmod led.ko
  2. [Kernel] led init done.
  3. [Kernel] request dev number.
  4. [Kernel] dev add done.
  5. [major 252] [minor 0] led module inserted.

  6. 此时查看/proc/devices [查看已经加载的设备和分类] 和 /dev [查看所有外部设备的详细信息]
  7. 可以发现设备号申请成功,设备节点也创建起来了:

  8. [root@EmbedSky /]# cat /proc/devices
  9. Character devices:
  10.   1 mem
  11.   4 /dev/vc/0
  12.   4 tty
  13.   5 /dev/tty
  14.   5 /dev/console
  15.   5 /dev/ptmx
  16.   7 vcs
  17.  10 misc
  18.  13 input
  19.  14 sound
  20.  29 fb
  21.  81 video4linux
  22.  89 i2c
  23.  90 mtd
  24. 108 ppp
  25. 116 alsa
  26. 128 ptm
  27. 136 pts
  28. 180 usb
  29. 188 ttyUSB
  30. 189 usb_device
  31. 204 ttySAC
  32. 252 led_driver
  33. 253 usb_endpoint
  34. 254 rtc

  35. Block devices:
  36. 259 blkext
  37.   7 loop
  38.   8 sd
  39.  31 mtdblock
  40.  65 sd
  41. ... ...
  42. ... ...


  43. [root@EmbedSky /]# ls -l /dev
  44. crw-rw---- 1 root root 10, 60 Mar 9 2014 adc
  45. crw-rw---- 1 root root 14, 4 Mar 9 2014 audio
  46. crw-rw---- 1 root root 10, 61 Mar 9 2014 beep
  47. crw-rw---- 1 root root 10, 63 Mar 9 2014 bkl
  48. crw-rw---- 1 root root 10, 59 Mar 9 2014 camera
  49. crw-rw---- 1 root root 5, 1 Mar 9 13:31 console
  50. crw-rw---- 1 root root 116, 0 Mar 9 2014 controlC0
  51. crw-rw---- 1 root root 10, 58 Mar 9 2014 cpu_dma_latency
  52. lrwxrwxrwx 1 root root 14 Mar 9 2014 dsp -> /dev/sound/dsp
  53. crw-rw---- 1 root root 13, 64 Mar 9 2014 event0
  54. crw-rw---- 1 root root 13, 65 Mar 9 2014 event1
  55. crw-rw---- 1 root root 29, 0 Mar 9 2014 fb0
  56. crw-rw---- 1 root root 1, 7 Mar 9 2014 full
  57. crw-rw---- 1 root root 89, 0 Mar 9 2014 i2c-0
  58. crw-rw---- 1 root root 1, 11 Mar 9 2014 kmsg
  59. crw-rw---- 1 root root 10, 62 Mar 9 2014 led
  60. crw-rw---- 1 root root 252, 0 Mar 9 13:29 led_driver
  61. brw-rw---- 1 root root 7, 0 Mar 9 2014 loop0
  62. brw-rw---- 1 root root 7, 1 Mar 9 2014 loop1
  63. ... ...
  64. ... ...

接着运行test_led:

点击(此处)折叠或打开

  1. [root@EmbedSky /]# ./test_led
  2. [User] Open led, if succeed, all on. [打开文件节点]
  3. [Kernel] led0 on.
  4. [Kernel] led1 on.
  5. [Kernel] led2 on.
  6. [Kernel] led3 on.
  7. [User] Ready for writing.              [写文件节点]
  8. [User] Please input [0/1/2/3/4]:
  9. 1
  10. [Kernel] copy from user:1.
  11. [Kernel] write led status 1.
  12. [Kernel] led 1 on.
  13. [User] Write:1.
  14. [User] Ready for writing.              [写文件节点]
  15. [User] Please input [0/1/2/3/4]:
  16. 2
  17. [Kernel] copy from user:1.
  18. [Kernel] write led status 2.
  19. [Kernel] led 1,2 on.
  20. [User] Write:1.
  21. [User] Ready for writing.              [写文件节点]
  22. [User] Please input [0/1/2/3/4]:
  23. 3
  24. [Kernel] copy from user:1.
  25. [Kernel] write led status 3.
  26. [Kernel] led 1,2,3 on.
  27. [User] Write:1.
  28. [User] Ready for writing.             [写文件节点]
  29. [User] Please input [0/1/2/3/4]:
  30. 4
  31. [Kernel] copy from user:1.
  32. [Kernel] write led status 4.
  33. [Kernel] led all on.
  34. [U[Kernel] led0 on
  35. [Kernel] led1 on
  36. [Kernel] led2 on
  37. [Kernel] led3 on
  38. [Kernel] copy to user:12.
  39. ser] Write:1.
  40. [User] Ready for reading.              [读文件节点]
  41. [User] Read led status: on on on on .
  42. [User] Ready for ioctl.                [ioctl操作]
  43. 1
  44. [Kernel] led0 on.
  45. [User] ioctl0 cmd:1 arg:0.

  46. [Kernel] led1 on.
  47. [User] ioctl1 cmd:1 arg:1.

  48. [Kernel] led2 on.
  49. [User] ioctl2 cmd:1 arg:2.

  50. [Kernel] led3 on.
  51. [User] ioctl3 cmd:1 arg:3.
  52. [User] Ready for ioctl.

  53. [Kernel] led0 off.
  54. [User] ioctl0 cmd:0 arg:0.

  55. [Kernel] led1 off.
  56. [User] ioctl1 cmd:0 arg:1.

  57. [Kernel] led2 off.
  58. [User] ioctl2 cmd:0 arg:2.

  59. [Kernel] led3 off.
  60. [User] ioctl3 cmd:0 arg:3.
  61. [User] Ready for ioctl.

  62. [Kernel] led0 on.
  63. [User] ioctl0 cmd:1 arg:0.
  64. ^C[Kernel] led all off.               [关闭文件节点]


[6] 总结:

   [+] 有些时候,开发板默认开启了led,这时进行测试就会失败,因为看不到效果啊。
       所以,就需要手动终止开发板的led进程了。

点击(此处)折叠或打开

  1. [root@EmbedSky /]# ps
  2.   PID USER VSZ STAT COMMAND
  3.     1 root 2096 S init
  4.     2 root 0 SW< [kthreadd]
  5.     3 root 0 SW< [ksoftirqd/0]
  6.     4 root 0 SW< [events/0]
  7.     5 root 0 SW< [khelper]
  8.    11 root 0 SW< [async/mgr]
  9.   242 root 0 SW< [kblockd/0]
  10.   252 root 0 SW< [khubd]
  11.   255 root 0 SW< [kseriod]
  12.   261 root 0 SW< [kmmcd]
  13.   286 root 0 SW [pdflush]
  14.   287 root 0 SW [pdflush]
  15.   288 root 0 SW< [kswapd0]
  16.   333 root 0 SW< [aio/0]
  17.   337 root 0 SW< [nfsiod]
  18.   341 root 0 SW< [crypto/0]
  19.   460 root 0 SW< [mtdblockd]
  20.   580 root 0 SW< [usbhid_resumer]
  21.   596 root 0 SW< [rpciod/0]
  22.   613 root 1508 S EmbedSky_wdg
  23.   614 root 2100 S /bin/sh /bin/qtopia
  24.   616 root 18552 S qpe
  25.   619 root 0 SW< [zd1211rw]
  26.   632 root 1512 S led-player
  27.   637 root 4756 S /usr/sbin/inetd
  28.   642 root 2064 S /sbin/boa
  29.   648 root 2100 S -/bin/sh
  30.   658 root 9192 S < /opt/Qtopia/bin/qss
  31.   659 root 12748 S N /opt/Qtopia/bin/quicklauncher
  32.   668 root 2100 R ps

kill 632,终止即可。

   [+] getchar() 输入缓存区问题:

    一开始,使用getchar()调试时会造成两次输出(第一次输出正常,第二次不正常),鼓捣了许久,笔者确认代码区没有问题。
    于是把重点放在getchar()上,根据笔者的经验,输入输出存在缓存区的问题,现在遇到的清空很可能就是没有清空缓存区的原因。
    
    然后,笔者试着使用Windows下经常使用的fflush(stdin)对标准输入缓存区进行清空,结果发现还是一样的.
    百思不得其解,只好Google之。
    于是惊奇地发现fflush()在Linux下没有清空输入缓存区的效果,于是你知道的,差点破罐破摔了。

    最后总结出来,使用getchar()进行调试的最保险的做法是使用一个while循环对输入的字符进行检测,
    如果不是回车符,则继续输入。同理,该方法也适用于scanf()等。


点击(此处)折叠或打开

  1. while((ch = getchar()) != '\n')


本文原创,如须转载,请注明出处:http://blog.chinaunix.net/blog/post/id/4279550.html


阅读(8580) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:[个人]Ubuntu编程环境配置

给主人留下些什么吧!~~