리눅스 커널 영역에서는 사용자 메모리 공간을 포인터를 이용해서 메모리를 바로 사용할 수 없다.
따라서 복사해야 한다.

유저영역의 메모리를 커널로 복사하는 함수는 copy_from_user 이다.

이런 불편함때문에 생긴게 mmap 이다.  어플이 메모리를 커널에 바로 메모리를 (zero copy) 잡는다.



안드로이드 ipc에는 이런 코드들이 있다. 
binder_wirte_read struct를 을 복사할 때는 copy_from_user, get_user 함수를 이용한다.

transport 하는 데이터는 mmap 으로 관리하도록 되어 있다.
binder_mmap 함수가 바로 그것..

그 안에 binder_update_page_range 함수를 호출하여 물리메모리와 커널의 가상메모리의 수신버퍼, 사용자 공간의 수신버퍼를 매핑한다.

Posted by '김용환'
,
Posted by '김용환'
,



안드로이드 소스





* intent 사용예제

// 1. 어떤 이름인지 모를 때. (클래스 이름을 모를때)
// 필터를 줄 수 있다. 서버의 manifest.xml의 service -> intent-filter -> action에 넣어야 한다. 
Intent i = new Intent("com.google.p.server.REMOTE_SERVICE");

// 2. 클래스 이름을 알고 있을 때.
//             Intent i = new Intent(IMyService.class.getName());



* bind


생명주기













  이미지 출처 
     http://shadowxx.egloos.com/10726222
    http://blog.naver.com/mirnae/100101468187




* aidl

http://developer.android.com/guide/developing/tools/aidl.html

aidl 매니저가  aidl 파일을 일고 stub 코드를 알아서 생성
client가 쓸 수 있는 proxy 코드와 server가 쓸 수 있는  stub 코드를 생성한다.


package com.google.p.server;

interface IMyService {
 int getStatus();
}




=> gen 디렉토리 밑에 자동으로 파일을 생성되어 있다.


/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: C:\\AndroidP\\eclipse\\workspaces\\RemoteServerClient\\src\\com\\google\\p\\server\\IMyService.aidl
 */
package com.google.p.server;
public interface IMyService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.google.p.server.IMyService
{
private static final java.lang.String DESCRIPTOR = "com.google.p.server.IMyService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.google.p.server.IMyService interface,
 * generating a proxy if needed.
 */

public static com.google.p.server.IMyService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.google.p.server.IMyService))) {
return ((com.google.p.server.IMyService)iin);
}
return new com.google.p.server.IMyService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getStatus:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getStatus();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.google.p.server.IMyService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public int getStatus() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getStatus, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int getStatus() throws android.os.RemoteException;
}





* manifest.xml 

 service에 remote 설정하고 프로세스 단위의 통신이 된다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.google.p.client"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AIDLClient"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.google.p.server.MyService" android:process=":remote" >
            <intent-filter>
                <action android:name="com.google.p.server.REMOTE_SERVICE"></action>
            </intent-filter>
        </service>

    </application>
</manifest>




어플을 올리고, bind 가 되게 한 후(start binding),
 DDMS로 확인하니. 아래와 같이 remote 프로세스가 뜨는지 확인


adb shell로 들어가서, proc 정보를 본다.



어느 파일들을 읽고 있나 본다.
app_process 프로세스와 binder , dalvk 관련 내용들이  보인다.



결국 이런 개념이 됨
 remoteservice.jpg


(이미지 출처 : http://liveeasily.dothome.co.kr/wiki/doku.php?id=android_service)



---------------------------------

인사이드 안드로이드 의 8장 안드로이드 서비스 프레임워크
(네이티브) 샘플 소스를 보드에 넣어보고 테스트해 보기


HelloWorld 시스템 소스



1. 복사를 먼저 한다. 
1)  include 파일은 소스디렉토리\frameworks\base\include 에 include에  복사
2) libs 파일은 소스디렉토리\\frameworks\base\libs 에 libs 에 복사
3) helloworld client 소스는 소스디렉토리\\frameworks\base\helloworld 에 복사

