Възможно ли е да се знае дали даден процес чака в състояние на блокиране при повикване Receive() на Linux?

Основната ми цел е да изпълнявам процеси един по един в кръгов режим, докато някой извика receive() и бъде блокиран, така че изпълнението да превключи към следващия процес в опашката. Има приложение за контролер, което е кодирано в Java и изпълнява тези процеси (които също са приложения на Java) с помощта на Runtime.getRuntime().exec() и запазва върнатите стойности, които са обекти на процеса.

За да постигна тази цел, трябва да уловя повикванията receive() (или техните състояния, което е блокирано) и да ги кажа на приложението на контролера (master).

Мога да отида на толкова ниско ниво, колкото искате, ако това е възможно.. Първата ми мисъл беше да получа тази информация от драйвера и след това да я кажа на моето Java приложение на контролера. Написах мрежов модул на ядрото на Linux, който улавя операциите за изпращане и получаване, но AFAIK функцията socket.receive() не казва нищо на мрежовия драйвер.

Така че, мисля, че опциите са да получите тази информация или от JVM, по някакъв начин да я получите от линукс команда или така, или евентуално чрез модула на ядрото на линукс?

Какви са вашите предложения?


person Ozan    schedule 19.06.2009    source източник


Отговори (6)


Ако искате да знаете дали вашите нишки са блокирани или точно за какво са блокирани, можете или да направите дъмп на нишка, или да използвате инструмент като jvisualvm, за да прикачите към процеса и да разгледате (в jvisualvm ще прикачите към процеса, ще направите дъмп на нишка и след това погледнете активността на всяка нишка).

person matt b    schedule 19.06.2009
comment
Изглежда, че нишката все още е в състояние Runnable, но от проследяването на стека мога да видя извикванията accept(), receive() и т.н. Въпреки че изглежда, че това върши работа, ще трябва да изпълнявам jstack на всеки ~200 ms, за да проверя дали е блокиран или не и да анализирам изхода. (което не е много добро за производителността) Така че очевидно имам нужда от нещо като събитие- базирано решение, така че да ми сигнализира, когато е блокирано при повиквания на receive() и т.н. Това обаче е добро решение; ако не трябваше да го снимам (почти), когато се случи. - person Ozan; 21.06.2009

Гледали ли сте systemtap? Трябва да е лесно достъпен в последните системи Fedora.

Най-добрият Андерс

person anders.norgaard    schedule 19.06.2009
comment
Хм, това изглежда улавя системните извиквания на ядрото на гнездата. Което според мен е най-добрият вариант. В противен случай би било специфично за Java приложение. Не можах да го инсталирам и да го изпробвам на Ubuntu 9.04, защото се оплакваше от библиотеки за отстраняване на грешки в ядрото и т.н., а в момента нямам време да се занимавам с него. Определено ще го пробвам. Мисля, че това е най-добрият начин. Получаването на проследяване на стека и анализирането му изисква търсене на много функции на класове на сокет и т.н., които блокират по време на четене. - person Ozan; 21.06.2009

Не знам дали това ще ви помогне, но можете да получите информация за състоянието на Java нишка на вашата машина, като използвате локално прикачване.

1) Добавете tools.jar към вашия classpath и използвайте VirtualMachine.list(), за да получите списък с работещата JVM на вашата машина.

2) Прикрепете към JVM, обработен с помощта на VirtualMachine.attach(virtualMachineDescriptor)

3) Вземете адреса на локалния конектор, vm.getAgentProperties().get("com.sun.management.jmxremote.localConnectorAddress");

4) Използвайте JMXConnectorFactory.newJMXConnector(...), за да се свържете с JVM

5) От търсенето на JMX връзка нагоре ThreadMXBean

6) От ThreadMXBean получавате масив от ThreadInfos, който описва всички нишки в JVM.

7) От TheadInfo#getThreadState() можете да проверите дали състоянието е ThreadState.BLOCKED

person Kire Haglin    schedule 20.06.2009
comment
Не съм пробвал това, но използвайки JStack дава Thread.State: RUNNABLE, така че вероятно ще ми даде същото. Изглежда, че не мога да получа тази информация от състоянията на темата. - person Ozan; 21.06.2009

Трябва да използвате примитиви за междупроцесна комуникация във вашите работни процеси, за да уведомите приложението на контролера, че са готови да получават данни.

Не можете да правите предположения за това как дъщерните процеси изпълняват своето четене на сокет. Те може да използват recv, или select, или poll и т.н., за да изчакат мрежови данни.

person karunski    schedule 19.06.2009
comment
Въпреки че това със сигурност е възможно, това ще изисква промяна на кода на процесите. Друга моя цел е да бъда възможно най-независим от тези процеси, така че да работи с (почти) всеки процес. - person Ozan; 19.06.2009

Тук всъщност има няколко точки. Планировчикът на Linux е достатъчно умен, за да изпревари блокирана задача. Което означава, че ако извикате receive() и няма нищо, което чака да получи, вашата задача вероятно ще бъде поставена в режим на заспиване до момента, в който повикването ще се върне. Не е необходимо да се занимавате с планирането; Linux ядрото ще го направи вместо вас.

Въпреки това, ако трябва да знаете дали задачата ви е блокирана от някое демон приложение, ако желаете да напишете LKM, защо просто не вземете задачата в списъка със задачи, който ви интересува, и не проверите нейното състояние?

Разбира се, простото проверяване на състоянието на задачата може да не ви каже точно какво искате. Ако състоянието на вашата задача е TASK_INTERRUPTIBLE, това само ви казва, че вашата задача чака нещо, но може да не е маловажно да разберете какво е това нещо. По същия начин вашата задача може да бъде в състояние TASK_RUNNING и всъщност да не се изпълнява на процесора в текущия момент (но поне в състояние TASK_RUNNING знаете, че задачата ви не е блокирана).

person FreeMemory    schedule 19.06.2009

Можете просто да изпратите сигнал QUIT (Ctrl-\ на конзолата), за да получите дъмп на нишка.

person Ringding    schedule 09.07.2009