Service
-------
init process 는 다음을 통해서 각종 service를 control함.

SIGCHLD signal handler를 정의해서, service의 상태를 파악함
service가 죽는 경우 SIGCHLD signal이 날아오고, 이 signal로 어떤 service가 죽었는지/시작했는지 파악하고, 각 service의 flag에 따라서 다음 행동 (해당 service를 다시 시작하거나, system을 restart하거나 (critical service))을 결정함.
[property_service.c] '/dev/socket/property_service' socket을 열고 message를 기다림 (PROP_SERVICE_NAME).
'property_set(...)' interface를 통해서, property_service socket에 message가 써지고, init process의 property service부분에서 이 message를 handling함.
'ctl.start/stop/restart' 는 source code에 hard-coded된 특수한 message로, 해당 이름의 service를 control한다.

잊어먹지 않기 위해서 일단 기록해 둠....

* It is impossible to get full supporting from 'configure'

Getting runtime informations - ex bytes of 'long' type, checking whether symbol 'xxx' is in the library or not. - is impossible.
-> Some releases complain this and doesn't proceed anymore.

* Some releases still refer /lib, /usr/lib, /usr/include etc.

* Using 'make check' in naive way is impossible.

* Anything else???

⚫ ueventd
    ⚬ ueventd creates and 'poll' netlink socket.
        ueventd_main [init/ueventd.c]

    ⚬ read kernel event message -> parse -> handle
        handle_device_event [init/devices.c]
            -> device_changed [init/init.c]
                -> queue_device_triggers [init/init_parser.c]
                            |
            +---------------+
            |
            v
        : search action list to know what to do for this event.
          searching action which name is device-added/removed-[device node].
          [device node] is from 'DEVPATH' variable of uevent message.

    ⚬ action list : list declared at [init_parser.c]
        • builtin action (added by 'queue_builtin_action [init/init_parser.c]')
            ex. property_init, wait_for_coldboot_done etc.
        • from script (added by 'parse_action [init/init_parser.c]')
            section "on device-added-[device path] / on device-removed-[device path]"
            ex.
                [init.rc]
                on device-added-/dev/block/mmcblk0p18
                    exec /system/bin/sh /system/bin/hello_mmc.sh

⚫ other daemons (ex usbd)
    ⚬ create and 'poll' netlink socket.
⚫ Sendig kobject uevent to user space from kernel
    ⚬ Concept
        • Execute user-space binary with predefined + customized environment variables.
        • Send message to pre-defined netlink socket unit created by kernel.

    ⚬ From souce code (hotplug)
        • kernel node [kernel/sysctl.c]
        : /proc/sys/kernel/hotplug

        • kobject_uevent_env() [kobject_uevent.c]
            default user process executable image path
                -> CONFIG_UEVENT_HELPER_PATH
        • kernel/sysctl.c
            'uevent_helper' value can be RWed through 'hotplug' node of sysctl.

    ⚬ From souce code (netlink)
        • kobject_uevent_env() [kobject_uevent.c]
            : #if defined(CONFIG_NET)
            write message to netlink socket unit (NETLINK_KOBJECT_UEVENT)
        • netlink.h
            netlink units
        • Creating in userspace
            socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)
⚬ Concept
    - Creating Kernel Thread
    - Fork by call 'do_fork' directly (because, this is inside kernel!)
    - Exec by call 'do_execve'

