C言語のポインタと配列

プロセスの生成と、環境変数
プロセスの生成と環境変数









mainの引数: arg-print.c
mainの引数: 実行例
char *argv[ ]の構造
C言語のポインタと配列、2次元配列
コンパクトな配列: char *argv[ ]の構造
プログラムとプロセス
プロセスの操作
プロセスの生成と環境変数: newenv.c
プロセスの生成と環境変数: ./newenv

環境変数: env-print.c
環境変数: 実行例

ライブラリ関数 getenv(): home-print.c

ライブラリ関数 getenv() : 実行例

プロセスの生成と、環境変数
mainの引数: arg-print.c

プログラムを実行する時、コマンドラインから引数を渡すこと
がで きる。
#include <stdio.h>
main( int argc, char *argv[], char *envp[] )
{
int i ;
printf("&argc == 0x%x, argc == %d\n",
&argc, argc );
printf("&argv == 0x%x, argv == 0x%x\n",
&argv, argv );
for( i=0 ; argv[i] ; i++ )
printf("argv[%d]==0x%x, \"%s\"\n",
i,argv[i],argv[i] );
}
プロセスの生成と、環境変数
mainの引数: 実行例





argv[0] には、プログラムの名前が含まれている。
argv[1] 以降に、普通の意 味での引数が含まれている。
argc には、プログラムの名前まで含めての引数 の数が含まれている。
argv[0] からargv[argc-1] まで参照できる。
argv[argc] は、参照してはいけない(0が入っているはずではあるが)
プロセスの生成と、環境変数
char *argv[ ]の構造


char *argv[ ]は、2次元配列
ではない。
char *argv[ ]は、 char への
ポインタの配列の先頭番地
を入れたポインタ変数。
プロセスの生成と、環境変数
C言語のポインタと配列、2次元配列
C言語のポインタと配列
 C言語で char *argv[] は、*argv[0] と
書いたら char 型(8ビットの 整数)とい
う意味である。
 C言語で char *p と宣言した時、*p と
p[0] は、同じである。 *(p+1) と p[1] も
同じである。
C言語の2次元配列
 2次元配列は、C言語では配列の配
列として表される。
 char array[10][20];
 これで、全部で 10*20*1 == 200 バイト
のメモリが確保される。
 array[i][j] の番地を計算するには、次
のようになる。
 (1) arrayの先頭番地を求める。
 (2) (1)の値に + i*20 を加える。
 (3) (2)の値に j を加える。
2次元配列
char array[10][20];
プロセスの生成と、環境変数
コンパクトな配列: char *argv[ ]の構造







main() の引数で char *argv[] と char
**argv は、同じ意味になる。
argv[i] は、 *(argv+i)、 argv[i][j] は、
*(*(argv+i)+j) という意味になる。
char *argv[] で、argv[i][j] と書いた時の番
地の計算の仕方は、次のように なる。

(1) argv の番地の内容を load する。

(2) (1)の値に + i*4 を加え、その値の
番地の内容を load する。

(3) (2)の値に j を加える。
2次元配列と違って、番地を求めるだけで、
間に load が2回入る所に注意する。
2次元配列だと番地を計算する時には、
load は出てこない。
(main の)引数で、char *argv[] と char
**argv は、よいが、char argv[][] は、伝統
的にはエラーになる。
argv[i][j] を計算しようとすると、i を何倍 し
てよいのか計算できない。しかし、受け付
けるコンパイラもある。
プロセスの生成と、環境変数
プログラムとプロセス


プロセッサ(CPU)が実行できる
機械命令の列がプログラムで
ある。
プロセスとは、プログラムが、オ
ペレーティング・システムによっ
てメモリに読 み込まれ、そして、
オペレーティング・システムの管
理下にあるプロセッサによって
実行の対象になったものである。
プロセスの生成と、環境変数
プロセスの操作
プロセスを操作する機能には次のようなものがある。








fork()
新しくプロセスを作る。
execve()
プログラムを更新し実行する。
ps コマンド 動いているプロセスを調べる。
killコマンド、killシステムコール 動いているプロセスを殺す。
killコマンド、killシステムコール 動いているプロセスを一時的に止める。
killコマンド、killシステムコール 一時的に止まっているプロセスの実行
を再開させる。
niceコマンド プロセスの優先順位を変える。
ptraceシステムコール プロセスの実行の様子を調べる。
プロセスの生成と、環境変数
プロセスの生成と環境変数: newenv.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[], char
*envp[])
{
int i;
for (i=0;envp[i]!=NULL;i++) {
printf("%s\n",envp[i]);
}
return EXIT_SUCCESS;
}
プロセスの生成と、環境変数
プロセスの生成と環境変数: ./newenv
% ./newenv
PWD=/home/oida/
USER=oida
親プロセス
(シェル)
fork();
… 環境変数の一覧が
表示される
%
子プロセス(コマンド)
path
n e w e n v \0
argv[0]
argv[1]
n e w e n v \0
NULL
envp[0]
envp[1]
execにより
ロード
PATH= / u
SHE L L = /
.
.
execve(path,argv,envp);
引数を渡す
newenvコマンド
main(argc,argv,envp)
プロセスの生成と、環境変数
環境変数: env-print.c



環境変数は、プログラムからは、①main() の3番目の引数、②外部変数
environ 、 ③ライブラリ関数 getenv() でアクセスできる。
メモリ中の構造は、argv と同 じである。
各文字列は、「変数名=値」の形式になっている。
extern char **environ ;
main( int argc, char *argv[], char *envp[] )
{
int i ;
printf("envp == 0x%x\n",envp );
printf("environ == 0x%x\n",environ );
for( i=0 ; envp[i] ; i++ )
printf("envp[%d]==0x%x, \"%s\"\n",
i,envp[i],envp[i] );
for( i=0 ; environ[i] ; i++ )
printf("environ[%d]==0x%x, \"%s\"\n",
i,environ[i],environ[i] );
}
プロセスの生成と、環境変数
環境変数: 実行例


main の第3引数 envp と大域変数 environ は、同じ値である。
環境変数には、 ①ホーム・ディレクトリの名前を保持している HOME、
②コマンドを検索するディ レクトリの名前のリストを表す PATH、③標
準的に使われるエディタを表す EDITOR などがある。
プロセスの生成と、環境変数
ライブラリ関数 getenv(): home-print.c
環境変数は、ライブラリ 関数 getenv() を使ってアクセスした方が簡単である。

#include <string.h>
#include <stdlib.h>
/* strncmp() */
/* getenv() */
extern char **environ ;
main()
{
int i ;
char *homedir ;
for( i=0 ; environ[i] ; i++ )
{
if( strncmp(environ[i],"HOME=",5)==0 )
{
homedir = environ[i] ;
printf("0x%x, [%s]\n", homedir, homedir );
break;
}
}
homedir = getenv("HOME");
printf("getenv(\"HOME\")== 0x%x, [%s]\n",
homedir, homedir);
}
プロセスの生成と、環境変数
ライブラリ関数 getenv(): 実行例




環境変数 HOME の値を調べるは、外部変数 environ の中から
“HOME=” という 5 文字から始まるものを探す。
これには、 strncmp() を使うと便利である。
自分でループで探さなくても、getenv() ライブラリ関数を使う方法がある。
この場合、"HOME=" の 5 文字がスキップされた値(0xbffffa9d+5==
0xbffffaa2)が得られる。