GFP_KERNELとGFP_ATOMICの違い

2,572 views
Skip to first unread message

mochidai

unread,
May 20, 2011, 10:20:23 PM5/20/11
to 日本Androidの会
はじめまして。

現在パケットのレイヤ2ヘッダとレイヤ3ヘッダの間に
通信時に経由するルータの帯域情報等を埋め込むための
カーネル拡張を作成しています。

開発自体はUbuntuで進めていたもので、今回Android向けに移植
しようとしているのですが、malloc関連でエラーが起きており
AndroidのにおけるGFP_KERNELとGFP_ATOMICの取り扱いの
違いについて教えていただけないでしょうか。

具体的なエラーはroot権限でAndroid端末にログインし、
上記の機能を実現するカーネル拡張ip_sirens.koを読み込むと次のようなエラーが出ます。

insmod ip_sirens.ko
insmod: init_module 'ip_sirens.ko' failed (Device or resource busy)

原因は次のmalloc関連のGFP_KERNELによって起こることが
分かり、GFP_ATOMICに書き換えることで読み込み自体はエラーが
なくなりました。しかしUbuntuではGFP_KERNELで読み込めるものが、
なぜAndroidでは読み込めないのかわからず悩んでおります。


1478 /* allocate network interface tracking storage */
1479 read_lock(&dev_base_lock);
1480 for_each_netdev(&init_net, dev) {
1481 srip = kzalloc(sizeof (struct SRIFEntry), GFP_KERNEL);


考えられる理由としては
・端末のスペックの違い(メモリの搭載量など)
・UbuntuとAndroidではGFP_ATOMICの取り扱いが異なる。
などが考えられると思いますが、もし他の要因があるようでしたら
教えていただけないでしょうか。

利用している端末はNexus Oneで
・Android 2.2
・カーネルバージョン 2.6.32.9-27237-gbe746fb android-build@apa26#1
・ビルド番号 FRG33
となっています。

すべてのソースは
http://i-path.goto.info.waseda.ac.jp/trac/i-Path/browser/trunk/linux/SIRENSLinux/ip_sirens.c
です。


大垣憲俊

unread,
May 21, 2011, 9:41:47 AM5/21/11
to android-g...@googlegroups.com
大垣です。

私は、あまり詳しくないので他の方のフォローを期待しますが、
ちょっと気になったことを確認したくなりまして。

このソースをダウンロードして、ndkでビルドしようとしたのですが、
Android.mkの内容が分からずビルドできなかったため、以下推測です。

もし、ライブラリに stlport、gnu-libstdc++ を使用されるとすれば、
Ubuntuのようにフルスペックではないらしいので、違いはありうるかも、と。

もし、とんちんかんな受け答えだとしたら、笑って許してください。


大垣憲俊

unread,
May 21, 2011, 8:45:01 PM5/21/11
to 日本Androidの会
大垣です。

> もし、ライブラリに stlport、gnu-libstdc++ を使用されるとすれば、
> Ubuntuのようにフルスペックではないらしいので、違いはありうるかも、と。

カーネルモジュールなので、ライブラリは関係なかったですね。
すみません。。。

mochidai

unread,
May 22, 2011, 3:24:26 AM5/22/11
to 日本Androidの会
大垣さん

どうもありがとうございます。
もともとはPCルータ向けに作っているソースなので
メモリ管理が特殊な仕様ではないかと思い、質問してみた次第です。


Android向けにビルドするためには
次のディレクトリにあるMakefileとip_sirens.hが必要で、クロスコンパイルをしています。
http://i-path.goto.info.waseda.ac.jp/trac/i-Path/browser/trunk/linux/SIRENSLinux

make ARCH=arm CROSS_COMPILE=(Androidのソースディレクトリ)/prebuilt/linux-
x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- KERNEL_DIR=(AndroidのKernel)

大垣憲俊

unread,
May 22, 2011, 6:58:39 AM5/22/11
to 日本Androidの会
大垣です。こちらこそ、ありがとうございます。

ビルドして確認しようと思い、以下のサイトを参考に試しています
http://www.ekesete.net/log/?p=1710

カーネルがどれだか分からなかったので、ひとまず以下
$git clone git://android.git.kernel.org/kernel/msm kernel -b android-
msm-2.6.32


他サイトの情報も確認してみて、何か分かればお知らせします。
それより先に、私より詳しい方がフォローされるとは思いますが。。。


On 5月22日, 午後4:24, mochidai <mochi...@gmail.com> wrote:
> 大垣さん
>
> どうもありがとうございます。
> もともとはPCルータ向けに作っているソースなので
> メモリ管理が特殊な仕様ではないかと思い、質問してみた次第です。
>
> Android向けにビルドするためには
> 次のディレクトリにあるMakefileとip_sirens.hが必要で、クロスコンパイルをしています。http://i-path.goto.info.waseda.ac.jp/trac/i-Path/browser/trunk/linux/...

理一中野

unread,
May 22, 2011, 8:23:21 AM5/22/11
to android-g...@googlegroups.com
はじめまして

中野と申します。
釈迦に説法ならゴメンナサイ。
>・端末のスペックの違い(メモリの搭載量など)
>・UbuntuとAndroidではGFP_ATOMICの取り扱いが異なる
ご存知とは思いますが、
GFP_ATOMICはメモリアロケートできない場合には
内部でblocking waitせずに即時復帰する仕様と思います。
実際カーネルソースで確認した訳ではないのですが、
UbuntuとAndroidでアロケータの仕様が変わっているのは信じにくいです。

もし、クロスコンパイルが通らないのでGFP_KERNELを
GFP_ATOMICに変更したコードを実行してオカシクなっているのなら
GFP_KERNELでクロスコンパイルを通すのが先決と思います。
そうでないならAndroidの実メモリ不足を疑いたくなります。

ともかく、ネットワーク受信可割り込みの延長上で動作する
ネットワーク受信モジュール内でメモリプールに確保済みのデータに
「ルータの帯域情報等を埋め込む」のですから
GFP_ATOMICオプションはよほど厳格なエラー処理を実装しない限り
不味いように思います。

重ねて釈迦に説法ならゴメンナサイ。
以上、よろしくお願いします。
2011年5月22日19:58 大垣憲俊 <noritos...@gmail.com>:

> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。
>
>

大垣憲俊

unread,
May 22, 2011, 12:51:53 PM5/22/11
to 日本Androidの会
大垣です。中間報告です。

先ほどのカーネルではコンパイルエラーになるので、変更してカーネルのビルドはできました。

$git clone git://android.git.kernel.org/kernel/msm kernel -b archive/
android-msm-2.6.32

しかし、教えていただいた方法で、ip_sirensをビルドしようとすると、
「ターゲット `modules' を make するルールがありません」とのエラーになります。
(本題に入る前にひっかかってどうする、私と。。。)

> >> make ARCH=arm CROSS_COMPILE=(Androidのソースディレクトリ)/prebuilt/linux-
> >> x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- KERNEL_DIR=(AndroidのKernel)

実際のコマンドラインは、以下のようにしました。
Androidのソースディレクトリ下にip_sirensディレクトリを置いています。

make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-
eabi-4.4.0
/bin/arm-eabi- KERNEL_DIR=../kernel/arch/arm/boot

大垣憲俊

unread,
May 22, 2011, 9:17:24 PM5/22/11
to 日本Androidの会
大垣です。

> しかし、教えていただいた方法で、ip_sirensをビルドしようとすると、
> 「ターゲット `modules' を make するルールがありません」とのエラーになります。
> (本題に入る前にひっかかってどうする、私と。。。)

教えていただいたurlの上位にreadmeがあるのに気づき見たところ
単に make コマンド一発だということが分かりました。(初心者なもので。。。)

ビルドはできましたので、エミュレータか使わなくなったHT-03Aで試してみます。

mochidai

unread,
May 24, 2011, 12:38:35 AM5/24/11
to 日本Androidの会
中野さん

どうもありがとうございます。私は不勉強でしてGFP_ATOMICの
にしてしまうなど、まずは使えることを優先していました。

ご指摘のとおり実メモリ不足が考えられると思います。



On May 22, 9:23 pm, 理一中野 <riichi.nakano.0...@gmail.com> wrote:
> はじめまして
>
> 中野と申します。
> 釈迦に説法ならゴメンナサイ。>・端末のスペックの違い(メモリの搭載量など)
> >・UbuntuとAndroidではGFP_ATOMICの取り扱いが異なる
>
> ご存知とは思いますが、
> GFP_ATOMICはメモリアロケートできない場合には
> 内部でblocking waitせずに即時復帰する仕様と思います。
> 実際カーネルソースで確認した訳ではないのですが、
> UbuntuとAndroidでアロケータの仕様が変わっているのは信じにくいです。
>
> もし、クロスコンパイルが通らないのでGFP_KERNELを
> GFP_ATOMICに変更したコードを実行してオカシクなっているのなら
> GFP_KERNELでクロスコンパイルを通すのが先決と思います。
> そうでないならAndroidの実メモリ不足を疑いたくなります。
>
> ともかく、ネットワーク受信可割り込みの延長上で動作する
> ネットワーク受信モジュール内でメモリプールに確保済みのデータに
> 「ルータの帯域情報等を埋め込む」のですから
> GFP_ATOMICオプションはよほど厳格なエラー処理を実装しない限り
> 不味いように思います。
>
> 重ねて釈迦に説法ならゴメンナサイ。
> 以上、よろしくお願いします。
> 2011年5月22日19:58 大垣憲俊 <noritoshi.og...@gmail.com>:

noritoshi ogaki

unread,
May 24, 2011, 12:59:23 AM5/24/11
to android-g...@googlegroups.com
大垣です。

> ご指摘のとおり実メモリ不足が考えられると思います。

すでに結論が出たようなので、私も独りカラ回り状態を脱しようと思います。

かってに検証テストをしていましたが、結果が出せませんでした。
カーネルのビルドには成功したものの、
Ubuntuの/lib/module/下のMakefileを使うのが気になり、
UbuntuのOSバージョンとターゲットAndroidのバージョンを合わせるべき?
との疑問を感じながらも、
ともかくできあがったモジュールで insmod ip_sirens.ko とやると、
T-01C(まだAndroid2.1)では、許可なし(Operation Not Permitted)で、
HT-01Cは Android1.6なのでいくら何でもと思い、試していませんが、
avd2.2のエミュレータでも、何のエラーか忘れましたが、実行できませんでした。
rootユーザではなく、systemユーザでないとできないのですね、たぶん。

失礼しました。。。

mochidai

unread,
May 24, 2011, 2:51:51 AM5/24/11
to 日本Androidの会
大垣さん

返信が遅れまして失礼しました。
いろいろ試していただき、どうもありがとうございます。

> UbuntuのOSバージョンとターゲットAndroidのバージョンを合わせるべき?
はい。Androidのバージョンやarm環境向けのKernelのバージョンを細かく合わせる必要あります。
こちらでは実機でAndroid2.1と2.2で動作確認をしていますが、カーネルリビジョンをハッシュ値で
指定するなどが必要でした。
$git checkout be746fb2c3847ed8318ca713c5ab7dbcc6c80795


理一中野

unread,
May 24, 2011, 6:43:33 AM5/24/11
to android-g...@googlegroups.com
mochidaiさん、お疲れさまです。

返信ありがとうございます。

> 現在パケットのレイヤ2ヘッダとレイヤ3ヘッダの間に
> 通信時に経由するルータの帯域情報等を埋め込むための
> カーネル拡張を作成しています。
動的な帯域情報を保有するなんて、賢いパケットですね。
最近の常識なんでしょうか?
でも、通信系モジュールは様々な制約があり難しい。
だからやりがいがあると思います。


ご健闘を期待します。
中野
2011年5月24日13:38 mochidai <moch...@gmail.com>:

大垣憲俊

unread,
May 24, 2011, 7:26:57 AM5/24/11
to 日本Androidの会
mochidaiさん

> はい。Androidのバージョンやarm環境向けのKernelのバージョンを細かく合わせる必要あります。
> こちらでは実機でAndroid2.1と2.2で動作確認をしていますが、カーネルリビジョンをハッシュ値で
> 指定するなどが必要でした。
> $git checkout be746fb2c3847ed8318ca713c5ab7dbcc6c80795

教えてくださり、ありがとうございます。
興味がわいてきました。

カーネルソースをfgrepすれば、GFP_KERNELもGFP_ATOMICも出てくるので、
当然ながら、GFP_ATOMICでないと動かないというお話が、
再現できない=仕様ではない、と実際に示したかったのでした。。。

理一中野

unread,
May 24, 2011, 9:52:57 PM5/24/11
to android-g...@googlegroups.com
大垣さん、mochidaiさん

中野です。


> 実際カーネルソースで確認した訳ではないのですが、
> UbuntuとAndroidでアロケータの仕様が変わっているのは信じにくいです。
申し訳ありません。
Androidのアロケータ仕様は変更されているみたいでした。
推測で語ってしまった点を反省します。

> OSカーネルにはLinuxを採用。オープンソースとして提供されたAndroid 1.0は,
> カーネル2.6.25を採用する。
> これをベースに電源管理用モジュール,プロセス間通信用モジュール,
> メモリー量が不足したときにAndroid関連のプロセスを自動的に落とすモジュールなど,
> Android用のカーネル・モジュールが加えられている。
カーネル(アロケータ)内部でメモリ不足を検知するとプロセスを落としてしまう訳ですね。
週末にでもソースを読んで確認してみます。

> ご指摘のとおり実メモリ不足が考えられると思います。
納得です。
ありがとうございました。

2011年5月24日20:26 大垣憲俊 <noritos...@gmail.com>:

大垣憲俊

unread,
May 31, 2011, 8:49:50 AM5/31/11
to android-g...@googlegroups.com
mochidaiさん、中野さん

大垣です。

>・端末のスペックの違い(メモリの搭載量など) 
>・UbuntuとAndroidではGFP_ATOMICの取り扱いが異なる。 
>などが考えられると思いますが、もし他の要因があるようでしたら 
>教えていただけないでしょうか。 

froyoのカーネルソースを調べていて、以下に気づきました。
CONFIG_ANDROID_LOW_MEMORY_KILLER=y

これに対応するコードは、以下です。
<froyo>/kernal/drivers/staging/android/lowmemorykiller.c


それで、これをキーワードにネット検索したところ、以下が参考になりました。

「Androidのプロセスがkillされる基準」
2010/10/11 by demuyan

以下、一部を引用します。

「AndroidのLinuxカーネルにはその機能が2つ備わっていて、
一つがOOM(Out Of Memory) KillerというLinux本家での実装と、
もう一つLow Memory KillerというAndroid特有の機能として実装されているものがある。
じゃあ、OOM KillerとLow Memory Killerと何が違うのか? 
その答がAndroid Kernel Features – eLinux.orgoom handlingに書いてあったので紹介...」


理一中野

unread,
Jun 1, 2011, 6:32:59 AM6/1/11
to android-g...@googlegroups.com
大垣さん、mochidaiさん、お疲れさまです。

中野です。
大垣さん、情報ありがとうございました。


> Low Memory Killer
ashmem - Android shared memory
PMEM - Process memory allocatorに関するDave Sparksさんの説明が
とても分かりやすく納得できました。
アンドロイドでは「ashmem」と「pmem」の使い分けが微妙ですね。


メモリ不足時の、ubuntuとandroidの挙動の相違が明確になりました。
androidには「Low Memory Killer」があるので、
少ない実装メモリでもきめ細やかに制御可能なので、
アプリレベルではあまり頑張らなくてもよいが、GFP_KERNELが前提。
後腐れないようにプロセスを始末してくれるようですネ。

ありがとうございました。
中野

2011年5月31日21:49 大垣憲俊 <noritos...@gmail.com>:

> その答がAndroid Kernel Features - eLinux.orgのoom handlingに書いてあったので紹介...」

mochidai

unread,
Jun 1, 2011, 11:58:56 PM6/1/11
to 日本Androidの会
大垣さん、中野さん

情報をどうもありがとうございます。
Androidでのメモリの動作に違いがあるのですね。
プロセスがkillされる基準について、私は不勉強でしたが
とてもわかりやすく記述されていると感じました。



On Jun 1, 7:32 pm, 理一中野 <riichi.nakano.0...@gmail.com> wrote:
> 大垣さん、mochidaiさん、お疲れさまです。
>
> 中野です。
> 大垣さん、情報ありがとうございました。
>
> > Low Memory Killer
>
> ashmem - Android shared memory
> PMEM - Process memory allocatorに関するDave Sparksさんの説明が
> とても分かりやすく納得できました。
> アンドロイドでは「ashmem」と「pmem」の使い分けが微妙ですね。
>
> メモリ不足時の、ubuntuとandroidの挙動の相違が明確になりました。
> androidには「Low Memory Killer」があるので、
> 少ない実装メモリでもきめ細やかに制御可能なので、
> アプリレベルではあまり頑張らなくてもよいが、GFP_KERNELが前提。
> 後腐れないようにプロセスを始末してくれるようですネ。
>
> ありがとうございました。
> 中野
>
> 2011年5月31日21:49 大垣憲俊 <noritoshi.og...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages