20200


forkそのものを説明しているサイトでは求められている前提の条件やサンプルとプログラムの量からわかりやすいものがなく難しいです。

例えば、私が行いたい。htmlに含まれる画像リンクを保存するプログラムだとしたらどのように記述したらいいですか？

自分が知っている画像の保存方法はcurlコマンドを使った

[code]

    system（"curl -o ~/download/ex001.jpg http://ex001.ｊｐｇ"）;
    
[/code]

のようなものです。  
ここで、exは９９９まであり一枚あたり1MBほどでサイトによって１URLに対して５０ｋｂｐｓに制限されているとしたらとても時間がかかるように思います。  
５件以上同時にダウンロードした場合攻撃として検出されるサイトだとします。その場合、適切な制御が必要になります。

私は`fork`を使うことで問題が解決できると思ったのですが、効率的でネットワークをフルに使えるような方法はありませんか？


CC BY-SA 3.0
2015-12-19T10:30:07.947
20177
2015-12-20T04:25:39.147
2015-12-19T14:24:36.940
13656
13656
question
c
forkについて簡潔でわかりやすい説明をしてもらいたいのですが


サンプルを作ってみました。

[code]

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    #define PARA 4
    
    static void child(void)
    {
        char buf[1024];
        while (fgets(buf, sizeof buf, stdin) != NULL) {
            char cmd[1024], *p;
            if ((p = strchr(buf, '\n')) != NULL)
                *p = '\0';
            sprintf(cmd, "wget '%s'", buf);
            system(cmd);
        }
    }
    
    int main(void)
    {
        int i;
        int fd[PARA];
    
        for (i = 0; i < PARA; i++) {
            int fds[2];
            if (pipe(fds) == -1) {
                perror("pipe");
                exit(1);
            }
    
            switch (fork()) {
            case -1:
                /* エラー */
                perror("fork");
                exit(1);
    
            case 0:
                /* 子プロセス */
                close(fds[1]);
                dup2(fds[0], 0);
                child();
                exit(0);
    
            default:
                /* 親プロセス */
                close(fds[0]);
                fd[i] = fds[1];
            }
        }
    
        char buf[1024];
        int to_child = 0;
        while (fgets(buf, sizeof buf, stdin) != NULL) {
            write(fd[to_child], buf, strlen(buf));
    
            if (++to_child >= PARA)
                to_child = 0;
        }
    
        return 0;
    }
    
[/code]

実行すると、子プロセスを4つ作り、親プロセスは子プロセスにパイプ経由で URL を送り、子プロセスはそれを受け取り、処理します。当初、子プロセス 1つにつき
1つの URL
を処理して、どんどんプロセスを作ってどんどん終了して、という感じで考えていましたが、質問内容を改めて読み、一定個数のプロセスだけで処理した方が簡単なのでは、と思い直しました。

あと、このサンプルでは URL は親プロセスが標準入力からもらいます。ダウンロードは私が wget の方が慣れているため wget を使いました。


CC BY-SA 3.0
2015-12-20T03:39:52.710
20200
2015-12-20T03:39:52.710
5288
20177
answer


**system(3)**

> The `system()` library function uses `fork(2)` to create a child process
> that executes the shell command specified in command using `execl(3)` as
> follows:
[code]

>     execl("/bin/sh", "sh", "-c", command, (char *) 0);
>  
[/code]

つまり `system(3)` 関数の使用はシェルスクリプトを実行する事と同等ですので、C
でプログラムを作成する事が制約条件ではないのであれば、例えば以下の様なシェルスクリプトでも良いのではないでしょうか。

[code]

    $ seq -f 'ex%03g.jpg' 999 | xargs -P4 -I@ -n1 curl -s -o ~/download/@ http://hogehoge/@ &
    
[/code]

`xargs` コマンドの `-P` オプションで同時に実行される(最大)プロセス数を指定しています。


CC BY-SA 3.0
2015-12-20T04:25:39.147
20202
2015-12-20T04:25:39.147
20177
answer