89898
# 背景

「[試して理解
Linuxの仕組み](https://gihyo.jp/book/2018/978-4-7741-9607-7)」という書籍の3章を読んでいます。

# 質問

以下のコードで、`execve`関数を実行しています。

```

    static void child()
    {
        char *args[] = { "/bin/echo", "hello" , NULL};
        printf("I'm child! my pid is %d.\n", getpid());
        fflush(stdout);
        execve("/bin/echo", args, NULL);
        err(EXIT_FAILURE, "exec() failed");
    }
    
```

<https://github.com/satoru-takeuchi/linux-in-
practice/blob/faf52235402e10461a667a6c46cd60b87c2c3303/03-process-
management/fork-and-exec.c#L6-L13>

`execve`関数に渡す`args`の先頭要素は`/bin/echo`です。第1引数には`/bin/echo`を指定しているのに、なぜ`args`の先頭要素にも`/bin/echo`を指定しているのでしょうか？

[マニュアル](https://nxmnpg.lemoda.net/ja/2/execve)を眺めてみましたが、よく分かりませんでした。
CC BY-SA 4.0
2022-07-11T00:59:29.713
89894
2022-07-11T23:46:04.127
19524
question
c
execve関数の第2引数の先頭要素には、なぜ`/bin/echo`などの実行ファイルのパスを指定する必要があるのでしょうか？
execveの最初の"/bin/echo"は実行するプログラムの名称（パス）です。  
argsはそのプログラムに渡す引数ですので、意味が違いますが、  
argsの最初の引数には、実行するプログラムが入ります。  
なので、このようになっています。
CC BY-SA 4.0
2022-07-11T01:14:35.660
89897
2022-07-11T01:14:35.660
24490
89894
answer
UNIX ([linux](/questions/tagged/linux "'linux' のタグが付いた質問を表示")) の世界において
`argv[0]` は起動されたプログラムのファイル名ということになっています。一方で hardlink/symlink
という機能によって、１つのファイル本体に複数の名前を付けることができるようになっています。例えばウチの hpux11.11 では `vi` と `ex`
というコマンドは同一のファイル（の別名）となっています。

```

    $ ls -li /usr/bin/ex /usr/bin/vi
    8882 -r-x-r-xr-t 6 bin bin 249856 1月 18   2008 /usr/bin/ex
    8882 -r-x-r-xr-t 6 bin bin 249856 1月 18   2008 /usr/bin/vi
    $
    
```

今 `vi` として起動したいのか `ex` として起動したいのかを `argv[0]` で指定することができるわけです。

別のプラットフォームでの典型例は `busybox` で、実際の挙動は `argv[0]` で決まることになります。 [組み込み Linux で際立つ
busybox の魅力](https://monoist.itmedia.co.jp/mn/articles/0802/04/news114.html)

提示例はこういうのと関係ない例で、なので `argv[0]` はごく普通にファイル名と同一のものを（二重に）指定しているわけです。

* * *

これだけだとわかりにくい？かも、と思ったので未検証のコードを追記  
# 期待通りに動かないかもしれないけどその場合は勘弁してちょ  
# C++ の人は適切に `const` ないしは 非 `const` 化が必要かもしれない

```

    char *args[] = { "ls", NULL};
    execve("/bin/busybox", args, NULL); // だと ls として動作
    
```

ほぼ同等だけど

```

    char *args[] = { "cat", "/etc/passwd", NULL};
    execve("/bin/busybox", args, NULL); // だと cat として動作
    
```
CC BY-SA 4.0
2022-07-11T01:15:06.230
89898
2022-07-11T23:46:04.127
2022-07-11T23:46:04.127
8589
8589
89894
answer