2. 다음은 전체 컴파일을 한다.  

소스디렉토리 # ./build_android.sh 

3. output이 정상적으로 나왔는지 확인
소스디렉토리\out\target\product\sv210\system\lib 밑에 보면,libhelloworld.so 파일이 들어가 있다.


서비스와 클라이언트 파일이 정상적으로 만들어졌는지 본다.

 

4. 이미지 복사
소스빌드디렉토리에서 (out\target\product\sv210)  root.img, system.img 파일을 복사하여 이미지를 다운받기 좋은 곳으로 보낸다.
기존에 있던 bootloader  zImage 파일도 복사해 둔다.


5. 이미지 다운로드
Hybus 보드에 그 이미지를 넣는다.  odin 같은거 없고, 벤더에서 준 ndw.exe 라는 파일을 이용한다.
드라이버 설치하고 나서, 내 컴의 ndw.exe 를 실행한다.

1) nand init
nand scrub
nand erase 80000 FF80000

2) kernel write
nand erase 600000 500000
dnw c0008000
[내 컴의 ndw.exe] Select USB Port -> Transmit -> Transmit -> Select zImage
nand write c0008000 600000 500000

3) root.img write
nand erase b00000 500000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select root.img
nand write.yaffs 40000000 b00000 <byte size of system.img>

4) system.img write
nand erase 1000000 5a00000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select system.img
nand write.yaffs 40000000 1000000  <byte size of system.img>

5) reset
(Hybus를 재시작한다.)


6. adb shell로 명령어를 통해 디바이스로 접근하고 실행해 본다.

# cd /system/bin
# ./helloworldservide &
# ./helloworldclient
hello, world




--------------------------------------------------

안드로이스 시스템 서비스 예제

vender 디렉토리에 넣고, 그 부분만 컴파일 하기

소스



zip을 풀고, 소스 디렉토리\external 아래로 복사하고 빌드한다.
hybus의 기계이름은 HyBus_sv210이다.

# .  build/envsetup.sh
# chooseproduct  HyBus_sv210
# mmm  external/ExService3

make 파일처럼 out\target\product\sv210\system\lib 디렉토리에 libSQRS03.so이 나왔다.

(vender depedent)
4. Hybus 에서는 yaffs로 system  이미지를 바꿔야 한다. system.img를 yaffs 파일시스템 형식으로 변환

소스디렉토리/vendor# ./mkyaffs2image  /work/android_froyo_sv210/out/target/product/sv210/system system.img
system 디렉토리를 yaffs 파일시스템형식으로 img 파일을 복사한다.

(원형    # vendor/mkyaffs2image  system  system.img )


4. 빌드 결과 이미지를 타깃 시스템에 올린다.

1) nand init
nand scrub
nand erase 80000 FF80000

2) kernel write
nand erase 600000 500000
dnw c0008000
[내 컴의 ndw.exe] Select USB Port -> Transmit -> Transmit -> Select zImage
nand write c0008000 600000 500000

3) root.img write
nand erase b00000 500000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select root.img
nand write.yaffs 40000000 b00000 <byte size of system.img>

4) system.img write
nand erase 1000000 5a00000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select system.img
nand write.yaffs 40000000 1000000  <byte size of system.img>

5) reset
(Hybus를 재시작한다.)


5. 결과 확인
#adb shell로 접근한다.

 


6. server 실행하기

  # logcat &

  # addserver03 &

7. client 실행하기

  # sqrtest3





Posted by '김용환'
,

안드로이드 플러그인이 설치된 이클립스에서 새로운 프로젝트를 생성한다.
Create proejcty from existing sample을 선택하면 Sample 컴보박스가 뜬다.





여기서 예제들을 선택하고 개념을 파악하면 쉽다.



Posted by '김용환'
,