Как увеличить лимит «максимально открытых файлов» в C на Mac OS X - PullRequest
6 голосов
/ 02 июля 2010

Максимальное количество открытых файлов в Mac OS X по умолчанию - 256 (ulimit -n), и моему приложению требуется около 400 обработчиков файлов.

Я пытался изменить лимит с помощью setrlimit (), но даже если функция выполняется правильно, я все равно ограничен 256.

Вот тестовая программа, которую я использую:

#include <stdio.h>
#include <sys/resource.h>

main()
{
  struct rlimit rlp;

  FILE *fp[10000];
  int i;

  getrlimit(RLIMIT_NOFILE, &rlp);
  printf("before %d %d\n", rlp.rlim_cur, rlp.rlim_max);

  rlp.rlim_cur = 10000;
  setrlimit(RLIMIT_NOFILE, &rlp);

  getrlimit(RLIMIT_NOFILE, &rlp);
  printf("after %d %d\n", rlp.rlim_cur, rlp.rlim_max);

  for(i=0;i<10000;i++) {
    fp[i] = fopen("a.out", "r");
    if(fp[i]==0) { printf("failed after %d\n", i); break; }
  }

}

и вывод:

before 256 -1
after 10000 -1
failed after 253

Я не могу просить людей, которые используют мое приложение, тыкать в файл / etc или что-то в этом роде. Мне нужно приложение, чтобы сделать это самостоятельно.

Ответы [ 6 ]

5 голосов
/ 09 июля 2010

etresoft нашел ответ на доске объявлений apple :

Вся проблема здесь ваша функция printf (). Когда вы звоните printf (), вы инициализируете внутренние структуры данных до определенного размер. Затем вы вызываете setrlimit () для попробуйте отрегулировать эти размеры. Тот функция не работает, потому что у вас есть уже использовал эти внутренние структуры с вашим printf (). если ты использовать две структуры rlimit (одна для до и один за), а не распечатайте их, пока не позвоните setrlimit, вы найдете, что вы можете изменить пределы тока обрабатывать даже в командной строке программа. Максимальное значение 10240.

5 голосов
/ 03 июля 2010

rlp.rlim_cur = 10000;

Две вещи.

1-й.ЛОЛ.Очевидно, вы нашли ошибку в Mac OS X 'stdio.Если я исправлю вашу программу, добавлю обработку ошибок и т. Д., А также заменю fopen () на системный вызов open (), я могу легко достичь предела 10000 (что на 240 фд ниже моего 10.6.3 'ограничения OPEN_MAX 10240)

второй.RTFM: man setrlimit.Случай с максимальным количеством открытых файлов должен быть обработан специально для OPEN_MAX.

2 голосов
/ 18 августа 2014

По какой-то причине (возможно, двоичная совместимость), вы должны определить _DARWIN_UNLIMITED_STREAMS перед включением <stdio.h>:

#define _DARWIN_UNLIMITED_STREAMS

#include <stdio.h>
#include <sys/resource.h>

main()
{
  struct rlimit rlp;

  FILE *fp[10000];
  int i;

  getrlimit(RLIMIT_NOFILE, &rlp);
  printf("before %d %d\n", rlp.rlim_cur, rlp.rlim_max);

  rlp.rlim_cur = 10000;
  setrlimit(RLIMIT_NOFILE, &rlp);

  getrlimit(RLIMIT_NOFILE, &rlp);
  printf("after %d %d\n", rlp.rlim_cur, rlp.rlim_max);

  for(i=0;i<10000;i++) {
    fp[i] = fopen("a.out", "r");
    if(fp[i]==0) { printf("failed after %d\n", i); break; }
  }

}

отпечатков

before 256 -1
after 10000 -1
failed after 9997

Эта функция, кажется, былапредставлен в Mac OS X 10.6.

2 голосов
/ 03 июля 2010

Это может быть жестким ограничением вашего libc. Некоторые версии solaris имеют аналогичное ограничение, поскольку они хранят fd как unsigned char в структуре FILE. Если это касается и вашего libc, вы, возможно, не сможете делать то, что хотите.

Насколько я знаю, такие вещи, как setrlimit, влияют только на то, сколько файлов вы можете открыть с помощью open (fopen почти наверняка реализован в терминах open). Поэтому, если это ограничение находится на уровне libc, вам понадобится альтернативное решение.

Конечно, вы всегда можете не использовать fopen и вместо этого использовать системный вызов open, доступный практически для каждого варианта unix.

Недостатком является то, что вы должны использовать write и read вместо fwrite и fread, которые не выполняют такие функции, как буферизация (это все делается в вашей libc, а не самой ОС) , Так что это может стать узким местом в производительности.

Можете ли вы описать сценарий, который требует 400 файлов, открытых ** одновременно **? Я не говорю, что нет такого случая, когда это необходимо. Но если вы опишите ваш вариант использования более четко, то, возможно, мы можем порекомендовать лучшее решение.

0 голосов
/ 17 января 2017

Mac OS не позволяет нам легко изменять лимит, как во многих операционных системах на основе Unix. Мы должны создать два файла

/ Library / LaunchDaemons / limit.maxfiles.plist /Library/LaunchDaemons/limit.maxproc.plist описывающий максимальный процесс и максимальный лимит файла. Владелец файла необходимо изменить на «root: wheel»

Это само по себе не решает проблему, по умолчанию последняя версия Mac OSX использует 'csrutil', мы должны отключить его. Чтобы отключить его, нам нужно перезагрузить Mac в режиме восстановления и оттуда отключить csrutil с помощью терминала.

Теперь мы можем легко изменить максимальный предел дескриптора открытого файла из самого терминала (даже в обычном режиме загрузки).

Этот метод подробно объясняется в следующей ссылке. http://blog.dekstroza.io/ulimit-shenanigans-on-osx-el-capitan/

работает для OSX-elcapitan и OSX-Seirra.

0 голосов
/ 02 июля 2010

Я знаю, это звучит глупо, но вам действительно нужно одновременно открыть 400 файлов?Кстати, вы запускаете этот код как root?

...