动手写linux驱动(1)--Apple的学习笔记

一,前言

学习的步骤一般都是从简单到难,从开发驱动的角度来看,linux和单片机的区别主要是框架不同。若简单来说linux的架构及API的使用方法了解后,就可以自己写驱动了。而不是仅仅只是改改设备树,改改配置,调试下了。当内核理论及常用API复习完成后,我开始进入自己动手写驱动了,光看不练是不行地~代码工程我会放在我gitee上https://gitee.com/applecai/linux-driver-study

二,globalmem改成了applepaper驱动

linux设备驱动开发详解中有globalmem虚拟驱动,然后几个章节都在其上做功能添加及改进。我也参考这个思路,由于globalmem就是一段内存区的字符设备驱动,所以我把它当做paper来使用。设备名字定义为applepaper。另外设备号一般都从0开始,我故意改成6,主要是习惯下那些API的参数。
刚刚做了2个工程
ko模块编译方法:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
APP编译方法:arm-linux-gnueabihf-gcc -static applepaperApp.c -o applepaperApp
1. 1_applepaper工程
功能说明:就是注释和注销设备号。目的是练习最小框架。
2. 2_applepaper工程
功能说明:在1的基础上添加了read和write函数。并且添加了APP对读写进行功能验证。仅简单入门读写框架。将来会继续添加功能。

三,过程中遇到的问题

1.编译出现错误:fatal error: asm/system.h: No such file or directory
错误信息可知,缺少此头文件
原因:
Linux内核是不断地更新换代,即3.3版本之后内核用switch_to.h替换了曾经的system.h头文件。
解决方法:
可在终端输入uname -r,查看自己Linux内核版本。如,我的内核版本是4.2.0-27-generic,可知为3.3之后版本,直接使用#include 替换掉原来的#include

2.insmod applepaper.ko 提示 loading out-of-tree module taints kernel
原因:
使用内核源代码未包含的树外模块,由于我每添加到设备树,所以警告是应该的。暂时不改。
参考网址:
https://unix.stackexchange.com/questions/118116/what-is-a-tainted-kernel-in-linux

3.device_create的oops错误解决方法

[   25.443548] Backtrace: 
[   25.446020] [] (kvasprintf_const) from [] (kobject_set_name_vargs+0x34/0xa8)
[   25.454846]  r7:00000000 r6:bf001104 r5:dd2c6f40 r4:dd297e00
[   25.460537] [] (kobject_set_name_vargs) from [] (device_create_groups_vargs+0x90/0xc4)
[   25.470234]  r7:00000000 r6:bf001104 r5:dd2c6f40 r4:dd297e00
[   25.475920] [] (device_create_groups_vargs) from [] (device_create+0x40/0x60)
[   25.484834]  r9:bf002040 r8:bf002040 r7:bf002000 r6:c0e05148 r5:00000000 r4:c0e05148
[   25.492627] [] (device_create) from [] (applepaper_init+0x124/0x1000 [applepaper])
[   25.501973]  r5:bf002240 r4:00000000
[   25.505575] [] (applepaper_init [applepaper]) from [] (do_one_initcall+0x58/0x258)
[   25.514924]  r8:c0ec3aa0 r7:ffffe000 r6:00000000 r5:bf005000 r4:c0e05148
[   25.521661] [] (do_one_initcall) from [] (do_init_module+0x6c/0x264)
[   25.529789]  r8:dd2eff28 r7:dd20cfc0 r6:dd20cf80 r5:dd206bc0 r4:bf002040
[   25.536522] [] (do_init_module) from [] (load_module+0x2328/0x25b0)
[   25.544561]  r6:dd20cf80 r5:00000002 r4:00000002
[   25.549201] [] (load_module) from [] (sys_finit_module+0xcc/0xec)
[   25.557067]  r10:0000017b r9:00000000 r8:7fffffff r7:00000003 r6:000d6008 r5:00000000
[   25.564928]  r4:c0e05148
[   25.567474] [] (sys_finit_module) from [] (ret_fast_syscall+0x0/0x28)
[   25.575686] Exception stack(0xdd2effa8 to 0xdd2efff0)
[   25.580762] ffa0:                   000d6008 00000006 00000003 000d6008 00000000 beb0cf49
[   25.588979] ffc0: 000d6008 00000006 beb0cf49 0000017b 00000000 00000000 b6f3cf74 00000000
[   25.597194] ffe0: beb0ccb0 beb0cca0 00030228 b6ea9cf0
[   25.602270]  r9:dd2ee000 r8:c01011c4 r7:0000017b r6:beb0cf49 r5:00000006 r4:000d6008
[   25.610051] Code: 00000000 00000000 00000000 e20110ff (e4d02001) 
[   25.616236] ---[ end trace e39ec680f5e4bed7 ]---
Segmentation fault

