1:node
joe@joe-Aspire-Z3730:~$ cd /media/sdb4/aosp/kernel/goldfish/drivers/
2:linux
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish/drivers$ mkdir hello
3:在hello 目錄中增長hello.h 文件 參考 Android驅動開發全過程(有圖有真相)的hello.handroid
#ifndef _HELLO_Android_H_ #define _HELLO_ANDROID_H_ #include <linux/cdev.h> #include <linux/semaphore.h> #define HELLO_DEVICE_NODE_NAME "hello" #define HELLO_DEVICE_FILE_NAME "hello" #define HELLO_DEVICE_PROC_NAME "hello" #define HELLO_DEVICE_CLASS_NAME "hello" struct hello_android_dev { int val; struct semaphore sem; struct cdev dev; }; #endif
4:在hello 目錄中增長hello.c 文件 參考 https://blog.csdn.net/eliot_shao/article/details/51864811 帖子中的連接 http://blog.csdn.net/eliot_shao/article/details/51860229shell
也參考了 http://www.javashuo.com/article/p-gisynhty-bk.htmlapp
/* * hello.c -- A simple virtual char device driver */ #include <linux/module.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/slab.h> #include <asm/io.h> #include <linux/device.h> #include <asm/uaccess.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("eliot shao"); #define DEVICE_SUM 1 static int hello_open(struct inode *inode, struct file *filp); static int hello_release(struct inode *, struct file *filp); static ssize_t hello_read(struct file*, char*, size_t, loff_t*); static ssize_t hello_write(struct file*, const char*, size_t, loff_t*); /* the major device number */ static int hello_major = 0; static int hello_minor = 0; static struct class* hello_class = NULL; /* init the file_operations structure */ struct file_operations hello_fops = { .owner = THIS_MODULE, .open = hello_open, .release = hello_release, .read = hello_read, .write = hello_write, }; /* define a cdev device */ struct cdev *cdev; static int global_var = 0; /* global var */ /* module init */ static int __init hello_init(void) { int ret = 0; struct device* temp = NULL; dev_t devno = 0; printk("hello:hello_init .\n"); /*動態分配主設備和從設備號*/ ret = alloc_chrdev_region(&devno, hello_minor, DEVICE_SUM, "hello"); if(ret < 0) { printk(KERN_ALERT"hello:Failed to alloc char dev region.\n"); goto fail; } hello_major = MAJOR(devno); hello_minor = MINOR(devno); cdev = cdev_alloc(); cdev->owner = THIS_MODULE; cdev->ops = &hello_fops; if ((ret = cdev_add(cdev, devno, 1))) { printk(KERN_NOTICE "hello:Error %d adding hello.\n", ret); return 0; } else printk("hello:hello register success.\n"); /*在/sys/class/目錄下建立設備類別目錄hello*/ hello_class = class_create(THIS_MODULE, "hello"); if(IS_ERR(hello_class)) { ret = PTR_ERR(hello_class); printk(KERN_ALERT"Failed to create hello class.\n"); goto destroy_cdev; } /*在/dev/目錄和/sys/class/hello目錄下分別建立設備文件hello*/ temp = device_create(hello_class, NULL, devno, "%s", "hello"); if(IS_ERR(temp)) { ret = PTR_ERR(temp); printk(KERN_ALERT"Failed to create hello device."); goto destroy_class; } return ret; destroy_class: class_destroy(hello_class); destroy_cdev: cdev_del(cdev); fail: return ret; } /* module exit */ static void __exit hello_exit(void) { dev_t devno = MKDEV(hello_major, 0); /* remove cdev from kernel */ cdev_del(cdev); /* unregister the device driver */ unregister_chrdev_region(devno, 1); /* free the dev structure */ if(cdev) kfree(cdev); cdev = NULL; } /* open device */ static int hello_open(struct inode *inode, struct file *filp) { int ret = 0; printk("KERNEL:open success.\n"); return ret; } /* release device */ static int hello_release(struct inode *inode, struct file *filp) { printk("KERNEL:release success.\n"); return 0; } /* read device */ static ssize_t hello_read(struct file *filp, char *buf, size_t len, loff_t *off) { printk("KERNEL:reading...\n"); if(copy_to_user(buf, &global_var, sizeof(int))) { return -EFAULT; } return sizeof(int); } /* write device */ static ssize_t hello_write(struct file *filp, const char *buf, size_t len, loff_t *off) { printk("KERNEL:writing...\n"); if(copy_from_user(&global_var, buf, sizeof(int))) { return -EFAULT; } return sizeof(int); } /* module register */ module_init(hello_init); module_exit(hello_exit);
5:/media/sdb4/aosp/kernel/goldfish/drivers目錄下的Makefile中增長一行:dom
obj-$(CONFIG_HELLO) += hello/
6:/media/sdb4/aosp/kernel/goldfish/drivers目錄下的Kconfig中增長一行(注意位置):socket
menu "Device Drivers" 。。。。。 source "drivers/hello/Kconfig" 。。。 endmenu
7:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下增長Makefile文件,內容爲:oop
obj-$(CONFIG_HELLO) += hello.o
8:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下增長Kconfig文件,內容爲測試
config HELLO tristate "First Android Driver" default n help This is first Android Deiver for demo
9:ui
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ export CROSS_COMPILE=arm-eabi- joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ export ARCH=arm joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ export SUBARCH=arm
10:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ make goldfish_armv7_defconfig # # configuration written to .config # #### make completed successfully (7 seconds) ####
11:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ make scripts/kconfig/conf --silentoldconfig Kconfig CHK include/linux/version.h CHK include/generated/utsrelease.h make[1]: `include/generated/mach-types.h' is up to date. CALL scripts/checksyscalls.sh CHK include/generated/compile.h GZIP kernel/config_data.gz CHK kernel/config_data.h UPD kernel/config_data.h CC kernel/configs.o LD kernel/built-in.o LD vmlinux.o MODPOST vmlinux.o GEN .version CHK include/generated/compile.h UPD include/generated/compile.h CC init/version.o LD init/built-in.o LD .tmp_vmlinux1 KSYM .tmp_kallsyms1.S AS .tmp_kallsyms1.o LD .tmp_vmlinux2 KSYM .tmp_kallsyms2.S AS .tmp_kallsyms2.o LD vmlinux SYSMAP System.map SYSMAP .tmp_System.map OBJCOPY arch/arm/boot/Image Kernel: arch/arm/boot/Image is ready GZIP arch/arm/boot/compressed/piggy.gzip AS arch/arm/boot/compressed/piggy.gzip.o LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready #### make completed successfully (29 seconds) #### 總感受不可能有這麼快的編譯速度?????
12:從新進到aosp目錄
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage
13:雖然用新的內核啓動了模擬器,但我在/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄中沒有看到 hello.o文件
14:在/dev和/proc中都沒有看到hello設備
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ adb shell root@generic:/ # cd dev root@generic:/dev # ls __properties__ ashmem binder block console cpu_dma_latency cpuctl device-mapper eac fscklogs full fuse graphics input kmem kmsg loop-control mem memcg mtd network_latency network_throughput null psaux ptmx pts qemu_pipe random rtc0 socket tty tty0 tty1 tty10 tty11 tty12 tty13 tty14 tty15 tty16 tty17 tty18 tty19 tty2 tty20 tty21 tty22 tty23 tty24 tty25 tty26 tty27 tty28 tty29 tty3 tty30 tty31 tty32 tty33 tty34 tty35 tty36 tty37 tty38 tty39 tty4 tty40 tty41 tty42 tty43 tty44 tty45 tty46 tty47 tty48 tty49 tty5 tty50 tty51 tty52 tty53 tty54 tty55 tty56 tty57 tty58 tty59 tty6 tty60 tty61 tty62 tty63 tty7 tty8 tty9 ttyS0 ttyS1 ttyS2 tun urandom vcs vcs1 vcsa vcsa1 xt_qtaguid zero root@generic:/dev # cd /proc root@generic:/proc # ls 1 10 1013 1030 1061 1081 1098 11 1125 1162 1178 1186 12 13 139 14 2 25 26 27 28 29 3 30 31 33 337 34 37 39 40 43 447 45 46 47 48 49 5 50 51 52 54 57 58 587 59 6 60 61 62 63 64 646 65 66 663 682 7 709 73 739 783 8 822 839 897 9 923 940 963 995 buddyinfo bus cgroups cmdline config.gz consoles cpu cpuinfo crypto devices diskstats dma-mappings driver execdomains fb filesystems fs interrupts iomem ioports irq kallsyms kmsg kpagecount kpageflags loadavg locks meminfo misc mounts mtd net pagetypeinfo partitions sched_debug schedstat self slabinfo softirqs stat swaps sys sysrq-trigger sysvipc timer_list tty uptime version vmallocinfo vmstat yaffs zoneinfo
15:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下修改Kconfig文件
config HELLO tristate "First Android Driver" default m help This is first Android Deiver for demo
16:從新執行第10和第11步,而後發現hello目錄中出現了hello.o文件,說明驅動程序編譯了
17:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ cd ../.. joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage &
18:參考 android-----模擬器加載本身編譯的內核(適用於驅動練習)https://blog.csdn.net/yf210yf/article/details/9901375 不成功。主要是由於權限問題,因此修改hello目錄下的Kconfig,將驅動程序直接編譯進內核中
config HELLO tristate "First Android Driver" default y help This is first Android Deiver for demo
19:從新執行第10和第11步
20:
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage &
21:參考 http://www.javashuo.com/article/p-gisynhty-bk.html
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ adb shell root@generic:/ # cd dev root@generic:/dev # ls 其中就出現了hello,但/proc目錄中卻沒有hello
22:下面的帖子中說明了如何在android源碼中寫應用層程序測試hello驅動
https://blog.csdn.net/lzpdz/article/details/50562366
23:按照22中所說,先進入源碼的external目錄,而後:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/external$ mkdir hello joe@joe-Aspire-Z3730:/media/sdb4/aosp/external$ cd hello joe@joe-Aspire-Z3730:/media/sdb4/aosp/external/hello$ gedit hello.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #define DEVICE_NAME "/dev/hello" int main(int argc, char** argv) { int fd = -1; int val = 0; fd = open(DEVICE_NAME, O_RDWR); if(fd == -1) { printf("Failed to open device %s.\n", DEVICE_NAME); return -1; } printf("Read original value:\n"); read(fd, &val, sizeof(val)); printf("%d.\n\n", val); val = 5; printf("Write value %d to %s.\n\n", val, DEVICE_NAME); write(fd, &val, sizeof(val)); printf("Read the value again:\n"); read(fd, &val, sizeof(val)); printf("%d.\n\n", val); close(fd); return 0; }
24:在hello目錄中增長Android.mk
joe@joe-Aspire-Z3730:/media/sdb4/aosp/external/hello$ gedit Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_MODULE := hello LOCAL_SRC_FILES := $(call all-subdir-c-files) include $(BUILD_EXECUTABLE)
25:在hello目錄中編譯模塊
joe@joe-Aspire-Z3730:/media/sdb4/aosp/external/hello$ mm ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=5.1.1 TARGET_PRODUCT=aosp_arm TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_OS=linux HOST_OS_EXTRA=Linux-3.11.0-15-generic-x86_64-with-Ubuntu-12.04-precise HOST_BUILD_TYPE=release BUILD_ID=LMY47Z OUT_DIR=out ============================================ make: Entering directory `/media/46bb100d-2505-4025-8425-34ecf3129209/aosp' Import includes file: out/target/product/generic/obj/EXECUTABLES/hello_intermediates/import_includes target thumb C: hello <= external/hello/hello.c external/hello/hello.c: In function 'main': external/hello/hello.c:5:14: warning: unused parameter 'argc' [-Wunused-parameter] int main(int argc, char** argv) ^ external/hello/hello.c:5:27: warning: unused parameter 'argv' [-Wunused-parameter] int main(int argc, char** argv) ^ target Executable: hello (out/target/product/generic/obj/EXECUTABLES/hello_intermediates/LINKED/hello) target Symbolic: hello (out/target/product/generic/symbols/system/bin/hello) Export includes file: external/hello/Android.mk -- out/target/product/generic/obj/EXECUTABLES/hello_intermediates/export_includes target Strip: hello (out/target/product/generic/obj/EXECUTABLES/hello_intermediates/hello) Install: out/target/product/generic/system/bin/hello make: Leaving directory `/media/46bb100d-2505-4025-8425-34ecf3129209/aosp' #### make completed successfully (4 seconds) ####
26:從新打包Android系統文件system.img:
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ make snod ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=5.1.1 TARGET_PRODUCT=aosp_arm TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_OS=linux HOST_OS_EXTRA=Linux-3.11.0-15-generic-x86_64-with-Ubuntu-12.04-precise HOST_BUILD_TYPE=release BUILD_ID=LMY47Z OUT_DIR=out ============================================ build/core/Makefile:1013: Warning: with dexpreopt enabled, you may need a full rebuild. make snod: ignoring dependencies Target system fs image: out/target/product/generic/system.img Running: mkuserimg.sh out/target/product/generic/system out/target/product/generic/system.img ext4 system 576716800 out/target/product/generic/root/file_contexts make_ext4fs -T -1 -S out/target/product/generic/root/file_contexts -l 576716800 -a system out/target/product/generic/system.img out/target/product/generic/system Creating filesystem with parameters: Size: 576716800 Block size: 4096 Blocks per group: 32768 Inodes per group: 7040 Inode size: 256 Journal blocks: 2200 Label: Blocks: 140800 Block groups: 5 Reserved block group size: 39 Created filesystem with 1468/35200 inodes and 109538/140800 blocks out/target/product/generic/system.img maxsize=588791808 blocksize=2112 total=576716800 reserve=5947392 #### make completed successfully (19 seconds) ####
27:從新啓動模擬器
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage -system out/target/product/generic/system.img
28:經過adb shell測試應用程序hello
root@generic:/system/bin # ls -rwxr-xr-x root shell 5356 2018-04-25 16:29 hello
29:經過下面的測試,說明咱們寫的hello驅動程序和hello應用程序都成功運行了。
root@generic:/system/bin # hello Read original value: 0. Write value 5 to /dev/hello. Read the value again: 5. root@generic:/system/bin # hello //注意此次執行命令與第一次執行的結果 Read original value: 5. Write value 5 to /dev/hello. Read the value again: 5.
默認只有root 用戶可讀寫,而hello_device_open 通常是由上層APP 來調用的,這些APP 通常不具備root 權限,這時候就 致使打開設備文件失敗: Hello Stub: failed to open /dev/hello -- Permission denied. 解決辦法是相似於Linux 的udev 規則,打開Android 源代碼工程目錄下,進入到system/core/rootdir 目錄,裏面有一個名爲 uevent.rc 文件,往裏面添加一行: /dev/hello 0666 root root 備註說明:參考 Android驅動開發全過程(有圖有真相)中對此權限操做方面的說明
手機未root 查看data/data/某一app文件信息 筆者的小米3沒有root,可是又想方便地查看data/data/目錄下的一些文件,直接進入data會提示沒有權限,查看的方式爲進入data/data/後,運行下面的命令,就能直接進入你應用的包下了,可通用cp或者mv拷貝或移動到sdcard目錄進行其餘操做
run-as package_name