ブログの引越
ブログを引っ越すことにしました。新ブログは https://utshina.hatenablog.jp/ です。
主に研究分野(OSや仮想化、セキュリティなどのシステムソフトウェア)に関することを記述します。
品川研究室 のホームページもよろしくお願いします。
mruby を Linux カーネル内で動作させる
mruby を Loadable Kernel Module (LKM) として Linux カーネル内動作させて printk する方法をメモしておきます。
1年以上前に書きかけていたものを完成させたので、mrubyのバージョンが古いです。最近のバージョンだとどうなるのかは分かりません。
mruby のビルド
まず GitHub から mruby のソースコードをダウンロードします。今回試したのは f65a39f4d19b1de019b0b805ccfb081757e5b7b5 (Wed Sep 18 20:00:35 2013 -0700) です。
$ git clone https://github.com/mruby/mruby.git
$ cd mruby
$ git checkout f65a39f4d19b1de019b0b805ccfb081757e5b7b5
次にカーネル内で動作するバージョンをクロスビルドするための設定を追加します。これにより、ホスト上で動く通常の mruby とは別に、build/kernel 以下にカーネル内動作用の mruby がビルドされます。
$ cat >> build_config.rb MRuby::CrossBuild.new('kernel') do |conf| toolchain :gcc conf.cc.flags << "-Iinclude/kernel -mcmodel=kernel -mno-red-zone -mfpmath=387 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -msoft-float -fno-asynchronous-unwind-tables -fno-omit-frame-pointer" conf.cc.defines << %w(DISABLE_STDIO) conf.cc.defines << %w(DISABLE_FLOAT) conf.cc.defines << %w(MRB_INT64) end (ctrl-d)
次にカーネル内で動作させるためのヘッダファイルを作成します。
stdlib.h は必要最小限のものに置き換えます。これにより浮動小数点関係のエラーが減ります。
$ mkdir include/kernel $ cat > include/kernel/stdlib.h typedef unsigned long size_t; void free(void *ptr); void *realloc(void *ptr, size_t size); int abs(int j); unsigned long int strtol(const char *nptr, char **endptr, int base); unsigned long int strtoul(const char *nptr, char **endptr, int base); void exit(int status); #define EXIT_SUCCESS 0 #define EXIT_FAILURE (-1) void abort(void); int atoi(const char *nptr); # define strtod(p,e) strtol(p,e,10) (ctrl-d)
stdarg.h は vsnprintf 関係のものだけを gcc の builtin 関数で記述します。
$ cat > include/kernel/stdarg.h typedef unsigned long size_t; typedef __builtin_va_list __gnuc_va_list; typedef __gnuc_va_list va_list; #define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l) int vsnprintf(char *str, size_t size, const char *format, va_list ap); (ctrl-d)
浮動小数点は使わないので、全部ごまかします。
$ cat > include/kernel/math.h # define fmod(x,y) (x) # define pow(x,y) (x) # define log10(x) (x) # define floor(x) (x) # define ceil(x) (x) # define isinf(x) 0 # define isnan(x) 0 (ctrl-d)
内部のfloat型(mrb_float)をlongで置き換えます。
$ cat > value.h.patch --- include/mruby/value.h.orig 2013-09-19 13:24:11.378647350 +0900 +++ include/mruby/value.h 2013-09-19 16:15:33.647687793 +0900 @@ -7,7 +7,13 @@ #ifndef MRUBY_VALUE_H #define MRUBY_VALUE_H -#ifdef MRB_USE_FLOAT +#if defined(DISABLE_FLOAT) + typedef long mrb_float; +# define double long +int sprintf(char *str, const char *format, ...); +# define mrb_float_to_str(buf, i) sprintf(buf, "%d", i) +# define str_to_mrb_float(buf) strtol(buf, NULL, 10) +#elif defined(MRB_USE_FLOAT) typedef float mrb_float; # define mrb_float_to_str(buf, i) sprintf(buf, "%.7e", i) # define str_to_mrb_float(buf) strtof(buf, NULL) (ctrl-d) $ patch -p0 < value.h.patch
浮動小数点演算をしているところを片っ端から潰します。計算結果のことはここでは考えません。
$ cat > numeric.c.patch --- src/numeric.c.orig 2013-09-19 13:24:11.389647270 +0900 +++ src/numeric.c 2013-09-19 16:34:56.098316936 +0900 @@ -209,7 +209,7 @@ if (m < 0) { m -= 1; } - n = n / pow(10.0, m); + n = n / pow((mrb_float)10.0, m); m = 0; } else { @@ -222,15 +222,15 @@ /* puts digits */ while (max_digit >= 0) { - mrb_float weight = pow(10.0, m); - digit = (int)floor(n / weight + FLT_EPSILON); + mrb_float weight = pow((mrb_float)10.0, m); + digit = (int)floor(n / weight + (mrb_float)FLT_EPSILON); *(c++) = '0' + digit; n -= (digit * weight); max_digit--; if (m-- == 0) { *(c++) = '.'; } - else if (m < -1 && n < FLT_EPSILON) { + else if (m < -1 && n < (mrb_float)FLT_EPSILON) { break; } } @@ -324,7 +324,7 @@ mrb_float div; mrb_float mod; - if (y == 0.0) { + if (y == (mrb_float)0.0) { div = str_to_mrb_float("inf"); mod = str_to_mrb_float("nan"); } @@ -336,7 +336,7 @@ div = (x - mod) / y; if (y*mod < 0) { mod += y; - div -= 1.0; + div -= (mrb_float)1.0; } } @@ -457,7 +457,7 @@ d = (mrb_float)mrb_fixnum(num); /* normalize -0.0 to 0.0 */ - if (d == 0) d = 0.0; + if (d == 0) d = (mrb_float)0.0; c = (char*)&d; for (hash=0, i=0; i<sizeof(mrb_float);i++) { hash = (hash * 971) ^ (unsigned char)c[i]; @@ -615,10 +615,10 @@ mrb_get_args(mrb, "|i", &ndigits); number = mrb_float(num); - f = 1.0; + f = (mrb_float)1.0; i = abs(ndigits); while (--i >= 0) - f = f*10.0; + f = f*(mrb_float)10.0; if (isinf(f)) { if (ndigits < 0) number = 0; @@ -630,13 +630,13 @@ else number *= f; /* home-made inline implementation of round(3) */ - if (number > 0.0) { + if (number > (mrb_float)0.0) { d = floor(number); - number = d + (number - d >= 0.5); + number = d + (number - d >= (mrb_float)0.5); } - else if (number < 0.0) { + else if (number < (mrb_float)0.0) { d = ceil(number); - number = d - (d - number >= 0.5); + number = d - (d - number >= (mrb_float)0.5); } if (ndigits < 0) number *= f; @@ -662,8 +662,8 @@ { mrb_float f = mrb_float(num); - if (f > 0.0) f = floor(f); - if (f < 0.0) f = ceil(f); + if (f > (mrb_float)0.0) f = floor(f); + if (f < (mrb_float)0.0) f = ceil(f); if (!FIXABLE(f)) { return mrb_float_value(mrb, f); (ctrl-d) $ patch -p0 < numeric.c.patch
make して build/kernel/lib/libmruby.aがビルドできればOKです。その他のコンパイルエラーは放置します。
$ make ... AR build/kernel/lib/libmruby.a ar: /home/shina/mruby-kernel/mruby/build/kernel/lib/libmruby.a を作成しています ...
ホスト環境での mruby での Hello World
まずはホスト環境(Linux)で mruby の動作を確認します。host というディレクトリを mruby の隣に作って試します。
$ cd .. $ mkdir host $ cd host
下記の main.c は mruby の実行環境を呼び出すプログラムです。今回は "Kernel" というモジュールと "printk" というクラスメソッドを用意します。実体は printf しているだけです。
$ cat > main.c #include "mruby.h" #include "mruby/proc.h" #include "mruby/string.h" extern uint8_t code[]; static mrb_value kernel_printk(mrb_state *mrb, mrb_value self) { mrb_value retval; mrb_value str; mrb_get_args(mrb, "S", &str); printf("%s", RSTRING_PTR(str)); retval.value.i = 0; return retval; } int main(int argc, char **argv) { mrb_state *mrb; struct RClass *kernel; mrb_value ret; mrb = mrb_open(); kernel = mrb_define_module(mrb, "Kernel"); mrb_define_class_method(mrb, kernel, "printk", kernel_printk, ARGS_REQ(1)); ret = mrb_load_irep(mrb, code); return ret.value.i; } (ctrl-d)
次に実行する ruby のプログラム hello.rb を用意します。Kernel クラスの printk メソッドを呼び出すだけです。
$ cat > hello.rb Kernel.printk "Hello World!\n" (ctrl-d)
ビルドするための Makefile です。先ほどビルドした mruby のホスト環境を使います。mrbc は ruby のコードを mruby のバイトコード(のC言語の配列表現)に変換するプログラムです。
$ cat > Makefile CFLAGS = -I../mruby/include -g LDFLAGS = -lm OBJS = main.o hello.o LIBS = ../mruby/build/kernel/lib/libmruby.a main: $(OBJS) $(LIBS) $(CC) $(OBJS) $(LIBS) $(LDFLAGS) -o $@ hello.c: hello.rb ../mruby/bin/mrbc -Bcode $< (ctrl-d)
make して実行して動作を確認します。
$ make cc -I../mruby/include -g -c -o main.o main.c ../mruby/bin/mrbc -Bcode hello.rb cc -I../mruby/include -g -c -o hello.o hello.c cc main.o hello.o ../mruby/build/kernel/lib/libmruby.a -lm -o main $ ./main Hello World!
Linux カーネル内での mruby での Hello World
次に Linux で動作するカーネルモジュールを作成します。kernel というディレクトリを mruby の隣に作って試します。
$ cd .. $ mkdir kernel $ cd kernel
まずはカーネルモジュールの初期化・終了をおこなうコードです。
$ cat > lkm.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/ctype.h> extern int mruby_main(void); static int lkm_init(void) { printk(KERN_INFO "LKM: init\n"); return mruby_main(); } static void lkm_exit(void) { printk(KERN_INFO "LKM: exit\n"); } module_init(lkm_init); module_exit(lkm_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("mruby"); MODULE_AUTHOR("Takahiro Shinagawa"); (ctrl-d)
次に mruby を呼び出すコードです。先ほどのホストで動作するものとほとんど同じです。
$ cat > main.c #include <linux/kernel.h> #include "mruby.h" #include "mruby/irep.h" #include "mruby/string.h" extern uint8_t code[]; static mrb_value kernel_printk(mrb_state *mrb, mrb_value self) { mrb_value retval; mrb_value str; mrb_get_args(mrb, "S", &str); printk(KERN_INFO "mruby: %s\n", RSTRING_PTR(str)); retval.value.i = 0; return retval; } int mruby_main(void) { mrb_state *mrb; struct RClass *kernel; mrb_value ret; mrb = mrb_open(); kernel = mrb_define_module(mrb, "Kernel"); mrb_define_class_method(mrb, kernel, "printk", kernel_printk, ARGS_REQ(1)); ret = mrb_load_irep(mrb, code); printk("mruby: ret = %d\n", ret.value.i); return 0; } (ctrl-d)
次に libc をエミュレーションするライブラリです。必要最低限しかエミュレーションしていないので、ちゃんと定義されていない関数が呼び出されたら正常に動作しないでしょう。
$ cat > libc.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> typedef unsigned long size_t; void *realloc(void *ptr, size_t size); void free(void *ptr); typedef int jmp_buf[6]; int setjmp(jmp_buf env); void longjmp(jmp_buf env, int val); int * __errno_location(void); const unsigned short * * __ctype_b_loc (void); long int strtol(const char *nptr, char **endptr, int base); unsigned long int strtoul(const char *nptr, char **endptr, int base); void abort(void); void exit(int status); void *realloc(void *ptr, size_t size) { return krealloc(ptr, size, GFP_KERNEL); } void free(void *ptr) { kfree(ptr); } int _setjmp(jmp_buf env) { return __builtin_setjmp(env); } void longjmp(jmp_buf env, int val) { __builtin_longjmp(env, 1); } int * __errno_location(void) { static int errno; return &errno; } const unsigned short * * __ctype_b_loc (void) { printk("%s\n", __FUNCTION__); return NULL; } const unsigned short * * __ctype_tolower_loc (void) { printk("%s\n", __FUNCTION__); return NULL; } const unsigned short * * __ctype_toupper_loc (void) { printk("%s\n", __FUNCTION__); return NULL; } int isspace(int c) { return (c == 0x20) | (0x09 <= c && c <= 0x0d); } int isdigit(int c) { return ('0' <= c && c <= '9'); } int isupper(int c) { return ('A' <= c && c <= 'Z'); } int islower(int c) { return ('a' <= c && c <= 'z'); } int isalpha(int c) { return isupper(c) || islower(c); } long int strtol(const char *nptr, char **endptr, int base) { printk("%s: %s\n", __FUNCTION__, nptr); return 0; } unsigned long int strtoul(const char *nptr, char **endptr, int base) { printk("%s: %s\n", __FUNCTION__, nptr); return 0; } void abort() { printk("%s\n", __FUNCTION__); } void exit(int status) { printk("%s\n", __FUNCTION__); } (ctrl-d)
最小限のヘッダファイルを作成します。
$ cat > stdint.h typedef unsigned char uint8_t; (ctrl-d) $ echo > inttypes.h
最後に Makefile です。上記のコードに加えて、先ほど hello.rb をバイトコードに変換したものと、mruby のライブラリをリンクします。
$ cat > Makefile ccflags-y += -DDISABLE_STDIO -I$(PWD)/../mruby/include -I$(PWD) obj-m := mruby.o mruby-objs := lkm.o main.o libc.o ../host/hello.o ../mruby/build/kernel/lib/libmruby.a all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) CFLAGS_MODULE=$(CFLAGS) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean (ctrl-d)
make すると少し警告が出ますが、mruby.ko が生成されるはずです。
$ make ... $ ls mruby.ko mruby.ko
出来たカーネルモジュールをロードすると、カーネルのログに Hello World! が出力されるはずです。
$ sudo insmod mruby.ko $ dmesg | grep mruby ... [ 75.744877] mruby: Hello World! [ 75.744879] mruby: ret = 0
※GitHub にコードを置きました.https://github.com/utshina/mruby-lkm
ツールキットを使わずに UEFI アプリケーションの Hello World! を作る
UEFI アプリケーションを作成するためのツールキットには、EDK II や gnu-efi などがあります。しかし、EDK II は複雑すぎて中身の構造が分かりにくく、とっつきにくい印象があります。また、gnu-efi は wrapper 経由で関数を呼び出さなければならないなど、標準的な UEFI アプリケーションのソースコードと若干異なるものになってしまうのが気になります。
そこで、UEFI の勉強も兼ねて、これらのツールキットを使わずに、本当に最小限の Hello World を表示するだけのアプリケーションを作ってみました。
開発環境は Linux です。必要な物は PE32+ executable を作るためのクロスコンパイラです。私は Fedora を使っているので、下記のコマンドでインストールできました。他のディストリビューションを使っている場合は、適宜探してインストールしてみてください。
yum install mingw64-gcc
実際に作成してみたソースコード(main.c)は以下のとおりです。定義はコンソール出力に必要な物だけに絞っており、かなり端折ってあります。その代わり、見える部分の定義はなるべく UEFI の仕様書のとおりになるようにしてみました。
#define IN #define EFIAPI #define EFI_SUCCESS 0 typedef unsigned short CHAR16; typedef unsigned long long EFI_STATUS; typedef void *EFI_HANDLE; struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; typedef EFI_STATUS (EFIAPI *EFI_TEXT_STRING) ( IN struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, IN CHAR16 *String ); typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { void *a; EFI_TEXT_STRING OutputString; } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; typedef struct { char a[52]; EFI_HANDLE ConsoleOutHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; } EFI_SYSTEM_TABLE; EFI_STATUS EFIAPI EfiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); while(1); return EFI_SUCCESS; }
EfiMain がエントリーポイントです。この関数に渡される EFI_SYSTEM_TABLE 型の SystemTable が各種システム・サービスへのポインタとなっています。その中に EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL 型の ConOut というデータがあり、オブジェクト指向のような関数テーブルとなっています。この中の OutputString という関数を呼び出すと、コンソールに文字列を出力することが出来ます。出力する文字列は Unicode なので、文字列の定義に L を付けます。
上記の main.c をコンパイルするための Makefile は以下のとおりです。
CC = x86_64-w64-mingw32-gcc CFLAGS = -shared -nostdlib -mno-red-zone -fno-stack-protector -Wall \ -e EfiMain all: main.efi %.efi: %.dll objcopy --target=efi-app-x86_64 $< $@ %.dll: %.c $(CC) $(CFLAGS) $< -o $@ qemu: main.efi OVMF.fd image/EFI/BOOT/BOOTX64.EFI qemu-system-x86_64 -nographic -bios OVMF.fd -hda fat:image image/EFI/BOOT/BOOTX64.EFI: mkdir -p image/EFI/BOOT ln -sf ../../../main.efi image/EFI/BOOT/BOOTX64.EFI OVMF.fd: wget http://downloads.sourceforge.net/project/edk2/OVMF/OVMF-X64-r15214.zip unzip OVMF-X64-r15214.zip OVMF.fd clean: rm -f main.efi
クロスコンパイラとして x86_64-w64-mingw32-gcc を指定しています。他のディストリビューションでは名称が異なるようですので、適宜修正してください。
このクロスコンパイラを使って、まず普通の PE 形式のファイル main.dll を作ります。余計なものをリンクしないように、-nostdlib を付けています。また、エントリポイントとして EfiMain を指定しています。
生成された main.dll は Windows 等で使われる DLL などと同じ形式になっているので、objcopy を使って subsystem が 10 になるように変換して、UEFI アプリケーションとして認識されるようにします。
生成された main.efi を qemu を使って実行してみます。
まず、qemu 用の UEFI のファームウェアである OVMF.fd を入手します。http://tianocore.sourceforge.net/wiki/OVMF から最新のファームウェアをダウンロードできます。執筆時点では、r15214 でした。先ほどの Makefile を使うと自動的に入手できます。
make OVMF.fd
次に先ほどの Makefile を使って qemu を起動します。
make qemu
-nographic を指定することで、グラフィックスモードは使わずに、コンソールから起動するようにしています。-bios で UEFI のファームウェアのファイルを指定しています。-hda fat:image とすることで、image ディレクトリ以下を FAT フォーマットの仮想ディスクとして見えるようにしています。image 以下には EFI/BOOT/BOOTX64.EFI というファイル名で生成された EFI ファイルを置いておくことで、仮想マシンの起動時に自動的に EFI アプリケーションが実行されるようにしています。
うまくいけば、Hello World! と表示されて停止するはずです。Ctrl-a x で qemu を抜けましょう。
Boot Failed. EFI Floppy
Boot Failed. EFI Floppy 1
Boot Failed. EFI DVD/CDROM
Hello World!
QEMU: Terminated
※GitHub にコードを置きました.https://github.com/utshina/uefi-simple
OS & システムソフトウェアの一流国際会議
OSやシステムソフトウェアをメイントピックとする著名な国際会議を4つ紹介します。
SOSP (ACM Symposium on Operating Systems Principles)
概要
OSやシステムソフトウェアの分野における世界最高峰の国際会議。名称は "Operating Systems" だが、分散システム、ネットワーク、ストレージ、セキュリティ、組み込み等に関するシステムソフトウェア全般を幅広く扱う。
- 2年に1回しか開催されない(下記のOSDIと交互に開催)
- 第1回は1967年、2011年に第23回
- 最近7回(1999年〜2011年)の平均採択率は 17% (154本/885本)
1999 | 2001 | 2003 | 2005 | 2007 | 2009 | 2011 | 計 | |
投稿 | 90 | 85 | 128 | 155 | 131 | 139 | 157 | 885 |
採択 | 19 | 17 | 22 | 20 | 25 | 23 | 28 | 154 |
採択率 | 21.1% | 20.0% | 17.2% | 12.9% | 19.1% | 16.5% | 17.8% | 17.4% |
- 2011年の査読は3ステージ制
- double blind、論文1本につき3〜8名の査読者、査読総数719、最終的にはコアPCメンバー13名で採択を決定
- 内容の濃い論文
- レターサイズ14ページ程度
- 高い被引用数
論文数 | 被引用数 | 平均被引用数 | H-index | |
---|---|---|---|---|
ACM Digital Library (2013年1月現在) | 609 (-82※) | 22,315 | 36.64 | - |
Microsoft Academic Search のデータ (2013年1月現在) | 413 | 21,287 | 51.5 | 73 |
※ACMのデータは関連ワークショップ論文を含む。
論文
※「会議ページ」からは論文やスライド、ビデオ等が無料でダウンロード可能
- SOSP: ACM Digital Library
- SOSP 2011: ACM Digital Library, 会議ページ
- SOSP 2009: ACM Digital Library, 会議ページ
- SOSP 2007: ACM Digital Library, 会議ページ
- SOSP 2005: ACM Digital Library
OSDI (USENIX Symposium on Operating Systems Design and Implementation)
概要
SOSP と並ぶOSやシステムソフトウェアの分野における超一流国際会議。SOSP が徹底した "evaluation" により完全に完成した(≒終了した)仕事が多いのに対し、OSDI は(比較的)設計・実装の面白さを重視した論文が多い。
- 2年に1回しか開催されない(上記の SOSP と交互に開催)
- 第1回は1994年、2012年に第10回
- 歴史は比較的浅いものの、ACM SIGOPSと連携しており、当初よりレベルの高い論文が多い。
- 最近7回(2000年〜2012年)の平均採択率は 15.5% (188本/1,211本)
2000 | 2002 | 2004 | 2006 | 2008 | 2010 | 2012 | 計 | |
投稿 | 111 | 150 | 193 | 150 | 193 | 199 | 215 | 1,211 |
採択 | 24 | 27 | 27 | 27 | 26 | 32 | 25 | 188 |
採択率 | 21.6% | 18.0% | 14.0% | 18.0% | 13.5% | 16.0% | 11.6% | 15.5% |
- 2010年の査読は3ラウンド制
- 内容の濃い論文
- レターサイズ14〜16ページ程度
- 高い被引用数
論文数 | 被引用数 | 平均被引用数 | H-index | |
---|---|---|---|---|
ACM Digital Library (2013年1月現在) | 221 | 7,817 | 35.37 | - |
Microsoft Academic Search のデータ (2013年1月現在) | 236 | 15,631 | 66.23 | 70 |
- 著名システムに関する論文もしばしば掲載される
- 日本人が第一著者の論文は1本?
EuroSys (The European Conference on Computer Systems)
概要
2006年に誕生したばかりで歴史は浅いが、当初より高いレベルを保っている一流国際会議。異常にレベルの高い SOSP や OSDI を補完する受け皿として、普通のトップカンファレンスとしての地位を確立しつつある。
- 毎年開催される
- 第1回は2006年、2012年に第7回
- 最近7回(2006年〜2012年)の平均採択率は 17.9% (185本/1,036本)
2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 計 | |
投稿 | 144 | 131 | 131 | 149 | 141 | 161 | 179 | 1,036 |
採択 | 29 | 29 | 24 | 25 | 27 | 24 | 27 | 185 |
採択率 | 20.1% | 22.1% | 18.3% | 16.8% | 19.1% | 14.9% | 15.1% | 17.9% |
- 2012年の査読は3ラウンド制
- 第1ラウンドは査読者3名以上(96本が次のラウンドへ)、第2ラウンドは査読者2名以上、評価の分かれた論文は第3ラウンドで更なる査読、査読総数750
- 査読コメントに対する著者の反論機会あり
- 全ての採択論文にはPCメンバーによるシェパードが付く
- 内容の濃い論文
- レターサイズ14ページ程度
- 高い被引用数
論文数 | 被引用数 | 平均被引用数 | H-index | |
---|---|---|---|---|
ACM Digital Libraryのデータ(2013年1月現在) | 382(-197※) | 3,184 | 8.34 | - |
Microsoft Academic Search のデータ(2013年1月現在) | 178 | 3,356 | 18.85 | 30 |
※ACMのデータは関連ワークショップ論文を含む。
論文
- EuroSYS: ACM Digital Library
- EuroSys 2012: ACM Digital Library
- EuroSys 2011: ACM Digital Library
- EuroSys 2010: ACM Digital Library
- EuroSys 2009: ACM Digital Library
USENIX ATC (Annual Technical Conference)
概要
近年アカデミックな論文発表の場として定着してきた一流国際会議。EuroSys と並んで SOSP や OSDI に通らなかった論文の受け皿として成長してきた。EuroSys に落ちた論文を投稿できるように日程調整等がされるときもある。
- 団体としての USENIX は "The Advanced Computing Systems Association" とも称される
- 近年は年に1回開催される
- Winter と Summer の年2回開催されていた時期もある
- "Annual" と付くようになったのは 1996 年頃から
- Technical Conference 自体は1980年代始めから開催されていたようである
- 開催回数が不明確なため、正式名称は "2012 USENIX Annual Technical Conference" のように年を記載する
- 最近7回(2006年〜2012年)の平均採択率は 15.1% (182本/1,202本)
2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 計 | |
投稿 | 153 | 170 | 176 | 191 | 147 | 180 | 185 | 1,202 |
採択 | 21 | 24 | 28 | 28 | 22 | 27 | 32 | 182 |
採択率 | 13.7% | 14.1% | 15.9% | 14.7% | 15.0% | 15.0% | 17.3% | 15.1% |
- 2012年の査読は3ラウンド制
- 第1ラウンドは査読者2人、第2ラウンドでは3人目の査読者が付く場合があり、第3ラウンドでは4,5人目の査読者が付く場合がある
- 全ての採択論文にはPCメンバーによるシェパードが付く
- 内容の濃い論文
- レターサイズ12〜14ページ程度
- 高い被引用数
論文数 | 被引用数 | 平均被引用数 | H-index | |
---|---|---|---|---|
Microsoft Academic Search のデータ(2013年1月現在) | 1,471 | 41,035 | 27.90 | 93 |
- 日本人が第一著者の論文は2000年以降は2本?
論文
- USENIX: USENIX Proceedings
- USENIX ATC 2012: Technical Sessions
- USENIX ATC 2011: Technical Sessions
- USENIX ATC 2010: Technical Sessions
- USENIX ATC 2009: Technical Sessions