{"id":858,"date":"2017-03-18T15:10:04","date_gmt":"2017-03-18T18:10:04","guid":{"rendered":"http:\/\/thesqltimes.com\/blog\/?p=858"},"modified":"2017-03-20T10:31:58","modified_gmt":"2017-03-20T13:31:58","slug":"kernel-mode-vs-user-mode","status":"publish","type":"post","link":"https:\/\/thesqltimes.com\/blog\/2017\/03\/18\/kernel-mode-vs-user-mode\/","title":{"rendered":"Kernel Mode vs User Mode"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"Muito \u00fatil!\" data-post-id=\"858\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Tempo de Leitura:<\/span> <span class=\"rt-time\"> 6<\/span> <span class=\"rt-label rt-postfix\">minutos<\/span><\/span><p style=\"text-align: justify;\">Aprofundar o conhecimento em um software, requer entender muitas caracter\u00edsticas do sistema operacional. No caso de SO&#8217;s como o Windows,\u00a0\u00e9 comum, em cursos avan\u00e7ados ouvir as express\u00f5es &#8220;Kernel Mode&#8221; e &#8220;User Mode&#8221;. Com o intuito de fazer um <del>r\u00e1pido<\/del> esclarecimento sobre o que significam estes nomes, eu preparei este post.<\/p>\n<p style=\"text-align: justify;\">Certas \u00e1reas de mem\u00f3ria cont\u00e9m dados vitais para o correto funcionamento do Windows. Por exemplo,\u00a0imagine que no endere\u00e7o \u00a00xFFFF0000, o Windows guardasse\u00a0a quantidade total de mem\u00f3ria livre para aloca\u00e7\u00e3o. Ora, se uma thread qualquer \u00a0altera esse valor,\u00a0o Windows poderia achar que havia mais ou menos mem\u00f3ria dispon\u00edvel para aloca\u00e7\u00e3o. Isso traria instabilidade e incosist\u00eancia para todo o sistema operacional, e, consequentemente, todos os processos em execu\u00e7\u00e3o.<\/p>\n<p style=\"text-align: justify;\">Para se prevenir deste tipo de caso, e outros, o Windows fornece privil\u00e9gios que permitem ou impedem que uma thread acesse um determinado recurso, como certos endere\u00e7os de mem\u00f3ria. Na verdade, isso \u00e9 poss\u00edvel gra\u00e7as ao processador: Nos primeiros momentos do boot, ele est\u00e1 livre e sem restri\u00e7\u00f5es, ent\u00e3o o sistema operacional interage com ele e registra uma s\u00e9rie de\u00a0rotinas e c\u00f3digos necess\u00e1rios para serem executados quando certos eventos ocorrem durante as execu\u00e7\u00f5es das instru\u00e7\u00f5es.\u00a0Alguns destes eventos s\u00e3o disparados justamente quando uma thread necessita acessar algum recurso protegido. Diante disso, o processador ir\u00e1 executar o c\u00f3digo que o sistema operacional registrou e o mesmo ir\u00e1 tratar de forma adequada o acesso. No exemplo acima, ao acessar o endere\u00e7o de mem\u00f3ria cr\u00edtico, o Windows ir\u00e1\u00a0impedir a a\u00e7\u00e3o de ser executada e gerar um erro para a thread que tentou fazer o acesso.<\/p>\n<p style=\"text-align: justify;\">Mas n\u00e3o \u00e9 todo momento que uma thread deve ser impedida de acessar recursos cr\u00edticos. Por exemplo, ao realizar um leitura de arquivo, a thread necessita chamar a fun\u00e7\u00e3o &#8220;ReadFile&#8221;, da API do Windows. Essa fun\u00e7\u00e3o vai executar um c\u00f3digo que requer o acesso a estruturas protegidas pelo sistema operacional. Neste caso, se houver o impedimento por parte do sistema operacinal, a thread n\u00e3o ir\u00e1 conseguir efetuar a leitura do arquivo.<\/p>\n<p style=\"text-align: justify;\">Para resolver isso, o Windows define dois modos de opera\u00e7\u00e3o das threads:<\/p>\n<ul>\n<li style=\"text-align: justify;\">User Mode<br \/>\nO User Mode\u00a0\u00e9 o modo de opera\u00e7\u00e3o em\u00a0que as threads executam na maior parte do tempo. Neste modo, a <em>thread<\/em> n\u00e3o pode acessar recursos vitais para o funcionamento do sistema, como certos endere\u00e7os de mem\u00f3ria e registradores. Para acessar, \u00e9 necess\u00e1rio entrar no &#8220;Kernel Mode&#8221;.<\/li>\n<li style=\"text-align: justify;\">Kernel Mode<br \/>\nEste \u00e9 o modo sob o qual as threads que executam o c\u00f3digo do sistema operam, j\u00e1 que o mesmo referencia\u00a0estruturas internas para completar os servi\u00e7os oferecidos. A API do Windows cont\u00e9m fun\u00e7\u00f5es que executam instru\u00e7\u00f5es que fazem com que o sistema entre neste modo. Um leitor curioso, pode ent\u00e3o, concluir que seria f\u00e1cil burlar as prote\u00e7\u00f5es do Kernel Mode, bastando apenas executar esta instru\u00e7\u00f5es que ativam o Kernel Mode. Bom, n\u00e3o \u00e9 bem assim.<\/li>\n<\/ul>\n<h3 style=\"text-align: justify;\">Transi\u00e7\u00e3o User Mode &#8211; Kernel\u00a0Mode<\/h3>\n<p style=\"text-align: justify;\">Quando a thread executa a instru\u00e7\u00e3o que faz o modo de opera\u00e7\u00e3o mudar para Kernel Mode, o processador interrompe a execu\u00e7\u00e3o da mesma e passa o controle para umas dessas rotinas que o Windows registrou l\u00e1 no boot. Isso significa, que gra\u00e7as ao suporte que o processador oferece, a thread passa a rodar um c\u00f3digo confi\u00e1vel pelo Windows, isto \u00e9, que faz parte do kernel.\u00a0Dessa maneira, ela\u00a0deixa de executar o seu c\u00f3digo original, e passa a executar um c\u00f3digo espec\u00edfico para tratar este evento gerado pelo processador. O nome da instru\u00e7\u00e3o que solicita essa transi\u00e7\u00e3o depende da arquitetura e fam\u00edlia do processador. No caso de processadores Intel x64, o nome da instru\u00e7\u00e3o \u00e9 syscall (Fonte:\u00a0<a href=\"https:\/\/software.intel.com\/sites\/default\/files\/managed\/39\/c5\/325462-sdm-vol-1-2abcd-3abcd.pdf\">Intel\u00ae 64 and IA-32 Architectures<\/a>, P\u00e1gina 1788). Esse processo tambem \u00e9 conhecido como &#8220;uso dos servi\u00e7os do sistema operacional&#8221;, pois \u00e9 assim que um processo consegue interagir com as centenas\u00a0de rotinas (os chamados &#8220;servi\u00e7os&#8221;) que prov\u00ea alguma funcionalidade do Windows (como ler arquivos, criar processos, transferir dados via rede, etc.).<\/p>\n<p style=\"text-align: justify;\">Mesmo que o usu\u00e1rio\u00a0utilizasse a instru\u00e7\u00e3o syscall em seu c\u00f3digo diretamente, o c\u00f3digo do sistema tomaria o controle da execu\u00e7\u00e3o e impediria o usu\u00e1rio de realizar qualquer modifica\u00e7\u00e3o que n\u00e3o fosse por parte de um c\u00f3digo criado pelos desenvolvedores do Windows.<\/p>\n<p style=\"text-align: justify;\">\u00c9 comum observar nas literaturas a respeito da arquitetura do Windows, o fato de que a API do Windows possui\u00a0uma parte User Mode e uma parte Kernel Mode. Utilizar a instru\u00e7\u00e3o syscall diretamente seria chato e complexo para os desenvolvedores. Ao realizar a transi\u00e7\u00e3o para Kernel Mode, \u00e9 necess\u00e1rio informar uma s\u00e9rie de par\u00e2metros (via registradores da CPU), que o c\u00f3digo do Windows ir\u00e1 validar para determinar\u00a0o que dever\u00e1 ser feito a partir dali. Ao inv\u00e9s do desenvolvedor ter que decorar as centenas de c\u00f3digos que s\u00e3o definidos, o Windows disponibiliza uma s\u00e9rie de fun\u00e7\u00f5es em DLLs como &#8220;kernel32.dll&#8221; e &#8220;user32.dll&#8221;. Essa fun\u00e7\u00f5es s\u00e3o respons\u00e1veis por preparar os par\u00e2metros e executar a instru\u00e7\u00e3o &#8220;syscall&#8221;. \u00a0Ent\u00e3o, por isso, at\u00e9 que a instru\u00e7\u00e3o &#8220;syscall&#8221; seja executada, o c\u00f3digo da DLL que faz parte do Windows, ainda estava rodando em User Mode, isto \u00e9, se houvesse uma tentativa de acessar um recurso protegido nesse momento, haveria uma falha (o que seria um bug no sistema operacional, j\u00e1 que a DLL faz parte do Windows). Por exemplo, a fun\u00e7\u00e3o ReadFile \u00e9 definida na DLL &#8220;Kernel32.dll&#8221; (Fonte:\u00a0<a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa365467%28v=vs.85%29.aspx\">https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa365467%28v=vs.85%29.aspx<\/a>). Essa \u00e9 a fun\u00e7\u00e3o que deve ser usada sempre que um processo necessita ler um arquivo (ou uma de suas varia\u00e7\u00f5es, como ReadFileEx). O SQL Server faz uso dessa fun\u00e7\u00e3o para ler o conte\u00fado dos arquivos de dados e log. Ao iniciar a sua execu\u00e7\u00e3o, a fun\u00e7\u00e3o ir\u00e1 realizar todas as valida\u00e7\u00f5es necess\u00e1rias e ir\u00e1 executar outras fun\u00e7\u00f5es que est\u00e3o defindias em outras DLLs do Windows. E s\u00e3o essas fun\u00e7\u00f5es que ir\u00e3o preparar e executar a instru\u00e7\u00e3o syscall.<\/p>\n<h3 style=\"text-align: justify;\">Transi\u00e7\u00e3o Kernel\u00a0Mode &#8211; User Mode<\/h3>\n<p style=\"text-align: justify;\">Depois que o c\u00f3digo do sistema operacional termina seu trabalho, \u00e9 necess\u00e1rio retomar a execu\u00e7\u00e3o do c\u00f3digo original, isto \u00e9, o codigo que causou a transi\u00e7\u00e3o para Kernel Mode. Mas antes, \u00e9 necess\u00e1rio voltar ao User Mode, caso contr\u00e1rio, toda o esquema de prote\u00e7\u00e3o feito at\u00e9 aqui seria in\u00fatil. \u00a0Assim como existem instru\u00e7\u00f5es para entrar em Kernel Mode, existem para sair. De novo, o nome vai depender da fam\u00edlia e arquitetura do processador. No caso de x64 , a instru\u00e7\u00e3o \u00e9 a sysret ( Fonte:\u00a0<a href=\"https:\/\/software.intel.com\/sites\/default\/files\/managed\/39\/c5\/325462-sdm-vol-1-2abcd-3abcd.pdf\">Intel\u00ae 64 and IA-32 Architectures<\/a>, P\u00e1gina 1796 \u00a0). Quando o c\u00f3digo do sistema operacional termina de fazer o que lhe foi solicitado, ent\u00e3o ele executa a instru\u00e7\u00e3o sysret, saindo do Kernel Mode e retomando a execu\u00e7\u00e3o do c\u00f3digo ap\u00f3s o syscall que causou a transi\u00e7\u00e3o para Kernel Mode.<\/p>\n<h3 style=\"text-align: justify;\">Mais alguns coment\u00e1rios&#8230;<\/h3>\n<p>&nbsp;<\/p>\n<p>Antes de encerrar, \u00e9 importante fortalecer alguns pontos.<\/p>\n<ol>\n<li>Tudo isso foi um resumo do resumo da resenha do rascunho do que \u00e9 realmente o Kernel Mode e o User Mode, e como ocorre toda essas transi\u00e7\u00f5es. Se voc\u00ea quer se aprofundar no assunto, pode usar a refer\u00eancia que deixei no final do artigo (e, se ainda n\u00e3o o fez, aproveita para estudar\u00a0C++ e Assembly, pois vai facilitar o entendimento de muita coisa).<\/li>\n<li>User Mode e Kernel Mode n\u00e3o s\u00e3o threads ou processos diferentes. Uma thread pode em um determinado momento estar em User Mode, e um outro determinado momento em Kernel Mode. O que muda \u00e9 que em Kernel Mode ela estara executando um c\u00f3digo do sistema operacional ou driver. Isso indica que se a thread passa muito tempo em Kernel Mode, \u00e9 uma grande chance de ser um problema de hardware, uso intenso de recursos do SO ou bug do sistema (este \u00faltimo com chances bem menores, mas n\u00e3o imposs\u00edvel).\n<figure id=\"attachment_892\" aria-describedby=\"caption-attachment-892\" style=\"width: 825px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-892\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ThreadUKModeTransition.png\" alt=\"\" width=\"825\" height=\"547\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ThreadUKModeTransition.png 825w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ThreadUKModeTransition-300x199.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ThreadUKModeTransition-768x509.png 768w\" sizes=\"auto, (max-width: 825px) 100vw, 825px\" \/><figcaption id=\"caption-attachment-892\" class=\"wp-caption-text\">Vida da thread e modos de opera\u00e7\u00e3o<\/figcaption><\/figure><\/li>\n<li>Algumas ferramentas, como o gerenciador de tarefas e o Process Explorer, permite que voc\u00ea monitore o uso de CPU em Kernel Mode. Por exemplo, voc\u00ea consegue determinar quanto de tempo foi gasto pelas threads executando em Kernel Mode.\n<figure id=\"attachment_894\" aria-describedby=\"caption-attachment-894\" style=\"width: 793px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-894\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ProcExpKernelTimeExample.png\" alt=\"\" width=\"793\" height=\"699\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ProcExpKernelTimeExample.png 793w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ProcExpKernelTimeExample-300x264.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2017\/03\/ProcExpKernelTimeExample-768x677.png 768w\" sizes=\"auto, (max-width: 793px) 100vw, 793px\" \/><figcaption id=\"caption-attachment-894\" class=\"wp-caption-text\">O gr\u00e1fico em vermelho mostra o tempo gasto pela CPU executando instru\u00e7\u00f5es sob o modo Kernel Mode. Tamb\u00e9m, \u00e9 possivel obter informa\u00e7\u00f5es por processo. Na imagem, \u00e9 poss\u00edvel observar o texto &#8220;Kernel Time&#8221; na janela da direita. Esta informa\u00e7\u00e3o indica o tempo total gasto em Kernel Mode pelo processo. O mesmo vale pro &#8220;User Time&#8221;.<\/figcaption><\/figure><\/li>\n<li>O que tudo isso tem a ver com SQL Server? N\u00e3o somente com SQL Server, mas com qualquer software que rode no Windows. Todos eles fazem uso constante de servi\u00e7os do sistema. Assim, entender o que \u00e9 o Kernel Mode \u00e9 \u00fatil para determinar se um poss\u00edvel problema est\u00e1 no sistema operacional ou no software. A transi\u00e7\u00e3o para Kernel Mode \u00e9 algo muito custoso do ponto de vista de um processo. Envolve a execu\u00e7\u00e3o de mais algumas centenas instru\u00e7\u00f5es, acesso a mem\u00f3ria, recursos compartilhados, etc. O SQL Server foi desenvolvido para evitar ao m\u00e1ximo fazer transi\u00e7\u00f5es de User Mode para Kernel Mode, para salvar a perfomance. \u00c9 obvio que existem casos onde n\u00e3o \u00e9 possivel evitar isso, como no momento em que \u00e9 necess\u00e1rio ler ou escrever dos arquivos. Mas \u00e9 sempre bom estar de olho nas m\u00e9tricas relativo ao uso dos recursos em Kernel Mode.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\"><strong>Refer\u00eancias:<\/strong><\/p>\n<ul>\n<li style=\"text-align: justify;\">System Service Dispatching<br \/>\nWindows Internals, 6ed, Part 1, Cap\u00edtulo\u00a03 &#8211; System Mechanisms, P\u00e1g 132<\/li>\n<li style=\"text-align: justify;\">Intel\u00ae 64 and IA-32 Architectures Software Developer\u2019s Manual<br \/>\n<a href=\"https:\/\/software.intel.com\/sites\/default\/files\/managed\/39\/c5\/325462-sdm-vol-1-2abcd-3abcd.pdf\">https:\/\/software.intel.com\/sites\/default\/files\/managed\/39\/c5\/325462-sdm-vol-1-2abcd-3abcd.pdf<\/a><\/li>\n<li style=\"text-align: justify;\">ReadFileEx<br \/>\n<a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa365468%28v=vs.85%29.aspx\">https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa365468%28v=vs.85%29.aspx<\/a><\/li>\n<li style=\"text-align: justify;\">Windows API<br \/>\n<a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ff818516(v=vs.85).aspx\">https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ff818516(v=vs.85).aspx<\/a><\/li>\n<li style=\"text-align: justify;\">User Mode and Kernel Mode<br \/>\n<a href=\"https:\/\/msdn.microsoft.com\/en-us\/windows\/hardware\/drivers\/gettingstarted\/user-mode-and-kernel-mode\">https:\/\/msdn.microsoft.com\/en-us\/windows\/hardware\/drivers\/gettingstarted\/user-mode-and-kernel-mode<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aprofundar o conhecimento em um software, requer entender muitas caracter\u00edsticas do sistema operacional. No caso de SO&#8217;s como o Windows,\u00a0\u00e9 comum, em cursos avan\u00e7ados ouvir as express\u00f5es &#8220;Kernel Mode&#8221; e &#8220;User Mode&#8221;. Com o intuito de fazer um r\u00e1pido esclarecimento sobre o que significam estes nomes, eu preparei este post. Certas \u00e1reas de mem\u00f3ria cont\u00e9m&hellip;&nbsp;<a href=\"https:\/\/thesqltimes.com\/blog\/2017\/03\/18\/kernel-mode-vs-user-mode\/\" rel=\"bookmark\"><span class=\"screen-reader-text\">Kernel Mode vs User Mode<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":895,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[9,7,93],"tags":[199,206,202,203,205,204,200,87,207,201],"series":[],"class_list":["post-858","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-arquitetura","category-sql-server","category-windows","tag-kernel-mode","tag-process-explorer","tag-syscall","tag-sysenter","tag-sysexit","tag-sysret","tag-user-mode","tag-windows","tag-windows-api","tag-x64"],"_links":{"self":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/858","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/comments?post=858"}],"version-history":[{"count":12,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/858\/revisions"}],"predecessor-version":[{"id":898,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/858\/revisions\/898"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media\/895"}],"wp:attachment":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media?parent=858"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/categories?post=858"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/tags?post=858"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/series?post=858"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}