Как безопасно убить подчиненное ядро? - PullRequest
4 голосов
/ 08 марта 2011

LinkClose[link] "не обязательно завершает программу на другом конце связи, как сказано в документации. Есть ли способ убить процесс подчиненного ядра безопасно?

EDIT:

В действительности мне нужна функция в Mathematica , которая возвращается только тогда, когда процесс подчиненного ядра уже убит и его память уже освобождена. И LinkInterrupt[link, 1], и LinkClose[link] не ждут выхода из подчиненного ядра. На данный момент единственной такой функцией, по-видимому, является killProc[procID] функция, которую я показал в одном из ответов на этой странице. А есть встроенный аналог?

Ответы [ 2 ]

1 голос
/ 10 марта 2011

Тодд Гейли ответил на мой вопрос в группе новостей.Решение состоит в том, чтобы отправить подчиненному ядру MLTerminateMessage.Из кода верхнего уровня:

   LinkInterrupt[link, 1] (* An undocumented form that lets you pick 
the message type *)

В C:

   MLPutMessage(link, MLTerminateMessage);

В Java с использованием J / Link:

   link.terminateKernel();

В .NET с использованием .NET /Ссылка:

   link.TerminateKernel();

РЕДАКТИРОВАТЬ:

Я обнаружил, что в стандартных случаях при использовании LinkInterrupt[link, 1] моя операционная система (в настоящее время Windows 2000) освобождает физическую памятьтолько через 0,05-0,1 секунды, начиная с момента выполнения LinkInterrupt[link, 1], тогда как при LinkClose[link] она освобождает физическую память за 0,01-0,03 секунды (оба значения включают время, затраченное на выполнение самой команды).Временные интервалы были измерены с использованием SessionTime[] в равных условиях и постоянно воспроизводятся.

На самом деле мне нужна функция в Mathematica , которая возвращается только тогда, когда процесс подчиненного ядра уже завершен иего память уже выпущена.И LinkInterrupt[link, 1], и LinkClose[link] не ждут выхода из подчиненного ядра.На данный момент единственной такой функцией, по-видимому, является killProc[procID] функция, которую я показал в другом ответе на этой странице.

1 голос
/ 09 марта 2011

На данный момент мне известен только один способ безопасного уничтожения процесса MathKernel.Этот метод использует NETLink и, похоже, работает только под Windows и требует установки Microsoft .NET 2 или более поздней версии.

killProc[processID_] := If[$OperatingSystem === "Windows",
   Needs["NETLink`"];
   Symbol["LoadNETType"]["System.Diagnostics.Process"];
   With[{procID = processID},
    killProc[procID_] := (
       proc = Process`GetProcessById[procID];
       proc@Kill[]
       );
    ];
   killProc[processID]
   ];
(*Killing the current MathKernel process*)
killProc[$ProcessID]

Любые предложения или улучшения будут оценены.

Более правильный метод:

Needs["NETLink`"];
LoadNETType["System.Diagnostics.Process"];

$kern = LinkLaunch[First[$CommandLine] <> " -mathlink -noinit"];
LinkRead[$kern];
LinkWrite[$kern, Unevaluated[$ProcessID]];
$kernProcessID = First@LinkRead[$kern];
$kernProcess = Process`GetProcessById[$kernProcessID];

AbortProtect[If[! ($kernProcess@Refresh[]; $kernProcess@HasExited),
  $kernProcess@Kill[]; $kernProcess@WaitForExit[];
  $kernProcess@Close[]];
 LinkClose[$kern]]

Редактировать 2:

Еще более правильный метод:

Needs["NETLink`"];
LoadNETType["System.Diagnostics.Process"];

$kern = LinkLaunch[First[$CommandLine] <> " -mathlink -noinit"];
LinkRead[$kern];
LinkWrite[$kern, Unevaluated[$ProcessID]];
$kernProcessID = First@LinkRead[$kern];
$kernProcess = Process`GetProcessById[$kernProcessID];

krnKill := AbortProtect[
   If[TrueQ[MemberQ[Links[], $kern]], LinkClose[$kern]];
   If[TrueQ[MemberQ[LoadedNETObjects[], $kernProcess]],
    If[! TrueQ[$kernProcess@WaitForExit[100]],
     Quiet@$kernProcess@Kill[]; $kernProcess@WaitForExit[]];
    $kernProcess@Close[]; ReleaseNETObject[$kernProcess];
    ]
   ];
...