Это зависит от того, что Вы подразумеваете под системным вызовом. Вы имеете в виду вызов библиотеки C (через glibc) или фактический системный вызов? Вызовы библиотеки C всегда заканчивают тем, что использовали системные вызовы в конце.
старый способ сделать системные вызовы был посредством программного прерывания, т.е. int
инструкция. Windows имел int 0x2e
, в то время как Linux имел int 0x80
. ОС настраивает обработчика прерываний для 0x2e или 0x80 в Таблице дескрипторов прерываний (IDT). Этот обработчик затем выполняет системный вызов. Это копирует аргументы от непривилегированного режима до привилегированного режима (этим управляет определенная для ОС конвенция). На Linux аргументы передаются с помощью ebx
, ecx
, edx
, esi
, и edi
. В Windows аргументы копируются со стека. Обработчик затем выполняет своего рода поиск (для нахождения адреса функции) и выполняет системный вызов. После того, как системный вызов завершается, iret
, инструкция возвращается к непривилегированному режиму.
новый путь sysenter
и sysexit
. Эти две инструкции в основном делают весь регистр работает на Вас. ОС настраивает инструкции через Образцовые Определенные Регистры (MSRs). После этого это - практически то же как использование int
.
Есть комментарий к social.msdn - хотя я не смог найти ничего подобного в документации:
Дескриптор TabControl должен быть создан для метода Insert для работы
Попробуйте использовать указанный код
IntPtr h = this.tabControl1.Handle;
, прежде чем переключаться между службами
Вы передаете тот же индекс методу Insert ()
. Если вы хотите просто увеличить, это должно сработать:
// ...
int i = 0;
foreach (MyServiceConfigElement service in obj.Services)
CreateServiceControl(service, i++);
// ...
private void CreateServiceControl(MyServiceConfigElement service, int i)
{
TabPage tp = new TabPage(service.Name);
tabControl1.TabPages.Insert(i, tp);
// ...
}