LINUX.ORG.RU

Можно ли с select() отслеживать, что в файле появились новые данные?


0

2

Всем привет,

Что-то торможу я в понедельник с простым вопросом. Проблемка примерно следующая: udev при подключении/отключении какого-либо устройства добавляет в /tmp/device файл строку, например, «+ mmc» или "- mmc". Хочу в моей программе получать инфу, в момент, когда новая запись добавляется в файл. И хотел сделать это с select(). Написал примитивную программку (см ниже). Так вот прикол в том, что select() всегда возвращается и read() читает 0 данных из файла. Что я делаю не так? Может select() не годится для слеженуя за нормальными файлами? select() мне был бы интересен, поскольку есть еще в программе netlink-соцкет, который я зацепил на select(), хотелось бы еще и эту часть связать с select()

Всем заранее спасибо

int m_fd = open( «/tmp/device», O_CREAT | O_RDONLY | O_SYNC );

while(1)
{
fd_set rfds;
char buffer[10000];
int rd;

FD_ZERO( &rfds );
FD_SET( m_fd, &rfds );

pselect( m_fd+ 1, &rfds, NULL, NULL, NULL, NULL );

if( FD_ISSET(m_fd, &rfds) )
{
rd=read( m_fd, buffer, sizeof(buffer) );
}
usleep(5000000);
}


Ответ на: комментарий от velikS

Не, он, вроде только «provides a mechanism for monitoring file system events». Т.е. одновременно отслеживать с select(), что по сокету приняты новые данные не получается. Пришлось бы или отдельный thread запускать (очень не хочется) или друг за другом сокет и файл проверять. Тогда время реакции суммируется (опять же не есть супергуд)

velikS
() автор топика

>Хочу в моей программе получать инфу, в момент, когда новая запись добавляется в файл. И хотел сделать это с select()

Use Inotify, Luke. Оно для того и создано, в общем-то

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

>Т.е. одновременно отслеживать с select(), что по сокету приняты новые данные не получается.

inotify даёт тебе дополнительный файловый указатель, делая select() на который, ты получаешь уведомления от ФС. Если у тебя есть ещё и сокет, ты можешь их обоих просматривать одним селектом

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

s/файловый указатель/файловый дескриптор/

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

Ок, спасибо за пинок в нужном направлении. Уже разбираюсь

velikS
() автор топика

Есть еще вариант задействовать ту информацию, которую с радостью отдает сам udev, а не пытатся все это читать из файла. Хотя, может быть я не вполне ясно представляю ваши задачи.

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


Да задача более, чем простая - подключили SD-Card - надо подмонтировать, сбросить логи на карточку; подключили USB-LAN adapter - fзапустить DHCP клиент, если адрес не нашел, выставить статический и попытаться связаться с компом; если подключили USB-Serial адаптер, то попробовать связаться с внещним устройством по ttyUSB0; есть еще вариант, когда подключается UMTS модем.

Вот собсна в двух словах об этой подзадаче. Работает это всё в embedded устройстве. udev мне не совсем нравится, т.к. время загрузки увеличивает на 1 сек, но остановился пока на нeм. Ну и вот был вопрос об том, как из udev получить инфу о подключаемых/отключаемых устройствах (см. http://www.linux.org.ru/forum/general/6125597), я остановился на варианте, что udev сбрасывает название подключаемого/отключаемого устройства в файл, а файл проверяю по select(). Если есть вариант, как вытащить инфу из udev попроще, был бы благодарен за идеи.

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

А добавить его туда нет возможности? На самом деле это бы значительно упростило задачу. Я так понимаю, что вы используетет Qt в своей системе? (посмотрел в предидущих тердах). Я решал точно такую же задачу и как раз на Qt+embedded.

Вот кусок кода из конструктора:

//получаем контекст для udev
	this->m_context = udev_new();
	//создаем контекст мониора, котоырй будет отслеживать события udev (не kernel)
	this->m_monitor = udev_monitor_new_from_netlink(this->m_context, "udev");

	//подключаем наш монитор для получения сообщений
	udev_monitor_enable_receiving(this->m_monitor);
	//получаем сокет для чтения событий монитора
	this->monitorNotifier = new QSocketNotifier(
		udev_monitor_get_fd(this->m_monitor),
		QSocketNotifier::Read,
		this);
	//подключаемся к сигналу сокета - готов работать
	connect(this->monitorNotifier, SIGNAL(activated(int)),
		this, SLOT(udevDataAvailable()));

Как только вы получили такой сигнал - udev_device* device = udev_monitor_receive_device(this->m_monitor);

Ну а дальше курим маны по удев вот тут: http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/

Этого удовольстия я не буду вас лишать. Там все очень просто и понятно. Если будут вопросы - пишите.

Ну а если libudev никак добавить нельзя, тогда действительно придется городить костыли.

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

В этой программе Qt нету. В этой программе я даже запретил себе делать threads. С Qt вы упростили задачу, которую я сделал через select(). Но сама соль как раз в libudev. Я собирал rottfs с Buildroot. Как я посмотрю, Buildroot предлагает udev, но не libudev. Меня это немного настораживает. А как вы получили libudev в rootfs? Собирали руками или как еще?

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

Мы работаем на основе Angstrem, поэтому просто доставили пакет в систему. К сожалению самой rootfs занимается мой коллега, поэтому всех тонкостей я не знаю. Но как я понял, там просто идет пакет с libudev и все.
Если не использовать Qt, тогда можно использовать inotify, как сказали выше. Ну или select, как у тебя.

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

Ок, спасибо. libudev у меня нету и собирать его как-то стрёмно. Останусь со своей идеей - udev пишет из своего rules-файла, что моё устройство подключилось/отключилось и т.д.

Если не использовать Qt, тогда можно использовать inotify, как сказали выше. Ну или select, как у тебя.

Не, не, коллега. Вы тут немного не поняли. ИЛИ не работает, надо с И иметь дело: с inotify получаю file descriptor на мой файл, в который пишет udev И по select() смотрю, когда файл изменился. По этому же селекту будет обрабатываться сокет приёма. Как-то так

Еще раз спасибо за идеи

velikS
() автор топика
Ответ на: комментарий от fghj

Файл можно открыть параллельно любым редактором, в файле стоит

+ eth1
- eth1
+ eth1
- eth1
+ mmcblk0p1
+ ttyUSB0
+ eth1

и я точно знаю что подключалось в системе. и правильно ли она обработала запросы. Так проще квалифицировать

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

Решается без inotify. К примеру флаг -f у tail присутствовал когда inotify небыло даже в мыслях.

Решение на C прям сейчас с пивом не вспомню, Но точь в точь такая же задача на tcl делается обычным fileevent и никаких лишних дескрипторов там нет.

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

Решается без inotify. К примеру флаг -f у tail присутствовал когда inotify небыло даже в мыслях.

До inotify был dnotify. freebsd'шный tail использует kqueue

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