fork()、execve()

```py
#!/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 を送出します。
### 出典
https://docs.python.org/ja/3/library/os.html#os.fork:~:text=%E5%AD%90%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%82%92%20fork%20%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%E5%AD%90%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%81%A7%E3%81%AF%200%20%E3%81%8C%E8%BF%94%E3%82%8A%E3%80%81%E8%A6%AA%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%81%A7%E3%81%AF%E5%AD%90%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%81%AE%20id%20%E3%81%8C%E8%BF%94%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%97%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AF%E3%80%81%20OSError%20%E3%82%92%E9%80%81%E5%87%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82
### getpid()
```現在のプロセス id を返します。```
### 出典
https://docs.python.org/ja/3/library/os.html#:~:text=os.-,getpid(),%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%20id%20%E3%82%92%E8%BF%94%E3%81%97%E3%81%BE%E3%81%99%E3%80%82,-The%20function%20is
### getppid()
```親プロセスのプロセス id を返します```。親プロセスが終了していた場合、Unix では init プロセスの id (1) が返され、Windows では親のプロセス id だったもの (別のプロセスで再利用されているかもしれない) がそのまま返されます。
### 出典
https://docs.python.org/ja/3/library/os.html#:~:text=getppid(),%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82
### 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("エラーメッセージ") と書くと、簡単にプログラムを終了することができます。
### 出典
https://docs.python.org/ja/3/library/sys.html#sys.exit:~:text=sys.exit(%5Barg,%E7%B5%82%E4%BA%86%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82
### 気づき
```子プロセスでは 0 が返り、親プロセスでは子プロセスの id が返ります```を読むと、二つ値が返っているようだ。
配列のようになっているのだろうか？

# なぜ二回処理しているのか？　retの値を調べてみる
```py
#!/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（）関数
```py
#!/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 例外として報告されます。
# 出典
https://docs.python.org/ja/3/library/os.html#os.execve:~:text=%E3%81%93%E3%82%8C%E3%82%89%E3%81%AE%E9%96%A2%E6%95%B0%E3%81%AF%E3%81%99%E3%81%B9%E3%81%A6%E3%80%81%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%82%92%E7%BD%AE%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B%E5%BD%A2%E3%81%A7%E6%96%B0%E3%81%9F%E3%81%AA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%BE%E3%81%99%20%3B%20%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%81%AF%E8%BF%94%E3%82%8A%E5%80%A4%E3%82%92%E8%BF%94%E3%81%97%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82%20Unix%20%E3%81%A7%E3%81%AF%E3%80%81%E6%96%B0%E3%81%9F%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%82%8B%E5%AE%9F%E8%A1%8C%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AF%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E5%86%85%E3%81%AB%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BE%E3%82%8C%E3%80%81%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E5%81%B4%E3%81%A8%E5%90%8C%E3%81%98%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%20ID%20%E3%82%92%E6%8C%81%E3%81%A4%E3%81%93%E3%81%A8%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AF%20OSError%20%E4%BE%8B%E5%A4%96%E3%81%A8%E3%81%97%E3%81%A6%E5%A0%B1%E5%91%8A%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

さまざまな exec* 関数は、プロセス内にロードされる新しいプログラムに与えるための、引数のリストを取ります。どの関数の場合でも、新しいプログラムに渡されるリストの最初の引数は、ユーザがコマンドラインで入力する引数ではなく、```そのプログラム自体の名前```です。 C プログラマならば、プログラムの main() に渡される argv[0] だと考えれば良いでしょう。たとえば、 os.execv('/bin/echo', ['foo', 'bar']) が標準出力に出力するのは bar だけで、 ```foo は無視```されたかのように見えることになります。
# 出典
https://docs.python.org/ja/3/library/os.html#os.execve:~:text=%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%20exec*%20%E9%96%A2%E6%95%B0%E3%81%AF%E3%80%81%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E5%86%85%E3%81%AB%E3%83%AD%E3%83%BC%E3%83%89%E3%81%95%E3%82%8C%E3%82%8B%E6%96%B0%E3%81%97%E3%81%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AB%E4%B8%8E%E3%81%88%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%80%81%E5%BC%95%E6%95%B0%E3%81%AE%E3%83%AA%E3%82%B9%E3%83%88%E3%82%92%E5%8F%96%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%E3%81%A9%E3%81%AE%E9%96%A2%E6%95%B0%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%A7%E3%82%82%E3%80%81%E6%96%B0%E3%81%97%E3%81%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AB%E6%B8%A1%E3%81%95%E3%82%8C%E3%82%8B%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AE%E6%9C%80%E5%88%9D%E3%81%AE%E5%BC%95%E6%95%B0%E3%81%AF%E3%80%81%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%8C%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%A7%E5%85%A5%E5%8A%9B%E3%81%99%E3%82%8B%E5%BC%95%E6%95%B0%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E3%80%81%E3%81%9D%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E8%87%AA%E4%BD%93%E3%81%AE%E5%90%8D%E5%89%8D%E3%81%A7%E3%81%99%E3%80%82%20C%20%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AA%E3%82%89%E3%81%B0%E3%80%81%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%20main()%20%E3%81%AB%E6%B8%A1%E3%81%95%E3%82%8C%E3%82%8B%20argv%5B0%5D%20%E3%81%A0%E3%81%A8%E8%80%83%E3%81%88%E3%82%8C%E3%81%B0%E8%89%AF%E3%81%84%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%80%82%E3%81%9F%E3%81%A8%E3%81%88%E3%81%B0%E3%80%81%20os.execv(%27/bin/echo%27%2C%20%5B%27foo%27%2C%20%27bar%27%5D)%20%E3%81%8C%E6%A8%99%E6%BA%96%E5%87%BA%E5%8A%9B%E3%81%AB%E5%87%BA%E5%8A%9B%E3%81%99%E3%82%8B%E3%81%AE%E3%81%AF%20bar%20%E3%81%A0%E3%81%91%E3%81%A7%E3%80%81%20foo%20%E3%81%AF%E7%84%A1%E8%A6%96%E3%81%95%E3%82%8C%E3%81%9F%E3%81%8B%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E8%A6%8B%E3%81%88%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82