ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

一つのプロセスが開けるファイルの数がリミットより3つ少ないわけ。

以前のエントリ
一つのプロセスが開けるファイルの数はいくつ?(分からずじまい)
で、リミットは2048なのに、アプリケーションから開けるファイルは2045である。という疑問が放置されたままでしたが、なんのことはない、標準入力、標準出力、標準エラーストリームの3つ分が既に確保されてしまっているからなのでした。


で、試しにそれらを閉じてみるプログラムを書いてみる。

#include <stdio.h>

void closeTest(int fd);

int main()
{
        int a;
        int retScanf, retFprintf;

        retScanf = scanf("%d", &a);
        printf("a = %d(%d)\n", a, retScanf);

        closeTest(0);

        retScanf = scanf("%d", &a);
        printf("a = %d(%d)\n", a, retScanf);

/*      closeTest(1); */

        retFprintf = fprintf(stderr, "error...\n");
        printf("retFprintf = %d\n", retFprintf);

        closeTest(2);

        retFprintf = fprintf(stderr, "error...\n");
        printf("retFprintf = %d\n", retFprintf);

        closeTest(3);

        return 0;
}

void closeTest(int fd)
{
        printf("closing fd %d...\n", fd);
        int retClose0 = close(fd);
        printf("close(%d) = %d\n", fd, retClose0);
        printf("fd %d closed.\n", fd);
}

0が標準入力、1が標準出力、2が標準エラーストリームみたいです。
で、0をクローズする前までは、scanfで値が読めていたのに、クローズ後は読めなくなっている。
同様に、2をクローズする前までは、fprintf(stderr, ...)で書けていたのに、クローズ後は書けなくなっています。
ちなみに、標準出力を閉じたら、以降何も出力されずにプログラムが終わったので、異常終了したのかと勘違いしましたが、標準出力を閉じているので、何も出なくなって当然でした(汗


標準出力を閉じないで実行した場合の結果はこんな感じ。

taka@ubuntu:~$ ./a.out
12
a = 12(1)
closing fd 0...
close(0) = 0
fd 0 closed.
a = 12(-1)
error...
retFprintf = 9
closing fd 2...
close(2) = 0
fd 2 closed.
retFprintf = -1
closing fd 3...
close(3) = -1
fd 3 closed.
taka@ubuntu:~$


ところで、標準入力と標準エラーストリームを閉じたら、アプリケーションで開けるファイル数は2つ増えるか?と思い、やってみることに。


まずは、リミットを調べる。

taka@ubuntu:~$ ulimit -n
1024
taka@ubuntu:~$

1プロセス当たり、1024ファイルまで開けることが分かります。
次にプログラム。

#include <stdio.h>

int main()
{
        int i;
        FILE* fp;

        close(0);
        close(2);

        for(i=0; i<3000; i++)
        {
                printf("file open %d\n", (i + 1));
                fp = fopen(__FILE__, "r");
                if(fp == NULL)
                {
                        puts("file open failed.");
                        break;
                }
        }
}

これを実行すると、

...
file open 1022
file open 1023
file open 1024
file open failed.

となり、1023個までファイルを開けていることになります。
もちろん、close(0); close(2);の2行をコメントアウトすると、

...
file open 1020
file open 1021
file open 1022
file open failed.

となります。