device_create()参数使用很灵活,一不小心就会导致加载时内核报oops错误(vsnprintf引起)。
device_create(my_class, NULL, MKDEV(major,minor), "hello" "%d",0);
在"hello" "%d"之间加上","能解决insmod时oops错误,但是却不能在/dev目录下创建想要的设备文件。正确的调用方法如下:
device_create(my_class, NULL, MKDEV(major,minor), NULL,"hello%d",0);

4.可执行程序无法在Linux上运行,显示line 1: syntax error: word unexpected (expecting ")
解决方法:应该用静态编译。-static
修改前,确实包含了动态库


image.png

修改后,不包括动态库


image.png

四,成功的log

1的log,设备号major为247,设备minor为6。class和dev都创建正确。

# insmod applepaper.ko 
[  265.735980] b
[  265.737626] 2
[  265.739218] 3
[  265.741211] Registered character driver
# cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 29 fb
 89 i2c
 90 mtd
128 ptm
136 pts
247 applepaper
248 ttySDIO
249 rpmb
250 ttyO
251 ptp
252 pps
253 rtc
254 gpiochip

Block devices:
  1 ramdisk
  7 loop
  8 sd
 31 mtdblock
 65 sd
 66 sd
 67 sd
 68 sd
 69 sd
 70 sd
 71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
259 blkext
# ls -l /dev|grep 247
crw-------    1 root     root      247,   6 Jan  1 00:04 applepaper6
# cd /sys
# ls
block     class     devices   fs        module
bus       dev       firmware  kernel    power
# cd class
# ls
apple_class   extcon        mem           pps           spi_master
ata_device    gpio          misc          ptp           thermal
ata_link      graphics      mmc_host      pwm           tty
ata_port      i2c-adapter   mtd           regulator     ubi
backlight     i2c-dev       net           remoteproc    vc
bdi           input         pci_bus       rtc           vtconsole
block         iommu         pci_epc       scsi_device   wakeup
devcoredump   lcd           phy           scsi_disk
dma           mdio_bus      power_supply  scsi_host
# cd apple_class/
# ls
applepaper6
# cd applepaper6/
# la
-sh: la: not found
# ls
dev        power      subsystem  uevent
# cat dev
247:6
# cd /sys/devices/
# ls
armv7_cortex_a8  platform         system           virtual
breakpoint       soc0             tracepoint
kprobe           software         uprobe
# cd virtual/
# ls
apple_class  block        mem          net          vc           workqueue
bdi          graphics     misc         tty          vtconsole
# cd apple_class/
# ls
applepaper6
# cd applepaper6/
# ls
dev        power      subsystem  uevent

2的log,通过运行applepaperApp读写正确。

# insmod applepaper1.ko 
[   29.700013] applepaper1: loading out-of-tree module taints kernel.
[   29.707770] Registered character driver
# ./applepaperApp /dev/applepaper6 2
[   49.949258] written 50 bytes(s) from 0
# ./applepaperApp /dev/applepaper6 1
[   52.665337] read 50 bytes(s) from 0
read data:usr data!
# echo "hi AppleCai" > /dev/applepaper6 
[   87.853832] written 12 bytes(s) from 0
# cat /dev/applepaper6 
[   94.177645] read 4096 bytes(s) from 0
hi AppleCai
��w|cat: read error: No such device or address

注:我主要用applepaperApp来进行读写是正确的,echo的读写调用的函数我暂时不太清楚,貌似也可以读写,只是尝试性用了下。

你可能感兴趣的:(动手写linux驱动(1)--Apple的学习笔记)