SYSCALLS(2)

Linuxの全システムコールのリストを得たいときは、SYSCALLS(2)という第2章の目次のような項目が参考になります。

$ man syscalls



NAME
       syscalls - Linux system calls

SYNOPSIS
       Linux system calls.

DESCRIPTION
       The system call is the fundamental interface between an application and the Linux kernel.


       System call                 Kernel        Notes
       ────────────────────────────────────────

       _llseek(2)                  1.2
       _newselect(2)
       _sysctl(2)
       accept(2)
       accept4(2)                  2.6.28
       access(2)
       acct(2)
       add_key(2)                  2.6.11
       adjtimex(2)
       afs_syscall(2)                            Not implemented
       alarm(2)
       alloc_hugepages(2)          2.5.36        Removed in 2.5.44
       bdflush(2)
       bind(2)
       break(2)                                  Not implemented
       brk(2)
       cacheflush(2)               1.2           Not on i386


以下続く。


システムコールの総数が定義されているのは、/usr/include/asm/unistd_32.h

/*
 * This file contains the system call numbers.
 */

#define __NR_restart_syscall      0
#define __NR_exit                 1
#define __NR_fork                 2
#define __NR_read                 3
#define __NR_write                4
#define __NR_open                 5
#define __NR_close                6
#define __NR_waitpid              7
以下続く。

ちなみに僕の環境(Ubuntu10.04、32bit)では、システムコールの総数は337個でした。







main()の第三引数の検証

main()には環境変数を格納する第三の引数(*envp[])が存在します。
*envp[]は環境変数を格納する文字列に対してのポインタ配列です。

以下のプログラムでは、envp[]が参照する配列の中身を順次表示させるものです。


/* myenv.c */
/* 第3の引数を検証するプログラム*/
#include<stdio.h> /* printf */

/*
main(int argc, char *argv[], char *envp[])
int argc;
char *argv[];
char *envp[];

*/


int main(int argc, char *argv[],char *envp[])
{
int i;
/* env[i]が存在する限り繰り返す */
for(i=0; envp[i]; i++){
printf("%s\n", envp[i]);
}

return 0;
}

gccが行っている作業を検証してみる

GCCはいくつかのコマンドによって構成されているらしいのである。

普段のgcc -o outfile infileと入力するだけだが、裏では様々なイベントが発生している。

gccは、

プリプロセッサ: /lib/cpp
コンパイラ : /usr/lib/gcc/i686-linux-gnu/4.4/cc1
アセンブラ : /usr/bin/as
リンカ: /usr/bin/lib

の4つのコマンド適宜呼び出すための、ドライバとしての働きをします。

以下に、ここのコマンドを個別に呼び出して、実行形式ファイルを作成する方法を示します。

#1.ソースコードの作成
$ vim hello.c

#include<stdio.h>

int main(void)
{
printf("Hello, world!\n");
return 0;
}

#2.プリプロセス(#で始まる内容の展開;ヘッダーファイルの取り込み、マクロの展開)
#プリプロセスの結果は標準出力に出されるので、リダイレクトしてファイルに出力する。
/lib/cpp hello.c > hello.i

#3.プリプロセスにより生成した中間ファイルをアセンブリソース(hello.s)にコンパイル
$ /usr/lib/gcc/i686-linux-gnu/4.4/cc1 hello.i


#4.アセンブラによりアセンブルを行いオブジェクトファイル(hello.o)を生成
$ /usr/bin/as hello.s -o hello.o

#5.オブジェクトファイル、共有ライブラリファイル(libc.so)、スタートアップルーチン(/usr/lib/crt1.o)等をダイナミックリンクさせ、実行形式ファイル(hello)を生成
$ /usr/bin/ld  -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/libc.so /usr/lib/crtn.o hello.o

#6.実行形式ファイルを実行
$ ./hello
Hello, world!


理解すると非常にすっきりできるお話です。コンパイルは、入門書には非常に観念的なレベルのみ説明されていることがほとんだと思います。

今回のように、一つ一つんファイルをフルパスで指定していくと、コンパイルの本質が見てきます。

ちなみに、同様の作業は、gccに特定のオプションをつければ可能です。











ld -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o hello.o -lc /usr/lib/crtn.o

MacでOpenGL

Mac OS Xの場合(10.6)、デフォルトでOpenGLがインストールされています。


$ gcc -framework GLUT -o file  sourcefile.c

のように入力すればコンパイル可能です。

ubuntuにOpenGLをインストール

$ sudo apt-get update
$ sudo apt-get install freeglut3-dev libglew1.5-dev

#テスト
$ vim test.c



/*test.c*/
#include <GL/glut.h>

int main(int argc,char *argv[])
{
/*初期化*/
glutInit(&argc,argv);
/*ウィンドウ作成*/
glutCreateWindow(argv[0]);
/*メインループ*/
glutMainLoop();

return 0;

}

#コンパイル


$ gcc -lglut -o test test.c