Planet maemo: category "feed:3443cd3b09dca3afd960884d779d28f3"
IOCTL is a very useful system call: it is simple and multiplexes the different commands to the appropriate kernel space function. In this post, I want to describe how you can implement a module with IOCTL support for Android. There are a lot of good articles about it (links below), and I just describe the differences regarding to the Android platform.
I've been always interested in scrapping a bit more my application... no matter its level: frontend, framework or native. That's why I guess I have decided to study a bit more Software Systems. Some weeks ago, I was implementing some tests to evaluate my current project in terms of "time spent for certain operations". In addition, I had to force some cache/memory fault, work on some *non* cache-friendly program and, at the end, I was thinking about other aspects of my system. Usually, for software systems, we pretty much focus on latency and bandwidth. For example, when you are developing an application to have an efficient access to memory (cache-friendly!), you are thinking about latency, as you want to avoid (expensive) access to a lower-level memory. Of course, depending on the operation (network, memory access, etc.), latency and bandwidth have a bit different meaning. For example, for network, latency is measured by sending a packet that is returned to the sender. For memory access, latency can be explained as "the delay time between the moment a memory controller tells the memory module to access a particular memory column on a RAM module, and the moment the data from the given array location is available on the module's output pins". [Wiki]
I took a look on some amazing links that gave me a very precise and detailed view about such discussion and here they are:
I took a look on some amazing links that gave me a very precise and detailed view about such discussion and here they are:
- Herb Sutter @ NWCPP - This is an amazing talk.It shows how your program actually uses your machine's architecture;
- Gerson Robboy Lecture Note - Very good lecture notes with some examples and exercises;
- Great stackoverflow post;
- Table with interesting numbers about latency;
- Latency through a Java perspective;
This week, I had some issues on my tests in a Lollipop device with AOSP. I really wanted to have synchronous reads/writes so that I could evaluate my solution in a different way. I am also trying to minimize the effects of caching as much as possible. If you check for async and sync I/O operations for Linux, you'll a lot of references to the flags O_DIRECT, O_SYNC, O_DSYNC, ...
Actually, that's a good way to implement. However, with Android NDK apps, things are not so straightforward.
First, to have a good understanding about the O_*SYNC flags, check this link. Of course, the man page for the command open as well.
First, O_DIRECT does not work in Android since 4.4. See this link for more details about it. That's sad. So, let's try to use the O_*SYNC data.
O_SYNC and O_DSYNC work fine in Android. But, as the description say, only for writes. Another detail: for Android, O_SYNC has the same semantics as O_DSYNC. That's good, but I still want something similar to reads as well.
Why don't we use O_RSYNC? Well, Android does not implement it :-( But it's not the only one... there are other Linux distributions that don't do it either.
What about dropping caches?? See this link for more details. Hum, that works, but after the first read, the data will be cached again :-(
So, I am still looking for a solution for Android Lollipop. Hope to post it soon!
Actually, that's a good way to implement. However, with Android NDK apps, things are not so straightforward.
First, to have a good understanding about the O_*SYNC flags, check this link. Of course, the man page for the command open as well.
First, O_DIRECT does not work in Android since 4.4. See this link for more details about it. That's sad. So, let's try to use the O_*SYNC data.
O_SYNC and O_DSYNC work fine in Android. But, as the description say, only for writes. Another detail: for Android, O_SYNC has the same semantics as O_DSYNC. That's good, but I still want something similar to reads as well.
Why don't we use O_RSYNC? Well, Android does not implement it :-( But it's not the only one... there are other Linux distributions that don't do it either.
What about dropping caches?? See this link for more details. Hum, that works, but after the first read, the data will be cached again :-(
So, I am still looking for a solution for Android Lollipop. Hope to post it soon!
I had some problems compiling ASM code as part of an Android kernel module.
I decided to use a different target platform for my project. Initially, I was using Android Kitkat + Galaxy Nexus (ARMv7 + TI OMAP 4460). To obtain best performance with some crypto operations, I am now using Android Lollipop + Nexus 9 (ARMv8 64bits). I did some tests with basic OpenSSL examples (for example, AES-128 and SHA1) and the numbers are impressive.
In my current project, the system has to notify the user about a certain action that actually takes place inside the kernel (in this case, transfer of security keys). I don't want to get into too much details about the tasks, but let's consider that the kernel and the Dalvik are the only trustworthy components and the security keys are stored inside the kernel. I've also seen some pieces of code that helps to implement this, but I could not find a end-to-end solution.
Let's now show how to install a module into the just compiled Android kernel (see this post for more information)
For compiling the module, it's important that you use the same kernel source that is installed in your device. Otherwise, you cannot install the module.
a. Go to the code that contains an example of kernel module for Android (for instance, [your_code]/module/intercept);
b. Update the makefile to point to your kernel source code;
c. You need to set some env variables, including the cross-compiler. In this case, you can use the ones provided by the Android source, in the folder prebuilts:
@desktop:$ export CROSS_COMPILE=[android_sdk]/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-
@desktop:$ export ARCH=arm
@desktop:$ export PATH=$PATH:/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/
@desktop:$ make
(a kernel module file will be generated ([your_module].ko) and this is the one that we need to install in our rooted device)
d. Copy the .ko file to the device using the following command:
@desktop:$ adb push [your_module].ko /data/local/tmp
e. Install the kernel module using the following commands:
@desktop:$ adb shell
@android:$ su
@android:$ cd /data/local/tmp
@android:$ insmod [your_module].ko
f. You might get some errors, such as "function not implemented". To check more details about what's wrong, you can check the log file by typing the following command.
@android:$ dmesg
For compiling the module, it's important that you use the same kernel source that is installed in your device. Otherwise, you cannot install the module.
a. Go to the code that contains an example of kernel module for Android (for instance, [your_code]/module/intercept);
b. Update the makefile to point to your kernel source code;
c. You need to set some env variables, including the cross-compiler. In this case, you can use the ones provided by the Android source, in the folder prebuilts:
@desktop:$ export CROSS_COMPILE=[android_sdk]/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-
@desktop:$ export ARCH=arm
@desktop:$ export PATH=$PATH:/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/
@desktop:$ make
(a kernel module file will be generated ([your_module].ko) and this is the one that we need to install in our rooted device)
d. Copy the .ko file to the device using the following command:
@desktop:$ adb push [your_module].ko /data/local/tmp
e. Install the kernel module using the following commands:
@desktop:$ adb shell
@android:$ su
@android:$ cd /data/local/tmp
@android:$ insmod [your_module].ko
f. You might get some errors, such as "function not implemented". To check more details about what's wrong, you can check the log file by typing the following command.
@android:$ dmesg
As you need to implement your solution into Android system, you end up learning a lot about the different Android layers (kernel, OS and applications) and how to integrate them. I decided to add the following list with some tips, as these small things took me some precious time to get it solved. The list will be often edited:
#01 - Make sure that you're flashing the device with the proper kernel image
This is what happened to me: I had previously built the kernel (something like two months before). Then, I had to build the OS image from scratch, that is, cleaning up the previous build (with make clobber). When I used the command make bootimage, including setting the variables properly, the output always had the wrong kernel image (not the one that I had previously built, but the existing one in the directory prebuilts). The build process won't take too old kernel images. Therefore, make sure that the compressed kernel image is always new. Even if you don't make any change on the kernel source, do make again to generate a new file.
#01 - Make sure that you're flashing the device with the proper kernel image
This is what happened to me: I had previously built the kernel (something like two months before). Then, I had to build the OS image from scratch, that is, cleaning up the previous build (with make clobber). When I used the command make bootimage, including setting the variables properly, the output always had the wrong kernel image (not the one that I had previously built, but the existing one in the directory prebuilts). The build process won't take too old kernel images. Therefore, make sure that the compressed kernel image is always new. Even if you don't make any change on the kernel source, do make again to generate a new file.
This week, I tried to compile a simple NDK application and link it with the OpenSSL library. Most of libraries (including OpenSSL) are not supported by the NDK, what makes it a bit more complicated to use. So, in this post, I describe what I usually do to properly compile applications that need external libs.
This week, I had to go through the process of Android OS/Kernel building/installation. And it was a lot much better and 6 months ago (maybe, because I built it for a device and not for the emulator?). I compiled the images in Ubuntu 12.04 and I used a Samsung Galaxy Nexus device (maguro with tuna as kernel). Therefore, I decided to summarize the steps that I took. This mini-tutorial is a lot shorter and simpler (and really works!!).
Among the tasks for build an Android kernel development, building the Android Goldfish kernel is the easiest :-) (I mean, no compiling errors...)
First, you need to have access to the cross-compiling tools. The Android source code provides them in folder /prebuilt/linux-x86/toolchain/.
Steps
1. Set the path to include the pre-build toolchain
# export PATH=/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/:$PATH
2. Set the Kernel config file. In this case, we are compiling for the ARM emulator (armv7).
# make ARCH=arm goldfish_armv7_defconfig
3. Run make
# CROSS_COMPILE=/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- ARCH=arm make
4. Change var ANDROID_PRODUCT_OUT
# export ANDROID_PRODUCT_OUT=/out/target/product/generic/
5. Run the emulator
# /out/host/linux-x86/bin/emulator-arm -system /out/target/product/generic/system.img -kernel /goldfish/arch/arm/boot/zImage -data /out/target/product/generic/userdata.img -ramdisk /out/target/product/generic/ramdisk.img -skindir /sdk/emulator/skins/ -skin HVGA -verbose -show-kernel
Issues
First, you need to have access to the cross-compiling tools. The Android source code provides them in folder /prebuilt/linux-x86/toolchain/.
Steps
1. Set the path to include the pre-build toolchain
# export PATH=/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/:$PATH
2. Set the Kernel config file. In this case, we are compiling for the ARM emulator (armv7).
# make ARCH=arm goldfish_armv7_defconfig
3. Run make
# CROSS_COMPILE=/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- ARCH=arm make
4. Change var ANDROID_PRODUCT_OUT
# export ANDROID_PRODUCT_OUT=/out/target/product/generic/
5. Run the emulator
# /out/host/linux-x86/bin/emulator-arm -system /out/target/product/generic/system.img -kernel /goldfish/arch/arm/boot/zImage -data /out/target/product/generic/userdata.img -ramdisk /out/target/product/generic/ramdisk.img -skindir /sdk/emulator/skins/ -skin HVGA -verbose -show-kernel
Issues
- The option CONFIG_MODULES is NOT enabled by default. If you want to insert modules into the kernel, make sure to set CONFIG_MODULES;
- Android emulator does NOT work with Kernels > 2.6.X So, make sure to use the proper Kernel. For devices, any support Kernel will work.
Finally, back to this :-)
Lately, I have being developing a new project which basically needs some kernel changes on Android Goldfish kernel. Initially, I thought that this would be something like "traditional" kernel development, but NOT. Android kernel is, of course, a Linux kernel but it has some peculiarities that impact on the development phase.
[NOTE] I'd rather provide a link to the source that I used than replicating the same information.
So, I split my experience into the following topics:
Lately, I have being developing a new project which basically needs some kernel changes on Android Goldfish kernel. Initially, I thought that this would be something like "traditional" kernel development, but NOT. Android kernel is, of course, a Linux kernel but it has some peculiarities that impact on the development phase.
[NOTE] I'd rather provide a link to the source that I used than replicating the same information.
So, I split my experience into the following topics:
- Building Android ICS
- Building/Running Android Goldfish kernel
- Creating a Goldfish kernel module
- Adding new syscalls into the Goldfish kernel