LINUX.ORG.RU

select/poll и fdopen с open'ом...


0

0

Уважаемые, обращаюсь к Вам за советом.

1) select/poll

Есть директория (к примеру dir), в которую асинхронно пользователем
сваливаются файлы, а программа должна отслеживать изменения в
структуре каталога и узнавать имена вновь прибывших файлов.
Естественно, что нам необходим или select или poll. Вопрос в том как
правильно написать этот код.

Моя попытка:

int d, fd;
struct pollfd cdp[1];

d = open(dir, O_RDONLY, S_IRUSR);
cdp[0].fd = d;
cdp[0].events = POLLRDNORM;
while(1) {
  fd = poll(cdp, 1, -1);
  if (fd == -1 || (cdp[0].revents & (POLLERR|POLLHUP|POLLNVAL))) {
    /* ERROR */
  }
  else if (fd == 0) {
    /* ERROR */
  }
  else {
    if (read(d, buf, sizeof(buf)) == -1) {
       /* ERROR */
    }
    else {
       /* в buf хочу получить имя файла (ну или структурку какую) */
  }
}

Дык вот этот код как умолишенный начинает работать. В buf пишется
один символ (^F). Это вероятно ошибка. Как нужно переделать?


2) fdopen и open

Вопрос второй. open умеет разделять права доступа к файлу на owner,
owner group и other. fdopen не умеет. Как с помощь fdopen получить
FILE* на открытый дескриптор:

  fd = open(file, O_CREAT | O_EXCL, S_IRWXU);
?

fdopen(fd, "w") не работает (возвращает 0x0 (NULL)).
anonymous

> Естественно, что нам необходим или select или poll

не поможет. поможет fcntl(fd, F_NOTIFY, DN_...)

> fd = open(file, O_CREAT | O_EXCL, S_IRWXU)

S_IRWXU означает, с какими правами создать файл

> fdopen(fd, "w") не работает (возвращает 0x0 (NULL))

потому, что в fd нельзя писать. fdopen() не меняет и не
переоткрывает файл, а просто "присоединяет" к нему буфер
для оптимизации i/o.

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

>> Естественно, что нам необходим или select или poll
>
> не поможет. поможет fcntl(fd, F_NOTIFY, DN_...)

Ok. Посмотрим....

>> fd = open(file, O_CREAT | O_EXCL, S_IRWXU)
>
> S_IRWXU означает, с какими правами создать файл

Угу. Сдесь 700, но можно и (S_IRUSR|S_IWRUSR), т.е. 600.

>> fdopen(fd, "w") не работает (возвращает 0x0 (NULL))
>
> потому, что в fd нельзя писать. fdopen() не меняет и не
> переоткрывает файл, а просто "присоединяет" к нему буфер
> для оптимизации i/o.

Почему в fd нельзя писать? Режим доступа ведь 700 (600).
А про "присоединение" я знаю. Но как тогда делать?

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

>>> fdopen(fd, "w") не работает (возвращает 0x0 (NULL))
>>
>> потому, что в fd нельзя писать. fdopen() не меняет и не
>> переоткрывает файл, а просто "присоединяет" к нему буфер
>> для оптимизации i/o.
>
> Почему в fd нельзя писать? Режим доступа ведь 700 (600).
> А про "присоединение" я знаю. Но как тогда делать?

Млин... я понял. Ваша правда.



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

>> не поможет. поможет fcntl(fd, F_NOTIFY, DN_...)
>
> Ok. Посмотрим....

Не, не поможет. F_NOTIFY есть не везде... В Linux есть (причем только
в 2.4+), в OpenBSD нет. А мне нужно, что бы было переносимо.

Есть еще идеи какие-нибудь?.... А че select'ом никак?

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

>> Не, не поможет. F_NOTIFY есть не везде...
>
> да, это непереносимо
>
>> А че select'ом никак?
>
> увы

Не уж то такая проблема не имеет решения.... Весьма странно.

anonymous
()

Портируемый способ: Каждую секунду перечитывать содержимое каталога и сравнивать с предыдущим.

Криво зато портируемо

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

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

Я и хотел это делать с alarm и таймаутом. Но таймаут в 1 секунду будет черезчур грузить процессор.

Буду делать так:

#ifdef __OpenBSD__ || __NetBSD__ || __FreeBSD__
  /* kqueue/kevent */
#else
  /* fcntl(..., F_NOTIFY,...) */
#endif

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

>Я и хотел это делать с alarm и таймаутом. Но таймаут в 1 секунду будет черезчур грузить процессор.

Здесь ты немного ошибаешся. Linux при соответствующей настройке будет тормозить только в течение первого считывания содержимого каталога, после чего он его прокеширует и будет работать достаточно шустро.

А вообще основная нагрузка падает не на проц а на ввод/вывод.

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

>> Я и хотел это делать с alarm и таймаутом. Но таймаут в 1 секунду
>> будет черезчур грузить процессор.
>
> Здесь ты немного ошибаешся. Linux при соответствующей настройке будет
> тормозить только в течение первого считывания содержимого каталога,
> после чего он его прокеширует и будет работать достаточно шустро.
>

Нет не ошибаюсь. Вы же не знаете, что я буду делать по достижении таймаута.
А делать я буду BF_cbc_encrypt(), посему каждую секунду не канает ;)

> А вообще основная нагрузка падает не на проц а на ввод/вывод.
>

Согласен.

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