0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

fork()、execve()

Posted at
#!/usr/bin/python3
import os, sys
ret = os.fork()
if ret == 0:
    print("子プロセス:pid={}, 親プロセスのpid={}".format(os.getpid(), os.getppid()))
    exit()
elif ret > 0:
    print("親プロセス:pid={}, 子プロセスのpid={}".format(os.getpid(), ret))
    exit()
sys.exit(1)
root@*******:*******# python3 hello.py
親プロセス:pid=3302, 子プロセスのpid=3303
子プロセス:pid=3303, 親プロセスのpid=3302

os.fork()

子プロセスを forkします。子プロセスでは 0 が返り、親プロセスでは子プロセスの id が返ります。エラーが発生した場合は、 OSError を送出します。

出典

getpid()

現在のプロセス id を返します。

出典

getppid()

親プロセスのプロセス id を返します。親プロセスが終了していた場合、Unix では init プロセスの id (1) が返され、Windows では親のプロセス id だったもの (別のプロセスで再利用されているかもしれない) がそのまま返されます。

出典

sys.exit([arg])

Raise a SystemExit exception, signaling an intention to exit the interpreter.

オプション引数 arg には、終了ステータスとして整数 (デフォルトは0)や他の型のオブジェクトを指定することができます。整数を指定した場合、シェル等は 0 は "正常終了"、0 以外の整数を "異常終了" として扱います。多くのシステムでは、有効な終了ステータスは 0--127 で、これ以外の値を返した場合の動作は未定義です。システムによっては特定の終了コードに個別の意味を持たせている場合がありますが、このような定義は僅かしかありません。Unix プログラムでは構文エラーの場合には 2 を、それ以外のエラーならば 1 を返します。arg に None を指定した場合は、数値の 0 を指定した場合と同じです。それ以外の型のオブジェクトを指定すると、そのオブジェクトが stderr に出力され、終了コードとして 1 を返します。エラー発生時には sys.exit("エラーメッセージ") と書くと、簡単にプログラムを終了することができます。

出典

気づき

子プロセスでは 0 が返り、親プロセスでは子プロセスの id が返りますを読むと、二つ値が返っているようだ。
配列のようになっているのだろうか?

なぜ二回処理しているのか? retの値を調べてみる

#!/usr/bin/python3
import os, sys
ret = os.fork()
print(ret)
if ret == 0:
    print("子プロセス:pid={}, 親プロセスのpid={}".format(os.getpid(), os.getppid()))
   # os.execve("/bin/echo", ["echo", "pid={}からこんにちは".format(os.getpid())], {})
    print(ret)
    exit()
elif ret > 0:
    print("親プロセス:pid={}, 子プロセスのpid={}".format(os.getpid(), ret))
    print(ret)
    exit()
sys.exit(1)
root@**********:**********# python3 hello.py
3619
親プロセス:pid=3618, 子プロセスのpid=3619
3619
root@**********:**********# 0
子プロセス:pid=3619, 親プロセスのpid=1716
0

気づき

二回やってることがわかった。
本当にプロセスが分身している

execve()関数

#!/usr/bin/python3
import os, sys
ret = os.fork()
if ret == 0:
    print("子プロセス:pid={}, 親プロセスのpid={}".format(os.getpid(), os.getppid()))
    os.execve("/bin/echo", ["echo", "pid={}からこんにちは".format(os.getpid())], {})
    exit()
elif ret > 0:
    print("親プロセス:pid={}, 子プロセスのpid={}".format(os.getpid(), ret))
    exit()
sys.exit(1)
root@*******:*******# python3 hello.py
親プロセス:pid=3340, 子プロセスのpid=3341
子プロセス:pid=3341, 親プロセスのpid=3340
root@*******:*******# pid=3341からこんにちは

os.execve

これらの関数はすべて、現在のプロセスを置き換える形で新たなプログラムを実行します ; 現在のプロセスは返り値を返しません。 Unix では、新たに実行される実行コードは現在のプロセス内に読み込まれ、呼び出し側と同じプロセス ID を持つことになります。エラーは OSError 例外として報告されます。

出典

さまざまな exec* 関数は、プロセス内にロードされる新しいプログラムに与えるための、引数のリストを取ります。どの関数の場合でも、新しいプログラムに渡されるリストの最初の引数は、ユーザがコマンドラインで入力する引数ではなく、そのプログラム自体の名前です。 C プログラマならば、プログラムの main() に渡される argv[0] だと考えれば良いでしょう。たとえば、 os.execv('/bin/echo', ['foo', 'bar']) が標準出力に出力するのは bar だけで、 foo は無視されたかのように見えることになります。

出典

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?