⚬ Code walkthrough
    • kmod.h
        call_usermodehelper / call_usermodehelper_fns
            call_usermode_helper_setup(...)
            call_usermode_helper_setfns(...)
            call_usermodehelper_exec(...)

    • kmod.c
        call_usermode_helper_setup()
            -> setup subprocess infos.
                : path to execute, arguments, env variables etc
            -> set 'work' function of 'workqueue' to '__call_usermodehelper'
                : INIT_WORK(&sub_info->work, __call_usermodehelper);
        call_usermode_helper_setfns()
            -> setup subprocess functions
        call_usermodehelper_exec()
            -> queue this work to 'khelper_wq' workqueue.
        __call_usermodehelper() /* <- in work queue (khelper_wq) */
            pid = kernel_thread(___call_usermodehelper, sub_info, CLONE_VFORK | SIGCHILD);
        kernel_thread(...)
            : set pc to 'kernel_thread_helper'- assembly function
            pid = do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
        kernel_thread_helper
            : Shuffle the arument into the correct register before calling the thread function
            : set pc to given thread function (in this example, '___call_usermodehelper()' function.)
        ___call_usermodehelper()
            kernel_execve(sub_info->path, sub_info->argv, sub_info->envp);

    • sys_arm.c
        kernel_execve()
            do_execve(...)
            : make it to user space process!
codec을 재 설치해도, GOM player, KMP등을 지우고 재설치해도 해결이 안되었는데,
KMP를 실행하고 '컨트롤 박스..(Alt+G)'를 실행하니,  'COLORS' tab의 HW controls 부분에서 3개의 설정중 제일 위의 것이 가장 좌측으로 설정되어 있었는데, 이걸 중간으로 옮기니 문제가 해결되었다. 자세한 내용은 좀더 분석이 필요..~~~
(귀차니즘에... 과연 내가 더 분석을 하긴 할까나... -_-; )

'Domain > Win32' 카테고리의 다른 글

[Win32] Function Calling Convention  (0) 2008.12.03
[Win32][Tips] Creating Window...  (0) 2007.06.27
[Win32] IME Active중 VK Code얻기  (0) 2007.06.25
[Win32] 한글 입력하기  (0) 2007.06.23
[Tips] Cross-Compiling on Windows for Linux  (0) 2007.06.20

This article is to describe summary and some important points to establish gnu system root on android devices based on my experience.

Notation
    [] : version used.

===============
Introduction
===============
    Now a days, performance of Android mobile device is much like PC.
    So, why don't you use Android device just like linux desktop?
    As a first step, here is summary to construct gnu system root on Android device.

