Как безопасно убить подчиненное ядро?

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

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

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

2 ответа

Решение

На данный момент я знаю только один способ убить 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];
    ]
   ];

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

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

В С:

   MLPutMessage(link, MLTerminateMessage);

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

   link.terminateKernel();

В.NET с помощью.NET/Link:

   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] Функция, которую я показал в другом ответе на этой странице.

Другие вопросы по тегам