LINUX.ORG.RU

Странности stat ?


0

0

Обнаружил что системный вызов stat для файла в /proc возвращает нулевую длину файла. Проверил: stat /proc/1/cmdline
Size: 0

Это только у меня (2.4.27) ?
Мерзкая фича какая-то...

anonymous

А что здесь не нормального?
Ты еще попробуй сделать stat /dev/hda1
тоже ноль почему-то пишет ;)

Dead ★★★★
()
Ответ на: комментарий от Dead

Не нормально то что скажем в солярке все верно показывает.
Мне нужно читать /proc/`pid`/cmdline, как я буду его читать когда я длину его не знаю. Под него нужно память выделить - сколько ?

Не stat не fseek ничего не дают. Пока идея только одна сначала тупо читать по байту (таким образом узнав размер), а потом выделять память и читать в нее. Но это же изврат. Не ужели это не раализовано ?

anonymous
()
Ответ на: комментарий от anonymous

Выдели максимальную длину командной строки (не знаю сколько это). А если памяти жаль что, сделай потом str(n)dup, а оригинальную строку убей.

theSoul ★★★
()
Ответ на: комментарий от theSoul

Не не прет. Как объяснил в соседнем треде idle, максимальную длина командной строки ограницена лишь количеством памяти.
Вообщем недоделка это у /proc.
Сейчас читаю по байту пока читается и кручу счетчик размера. Потом fseek на начало, выделяем память и читаем в нее.

anonymous
()
Ответ на: комментарий от anonymous

А чё побайтно??? Читай построчно. А если будешь юзать глиб так он тебе заодно и память нужного размера выделит.

cvv ★★★★★
()
Ответ на: комментарий от cvv

Построчно ? fgets ? нужно знать количество нужной памяти либо перераспределять ее в процессе чтения - а это еще тормозней и уродливей.

>А если будешь юзать глиб так он тебе заодно и память нужного размера >выделит.
Ты о чем ?

anonymous
()
Ответ на: комментарий от anonymous

> максимальную длина командной строки ограницена лишь
> количеством памяти.

нет, количество памяти, занимаемой аргументами и env
ограничено 32 (MAX_ARG_PAGES) страницами.

Кроме того, чтение из pid/cmdline вернет максимум 4k.
см fs/proc/base.c:proc_pid_cmdline()
        if (len > PAGE_SIZE)
                len = PAGE_SIZE;

если бы stat давал бы вам размер, это все равно бы
мало помогло, "размер" этого файла может измениться
асинхронно, т.к. процесс может сделать setproctitle()

idle ★★★★★
()
Ответ на: комментарий от anonymous

Глиб - это такая либа которая призвана упростить жизнь программерам на С Так вот она содержит ф-ю аналогичную фгетс но юзающую не статический буфер а динамически выделяющую память под твою строку, Тоесть если у тебя будет строка длиной 5К то она вернёт указатель на буфер с твоей строкой теминированной \0 длиной 5К+1.

cvv ★★★★★
()
Ответ на: комментарий от cvv

>>Так вот она содержит ф-ю аналогичную фгетс но юзающую не статический >>буфер а динамически выделяющую память под твою строку

Имя, имя сестра ?

anonymous
()
Ответ на: комментарий от cvv

glib - чрезвычайно глючная библиотека с отвратительным api. Лучше использовать libslack.

anonymous
()
Ответ на: комментарий от dilmah

>кстати а mmap его случайно нельзя?
У него то-же есть параметр задающий сколько именно байт отображать.
Может конечно его можно задать 0 или -1, но в man mmap про это ничего нет.

anonymous
()
Ответ на: комментарий от idle

>>Кроме того, чтение из pid/cmdline вернет максимум 4k.
Предлагаешь просто создать массив в 4k и попытаться прочитать в него 4k ? Такое поведение где-нибудь задокументированно, не изменится завтра ?

>>если бы stat давал бы вам размер, это все равно бы
>>мало помогло, "размер" этого файла может измениться
>>асинхронно, т.к. процесс может сделать setproctitle()
man setproctitle ничего не дал :( Но в таком случае может изменится не только размер но и содержимое...

anonymous
()
Ответ на: комментарий от anonymous

> > просто создать массив в 4k и попытаться прочитать в него 4k ?
> > Такое поведение где-нибудь задокументированно, не изменится завтра ?

если даже и изменится, что с того? больше 4К read()
не вернет. в худшем случае, вы получите не неполную
информацию, но вы и так получаете ее неполной, учитывая
нынешнее ограничение на 4K.

вообще, cmdline, как и многое в /proc, носит характер
информативный, не понимаю зачем вам точно знать аргументы
процесса. тем более, как я писал, он может содержимое
этого файла изменить, просто переписав argv[0]

> Но в таком случае может изменится не только размер но и содержимое...

вот именно

idle ★★★★★
()
Ответ на: комментарий от idle

>>не понимаю зачем вам точно знать аргументы процесса.
Текущая задача: есть множество одинаковых программ с разными аргументами - предотвратить повторный запуск программ с одинаковыми аргументами.
Впринципе все уже работает. Просто хотелось бы сделать не только для данного случая а универсально.

anonymous
()
Ответ на: комментарий от anonymous

Универсально, чтобы прочитать файл неизвестного размера, можно
заюзать примерно такой код:


/* на сколько байт за раз будет увеличиваться буфер */
/* значение в примере взято от балды                */
#define INCR 4096


/* чтение файла fd от текущей позиции до EOF или ошибки */
/* на выходе:                                           */
/*  *result = считанные данные                          */
/*  *size   = размер данных в байтах                    */
/* возвращается 0 при успешном выполнении, иначе -1     */
int my_read(int fd, void **result, size_t *size)
  {
  char *buf = NULL, *new;
  size_t bufsize = 0, cnt = 0;
  int fail = 0, error;
  ssize_t rd;

  /* читаем до EOF */
  do
    {
    /* буфер расширяем при необходимости */
    if (cnt == bufsize)
      {
      new = realloc(buf, bufsize += INCR);
      if (!new)  goto err;
      buf = new;
      }

    /* пытаемся считать максимум за раз */
    rd = read(fd, buf + cnt, bufsize - cnt);

    /* либо прерывание сигналом, либо ошибка чтения */
    if (rd == -1)
      {
      if (errno == EINTR)  continue;
      err:
        fail = -1;
        break;
      }

    /* либо считано сколько-то, либо дошли до EOF (считано 0) */
    cnt += rd;
    } while (rd);

  /* отдаем лишнюю память */
  error = errno;
  new = realloc(buf, cnt);

  /* это результат работы */
  *result = new ? new : buf;
  *size = cnt;

  /* 0 == ок; -1 == ошибка, при этом errno == код ошибки */
  errno = error;
  return fail;
  }

nobody ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.