==============
Setup Sequence
==============
    Installing cross compiling tools
    ----------------------------------------------------------------------
        *** NOTE ****************************************************************
        *    Followings are not tested because I just used built Sourcery g++.  *
        *    [ Codesourcery 2007q3-53 ]                                         *
        *************************************************************************
        * Reference : http://frank.harvard.edu/~coldwell/toolchain/
        * Build GNU binutils
            - Using '--disable-nls' option is recommended (to reduce compile time and dependency.
        * Install Linux Kernel Headers
            - Latest Sourcery g++(2010.09-50) supports only at-least-2.6.16-target-kernel.
        * Build GLIBC headers
        * Build GCC for headers:
            - Using '--disable-nls --without-headers' is recommended.
            - example : configure option of GCC in Codesourcery 2007q3-53
                /vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/src/gcc-4.2/configure --build=i686-pc-linux-gnu
                  --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap
                  --disable-libssp --disable-libgomp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld
                  --enable-languages=c,c++ --enable-shared --enable-symvers=gnu --enable-__cxa_atexit
                  --with-pkgversion=CodeSourcery Sourcery G++ Lite 2007q3-53
                  --with-bugurl=https://support.codesourcery.com/GNUToolchain/
                  --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc
                  --with-build-sysroot=/vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/install/arm-none-linux-gnueabi/libc
                  --enable-poison-system-directories
                  --with-build-time-tools=/vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/install/arm-none-linux-gnueabi/bin
                  --with-build-time-tools=/vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/install/arm-none-linux-gnueabi/binff
        * Build GLIBC libraries
        * Rebuild GCC using newly-built-GLIBC.

    Construct gnu system root
    -------------------------
        * Environments
            # this directory will be new gnu system root on Android target.
            PREFIX=/data/arm-gnu-sysroot/
            # gnu root directory on target device
            TGNUROOT=/data/gnuroot/
            TARGET=arm-none-linux-gnueabi
            export ARCH=arm
            export CROSS_COMPILE=${TARGET}-
            # set PATH
            PATH=<cross-tools>:$PATH
        * Install headers and GLIBC
            - copy cross-compiled glibc, headers etc to $TROOT except for i686 executables and related files
        * Build GNU binutils [binutils-2.18]
            - ./configure --prefix=${PREFIX} --host=${TARGET} --target=${TARGET} --disable-nls
        * Build GCC [gcc-4.2.1]
            - ./configure --prefix=${PREFIX} --build=i686-pc-linux-gnu --target=${TARGET} --host=${TARGET}
                --disable-nls --enable-languages=c
        * Build bash [bash-4.0]
            - ./configure --prefix=${PREFIX} -host=${TARGET} --without-bash-malloc
            - install to $PREFIX/bin. And link $PREFIX/bin/sh to $PREFIX/bin/bash
        * Build gnu make [make-3.82]
            - ./configure --prefix=${PREFIX} -host={TARGET}
        * Build busybox
            - Set cross compiler prefix to 'arm-none-linux-gnueabi-' and make.
            - install to $PREFIX/bin
              (usually commands in busybox are located at /bin)
            - create link to busybox for each command.
        * copy to target device
            - adb push $PREFIX $TGNUROOT
        * link rootfs to gnu system root.
            - ln -s $TGNUROOT/lib /lib
            - ln -s $TGNUROOT/bin /bin
              ...

===============
Confirm & Check
===============
    Build Emacs-23.2
    ----------------
        * push Emacs-23.2 source code to target.
        * ./configure --without-xpm --without-jpeg --without-tiff --without-gif --without-png --without-rsvg
             --without-xft --without-libotf --without-m17n-flt --without-toolkit-scroll-bars --without-xaw3d
             --without-xim --without-gpm
        * 'make' should be done without error.

    Running Emacs
    -------------
        * copy termcap.src from "http://www.opensource.apple.com/source/emacs/emacs-39/emacs/etc/termcap.src".
          And put this /usr/etc/termcap.src.
        * And set following environment variable
            TERM=linux
            TERMCAP=/usr/etc/termcap.src
        * Emacs should work without error in 'adb shell' terminal.

===============
NOTE
===============
    Points
    ------
        * headers and GLIBC built for cross-compiling should be used as they are at target system root.
          (To use cross-compiled binaries on target device without any potential issues.)
        * Some open source packages check only /lib and /usr/lib (/usr/local/lib isn't considered).
          So, fundamental libraries would be better to be installed at /usr/lib,
         even if it's default location is /usr/local/lib

Setting up gnu system root is the first step to construct gnu software stack on the system.
And, now it's done.
So, next step is installing packages to set up development-friendly environment on the Android device.
Below description is summary of issues that I faced against during installing gnu packages.

* Executing /usr/bin/su doesn't run ~/.bashrc
    ~/.bashrc is not executed if user shell is set up as /bin/sh, even if /bin/sh is just symbolic link of /bin/bash.
    Let's assume that /bin/sh -> /bin/bash.
    In this case, executing /bin/sh means "run bash as just 'shell' - sh".
    So, to make ~/.bashrc be run automatically, default shell of user should be set as /bin/bash not /bin/sh

* default .bashrc of normal(ex. ubuntu) desktop PC can be used as a template in Android device.

* terminal editor programs - vi, nano, emacs etc - don't work or work abnormally.
    Environment related with 'Terminal' should be set correctly.
        - Environment variables
            export TERM=xterm
            export TERMINFO=/etc/terminfo
            export TERMCAP=/etc/termcap
    Related files at /etc
        terminfo
            this has setting values for various terminal types - linux, vt100, xterm and so on.
            /etc/terminfo of desktop linux PC can be used as it is.
        termcap
            this is required by emacs.
            termcap.src(included at termcap source release) can be used as /etc/termcap.

* mode of newly created file becomes 0666 or 0777.
    umask should be set at .bashrc .
        umask 022

* window of editor programs like vi, emacs is default screen size (80x24)
 even if real screen size of terminal emulator is bigger.
    resize command should be executed.
    putting it at .bashrc is recommended.
    this command sets environment variables - COLUMNS and LINES - according to current terminal window size
   and export it.

* various colors are not used at the output of ls command.
    check that dircolors command is installed and this command is set correctly at .bashrc

* sudo command doesn't give any chance to enter password. It only says "Sorry, try again.".
    pam is not correctly binded with sudo.
    install /etc/pam.d/sudo file.
    (sample.pam included at sudo source code release can be a good reference.
     - especially, second option - use pam_unix - is recommended)

* icmp protocol is not recognized by ping - included at inetutils - command.
    check /etc/protocols file is correctly installed.
    this file can be used by copying desktop's one.

* localhost is not recognized even though ip address - 127.0.0.1  - works well.
    check followings at /etc/hosts
        127.0.0.1    localhost
    check below line at /etc/nsswitch.conf (related with nameserver)
        hosts: files dns

Anything to do?

This is due to flow control.
C-s and C-q is reserved key sequence for flow control.
So, by disabling it - just type 'stty -ixon' - you can use C-s and C-q key sequence.

* common

+ '-rdynamic' is not supported.
  android dynamic linker allows 'undefined symbol' only for weak symbol.(See (*1))
+ 'tmpfile()' function always returns NULL. "No such file or directory!"
+ 'strtod()' doesn't support '0xXXXX' format.

* NDK 8

'regex.h' exists in 'include'. But function bodies are not in library.

* NDK 9

'pthread_rwlock_xxxx' is declared in 'pthread.h'. But body is missing in library.
'pthread_exit' is declared without 'noreturn' attribute.
'regex' functions doesn't work as it should be. (bug? or not-implemented yet?? I have no idea.)

to be continued...

===== Details =====

(*1) : '-rdynamic' and 'weak' symbol (Updated at 2011-Aug-29)

Here is sample code to for testing 'weak' symbol at Android.

[ main.c ]
#include <dlfcn.h>
#include <stdio.h>

int g_d;

void
main() {
    void* handle;
    void  (*prf)(void);

    g_d = 369;

    handle = dlopen("/data/libgtst.so", RTLD_LAZY);
    if (!handle) {
        printf("Fail to load library\n");
        return;
    }

    prf = dlsym(handle, "print_g");
    if (NULL != dlerror()) {
        printf("Fail to get symbol print_g\n");
        return;
    }

    (*prf)();
    printf("=== DONE! ===\n");
}

[ lib.c ]
#include <stdio.h>

extern int g_d __attribute__((weak));

void
print_g(void) {
    printf("==> %d\n", g_d);
}

[ Android.mk ]
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libgtst
LOCAL_SRC_FILES := lib.c

LOCAL_CFLAGS :=
LOCAL_C_INCLUDES += $(NDK_PROJECT_PATH)
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := main.c
LOCAL_CFLAGS :=
LOCAL_LDFLAGS :=
LOCAL_C_INCLUDES += $(NDK_PROJECT_PATH)
include $(BUILD_EXECUTABLE)

----- Test Steps -----
* build above codes at Android NDK
adb push libgtst.so /data/libgtst.so
adb push test /data/test
adb shell /data/test
==> 369
=== DONE! ===

to be continued...

Model : HP EliteBook 8530w
Host : Linux hbg683-laptop 2.6.35-24-generic-pae #42-Ubuntu SMP Thu Dec 2 03:21:31 UTC 2010 i686 GNU/Linux

Current state : 'nvidia-xxx' is installed at 'synaptic package manager'. And then driver is updated by 'NVIDIA-Linux-x86-260.19.12.run' installer.
=> visual effect doesn't work.

Actions done : uninstall all 'nvidia-xxx' packages from 'synaptic package manager'. And then install driver by running 'NVIDIA-Linux-x86-260.19.12.run' installer.
=> Some errors are raised. (something like cannot copy xxx-260.19.06 bla... bla...)

Now visual effect works very well!!

+ Recent posts