Что именно происходит во время «переходного периода от управляемого к родному»? - PullRequest
20 голосов
/ 09 февраля 2012

Я понимаю, что в некоторых случаях CLR необходимо выполнить маршалинг, но скажем, у меня есть:

using System.Runtime.InteropServices;
using System.Security;

[SuppressUnmanagedCodeSecurity]
static class Program
{
    [DllImport("kernel32.dll", SetLastError = false)]
    static extern int GetVersion();

    static void Main()
    {
        for (; ; )
            GetVersion();
    }
}

Когда я врываюсь в эту программу с помощью отладчика, я всегда вижу:

Учитывая, что маршалинг не требуется (верно?), Может кто-нибудь объяснить, что на самом деле происходит в этом "переходе к нативному",а зачем это надо?

Ответы [ 5 ]

10 голосов
/ 09 февраля 2012

Сначала необходимо настроить стек вызовов, чтобы происходил STDCALL. Это соглашение о вызовах для Win32.

Затем среда выполнения выдвигает так называемый фрейм выполнения. Существует много различных типов фреймов: подтверждения безопасности, защищенные области GC, вызовы собственного кода, ...

Среда выполнения использует такой кадр для отслеживания того, что в настоящий момент выполняется собственный код. Это имеет значение для потенциально одновременной сборки мусора и, возможно, других вещей. Это также помогает отладчику.

Так что на самом деле здесь мало что происходит. Это довольно тонкий путь кода.

3 голосов
/ 27 марта 2013

Я понимаю, что на этот вопрос ответили, но я удивлен, что никто не предложил вам показать внешний код в окне отладки.Если вы щелкнете правой кнопкой мыши по строке [Native to Managed Transition] и отметите опцию Show External Code, вы увидите, какие именно методы .NET вызываются при переходе.Это может дать вам лучшую идею.Вот пример:

Displaying a Native to Managed Transition

2 голосов
/ 09 февраля 2012

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

Необходимо проверить контекст безопасности, чтобы убедиться, что вызывающему коду разрешен доступ к нативным методам.Текущий кадр управляемого стека необходимо сохранить, чтобы среда выполнения могла выполнять обход стека для таких вещей, как отладка и обработка исключений (не говоря уже о собственном коде, который вызывает управляемый обратный вызов).Внутренние биты состояния должны быть установлены, чтобы указать, что мы в настоящее время выполняем собственный код.

Кроме того, регистры, возможно, должны быть сохранены, в зависимости от того, что необходимо отслеживать и которые гарантированно будут восстановленыСоглашение о вызовах.Корни GC, которые находятся в регистрах (локальных), возможно, нужно каким-то образом пометить, чтобы они не собирали мусор во время нативного метода.

Так что в основном это обработка стека и маршалинг типов, с некоторыми мерами безопасностидобавлено. Хотя это не огромное количество вещей, оно будет представлять значительный барьер против вызова меньших собственных методов.Например, попытка P / Invoke в оптимизированную математическую библиотеку редко приводит к выигрышу в производительности, поскольку накладных расходов достаточно, чтобы свести на нет любое из потенциальных преимуществ.Некоторые результаты профилирования производительности обсуждаются здесь .

1 голос
/ 09 февраля 2012

Я действительно не вижу много, что было бы необходимо сделать. Я подозреваю, что это в основном информативно, чтобы показать вам, что часть вашего стека вызовов показывает собственные функции, а также чтобы указать, что IDE и отладчик могут вести себя по-разному во время этого перехода (так как управляемый код обрабатывается в отладчике очень по-разному, и некоторые функции, которые вы ожидаете, могут не работать)

Но я полагаю, вы сможете выяснить это, просто проверив разборку вокруг перехода. Посмотри, не делает ли это что-нибудь необычное.

0 голосов
/ 09 февраля 2012

Так как вы звоните в DLL.это должно выйти из управляемой среды.Это входит в ядро ​​Windows.Вы преодолеваете барьер .net и входите в код Windows, который не работает так же, как .NET.

...