139920579 Versao Traduzida de Book

238
Versão traduzida de book.pdf Handbook FreeBSD Developers ' *Page 1* *Page 1* *FreeBSD Developers' Handbook* *Handbook FreeBSD Developers '* *The FreeBSD Documentation Project* *O Projeto de Documentação do FreeBSD* ------------------------------------------------------------------------ *Page 2* *Page 2* *FreeBSD Developers' Handbook* *Handbook FreeBSD Developers '* by The FreeBSD Documentation Project pelo Projeto de Documentação do FreeBSD Published August 2000 Publicada agosto 2000 Copyright © 2000, 2001 by The FreeBSD Documentation Project Copyright © 2000, 2001 por O Projeto de Documentação do FreeBSD Welcome to the Developers' Handbook. Bem-vindo ao Manual dos Desenvolvedores. This manual is a /work in progress/ and is the work of many individuals. Este manual é um /trabalho em andamento/ e é o trabalho de muitos indivíduos. Many sections do not yet exist and some of those that do exist need to be updated. Muitas seções ainda não existem e algumas das que existem precisam ser atualizadas. If you are interested in helping Se você estiver interessado em ajudar with this project, send email to the FreeBSD documentation project mailing list < com este projeto, envie um email para o FreeBSD documentação do projeto lista de discussão < [email protected] [email protected] >. >. The latest version of this document is always available from the FreeBSD World Wide Web server A versão mais recente deste documento está sempre disponível a partir do servidor Web FreeBSD World Wide (http://www.FreeBSD.org/). (Http://www.FreeBSD.org/). It may also be downloaded in a variety of formats and compression options from the Também pode ser baixado em uma variedade de formatos e opções de compressão a partir da FreeBSD FTP server (ftp://ftp.FreeBSD.org/pub/FreeBSD/doc) or one of the numerous mirror sites FreeBSD servidor FTP (ftp://ftp.FreeBSD.org/pub/FreeBSD/doc) ou um dos numerosos sites espelhos (http://www.freebsd.org/handbook/mirrors-ftp.html). (Http://www.freebsd.org/handbook/mirrors-ftp.html). Redistribution and use in source (SGML DocBook) and 'compiled' forms (SGML, HTML, PDF, PostScript, RTF and so forth) with or without A redistribuição e utilização do código fonte (SGML DocBook) ou formato 'compilado' (SGML, HTML, PDF, PostScript, RTF e assim por diante) com ou sem modification, are permitted provided that the following conditions are met: modificação, são permitidas desde que as seguintes condições sejam atendidas: 1. 1. Redistributions of source code (SGML DocBook) must retain the above copyright notice, this list of conditions As redistribuições do código fonte (SGML DocBook) devem reter o aviso de copyright acima, esta lista de condições and the following disclaimer as the first lines of this file unmodified. eo aviso a seguir nas primeiras linhas deste arquivo não modificadas. 2. 2. Redistributions in compiled form (transformed to other DTDs, converted to PDF, PostScript, RTF and other As redistribuições em forma compilada (transformada para outros DTDs, convertida para PDF, PostScript, RTF e outros

Transcript of 139920579 Versao Traduzida de Book

Page 1: 139920579 Versao Traduzida de Book

Versão traduzida de book.pdf

Handbook FreeBSD Developers '*Page 1* *Page 1*

*FreeBSD Developers' Handbook* *Handbook FreeBSD Developers '**The FreeBSD Documentation Project* *O Projeto de Documentação do FreeBSD*------------------------------------------------------------------------*Page 2* *Page 2*

*FreeBSD Developers' Handbook* *Handbook FreeBSD Developers '*by The FreeBSD Documentation Project pelo Projeto de Documentação doFreeBSDPublished August 2000 Publicada agosto 2000Copyright © 2000, 2001 by The FreeBSD Documentation Project Copyright ©2000, 2001 por O Projeto de Documentação do FreeBSDWelcome to the Developers' Handbook. Bem-vindo ao Manual dosDesenvolvedores. This manual is a /work in progress/ and is the work ofmany individuals. Este manual é um /trabalho em andamento/ e é otrabalho de muitos indivíduos.Many sections do not yet exist and some of those that do exist need tobe updated. Muitas seções ainda não existem e algumas das que existemprecisam ser atualizadas. If you are interested in helping Se vocêestiver interessado em ajudarwith this project, send email to the FreeBSD documentation projectmailing list < com este projeto, envie um email para o FreeBSDdocumentação do projeto lista de discussão <[email protected] [email protected]>. >.The latest version of this document is always available from the FreeBSDWorld Wide Web server A versão mais recente deste documento está sempredisponível a partir do servidor Web FreeBSD World Wide(http://www.FreeBSD.org/). (Http://www.FreeBSD.org/). It may also bedownloaded in a variety of formats and compression options from theTambém pode ser baixado em uma variedade de formatos e opções decompressão a partir daFreeBSD FTP server (ftp://ftp.FreeBSD.org/pub/FreeBSD/doc) or one of thenumerous mirror sites FreeBSD servidor FTP(ftp://ftp.FreeBSD.org/pub/FreeBSD/doc) ou um dos numerosos sites espelhos(http://www.freebsd.org/handbook/mirrors-ftp.html).(Http://www.freebsd.org/handbook/mirrors-ftp.html).Redistribution and use in source (SGML DocBook) and 'compiled' forms(SGML, HTML, PDF, PostScript, RTF and so forth) with or without Aredistribuição e utilização do código fonte (SGML DocBook) ou formato'compilado' (SGML, HTML, PDF, PostScript, RTF e assim por diante) com ousemmodification, are permitted provided that the following conditions aremet: modificação, são permitidas desde que as seguintes condições sejamatendidas:1. 1. Redistributions of source code (SGML DocBook) must retain theabove copyright notice, this list of conditions As redistribuições docódigo fonte (SGML DocBook) devem reter o aviso de copyright acima, estalista de condiçõesand the following disclaimer as the first lines of this file unmodified.eo aviso a seguir nas primeiras linhas deste arquivo não modificadas.2. 2. Redistributions in compiled form (transformed to other DTDs,converted to PDF, PostScript, RTF and other As redistribuições em formacompilada (transformada para outros DTDs, convertida para PDF,PostScript, RTF e outros

Page 2: 139920579 Versao Traduzida de Book

formats) must reproduce the above copyright notice, this list ofconditions and the following disclaimer in the formatos) devemreproduzir o aviso de copyright acima, esta lista de condições easeguinte isenção de responsabilidade nadocumentation and/or other materials provided with the distribution.documentação e / ou outros materiais fornecidos com a distribuição.*Important:* THIS DOCUMENTATION IS PROVIDED BY THE FREEBSD DOCUMENTATIONPROJECT "AS IS" *Importante:* O DOCUMENTAÇÃO É OFERECIDO PELO PROJETO DEDOCUMENTAÇÃO DO FREEBSD "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE IMPLIED E QUALQUER GARANTIA EXPRESSA OU implícita, incluindo, masnão limitado a, GARANTIASWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. GARANTIAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UM PROPÓSITOESPECÍFICO. IN INNO EVENT SHALL THE FREEBSD DOCUMENTATION PROJECT BE LIABLE FOR ANYDIRECT, INDIRECT, NO CASO DO PROJETO DE DOCUMENTAÇÃO DO FREEBSD SERRESPONSÁVEL POR QUAISQUER DANOS DIRETOS,INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUTNOT LIMITED , ESPECIAIS, EXEMPLARES OU EMERGENTES incidental (INCLUINDO,SEM LIMITAÇÃOTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, ORPROFITS; OR À AQUISIÇÃO DE BENS OU SERVIÇOS, PERDA DE USO, DADOS OULUCROS OUBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN INTERRUPÇÃO DE NEGÓCIOS) CAUSADOS E EM QUALQUER TEORIA DERESPONSABILIDADE, SEJA EMCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY CONTRATO, RESPONSABILIDADE OBJETIVA OU DELITO (INCLUINDONEGLIGÊNCIA OU NÃO) DECORRENTE DE QUALQUERWAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH FORMA DE USO DA DOCUMENTAÇÃO, MESMO QUE AVISADO DAPOSSIBILIDADE DE TAISDAMAGE. DANO.------------------------------------------------------------------------*Page 3* *Página 3*

*Table of Contents* *Índice analítico**I. Introduction* <#7> *I. Introdução* <#7>1. <#8> 1. <#8> Developing on <#8> Desenvolvendo em <#8>2. <#9> 2. <#9> The BSD Vision <#9> A visão BSD <#9>3. <#10> 3. <#10> Architectural Overview <#10> Visão geral daarquitetura <#10>4. <#11> 4. <#11> The Layout of /usr/src <#11> O layout do arquivo / usr/ src <#11>*II.* <#12> *II.* <#12>5. <#13> 5. <#13> Programming <#13> Programação <#13>5.1. <#13> 5.1. <#13>5.2. <#13> 5.2. <#13>5.3. <#13> 5.3. <#13> Introduction to Programming <#13> Introdução àProgramação <#13>5.4. <#16> 5.4. <#16> Compiling with <#16> Compilando com <#16>cc <#16> cc <#16>5.5. <#24> 5.5. <#24> Make <#24> Fazer <#24>5.6. <#29> 5.6. <#29>5.7. <#33> 5.7. <#33> Using Emacs as a DevelopmentEnvironment................. <#33>...................................................................25Usando Emacs como um ambiente de desenvolvimento ................. <#33>........................... ........................................ 25

Page 3: 139920579 Versao Traduzida de Book

5.8. <#44> 5.8. <#44> Further Reading <#44> Leitura <#44>6. <#46> 6. <#46> Secure <#46> Proteger <#46>6.1. <#46> 6.1. <#46>6.2. <#46> 6.2. <#46> Secure Design <#46> Projeto seguro <#46>6.3. <#46> 6.3. <#46> Buffer Overflows <#46> Buffer overflows <#46>6.4. <#49> 6.4. <#49> SetUID <#49> SetUID <#49>6.5. <#49> 6.5. <#49> Limiting your program's <#49> Limitar o seuprograma de <#49>6.6. <#51> 6.6. <#51>6.7. <#51> 6.7. <#51> Race <#51> Corrida <#51>*III.* <#52> *III.* <#52> *Kernel* <#52> *Núcleo* <#52>7. <#53> 7. <#53> History of the Unix <#53> História do Unix <#53>8. <#54> 8. <#54> Locking Notes <#54> Bloqueio Notas <#54>8.1. <#54> 8.1. <#54>8.2. <#57> 8.2. <#57> Lock Manager <#57> Lock Manager <#57>8.3. <#57> 8.3. <#57> Atomically Protected Variables <#57> Variáveis ��atomicamente Protegidas <#57>*IV.* <#58> *IV.* <#58> *Memory* <#58> *Memória* <#58>9. <#59> 9. <#59> Virtual Memory System <#59> Sistema de Memória Virtual<#59>9.1. <#59> 9.1. <#59> The FreeBSD VM <#59> O FreeBSD VM <#59>10. <#63> 10. <#63>10.1. <#63> 10.1. <#63> DMA: What it is and How it Works ...............<#63>..................................................................................55DMA: O que é e como funciona ............... <#63>............................................................................ ...... 55*V. I/O* <#76> *V. I / O* <#76>11. <#77> 11. <#77>/3/ /3/------------------------------------------------------------------------*Page 4* *Page 4*

*VI.* <#78> *VI.* <#78> *Interprocess Communication* <#78> *Comunicaçãoentre* <#78>12. <#79> 12. <#79>*VII.* <#80> *VII.* <#80> *Networking* <#80> *Networking* <#80>13. <#81> 13. <#81> Sockets <#81> Sockets <#81>14. <#82> 14. <#82> IPv6 Internals <#82> Internals IPv6 <#82>14.1. <#82> 14.1. <#82> IPv6/IPsec <#82> IPv6/IPsec <#82>*VIII.* <#103> *VIII.* <#103> *Network* <#103> *Rede* <#103>15. <#104> 15. <#104>*IX.* <#105> *IX.* <#105> *Terminal Handling* <#105> *Terminal Handling*<#105>16. <#106> 16. <#106>*X.* <#107> *X.* <#107>17. <#108> 17. <#108>*XI.* <#109> *XI.* <#109> *Device* <#109> *Dispositivo* <#109>18. <#110> 18. <#110> Writing FreeBSD Device <#110> Escrevendodispositivo FreeBSD <#110>18.1. <#110> 18.1. <#110>18.2. <#110> 18.2. <#110> Dynamic Kernel Linker Facility -KLD................ <#110>..........................................................................102Dinâmica Kernel Linker Facility - KLD ................ <#110>.......................................................................... 10218.3. <#112> 18.3. <#112> Accessing a device driver <#112> Acessando um

Page 4: 139920579 Versao Traduzida de Book

driver de dispositivo <#112>18.4. <#112> 18.4. <#112> Character <#112> Caráter <#112>18.5. <#116> 18.5. <#116> Network <#116> Rede <#116>19. <#118> 19. <#118> ISA device drivers <#118> Drivers de dispositivosISA <#118>19.1. <#118> 19.1. <#118>19.2. <#118> 19.2. <#118> Basic <#118> Básico <#118>19.3. <#120> 19.3. <#120> Device_t <#120> Device_t <#120>19.4. <#121> 19,4. <#121> Config file and the order of identifying andprobing during auto-configuration........ <#121> ....................113Arquivo de configuração ea ordem de identificar e investigar durante aconfiguração automática ........ <#121> .................... 11319.5. <#123> 19.5. <#123>19.6. <#126> 19.6. <#126> Bus memory <#126> Memória Bus <#126>19.7. <#134> 19.7. <#134>19.8. <#136> 19.8. <#136>19.9. <#143> 19.9. <#143> xxx_isa_attach <#143> xxx_isa_attach <#143>19.10. <#147> 19.10. <#147> xxx_isa_detach <#147> xxx_isa_detach <#147>19.11. <#148> 19.11. <#148> xxx_isa_shutdown <#148> xxx_isa_shutdown <#148>20. <#150> 20. <#150> PCI <#150> PCI <#150>20.1. <#150> 20.1. <#150> Probe and <#150> Sonda e <#150>20.2. <#154> 20,2. <#154> Bus <#154> Ônibus <#154>21. <#158> 21. <#158> Common Access Method SCSI <#158> Common AccessMethod SCSI <#158>21.1. <#158> 21.1. <#158>21.2. <#158> 21.2. <#158> General <#158> Geral <#158>21.3. <#179> 21.3. <#179>/4/ /4/------------------------------------------------------------------------*Page 5* *Page 5*

21.4. <#180> 21.4. <#180> Asynchronous Events <#180> Eventos assíncronos<#180>21.5. <#181> 21.5. <#181>21.6. <#188> 21,6. <#188> Errors <#188> Erros <#188>21.7. <#189> 21,7. <#189> Timeout <#189> Timeout <#189>22. <#191> 22. <#191> USB Devices <#191> Dispositivos USB <#191>22.1. <#191> 22.1. <#191>22.2. <#192> 22.2. <#192> Host <#192> Hospedeiro <#192>22.3. <#194> 22.3. <#194> USB Device Information <#194> Informaçõessobre o dispositivo USB <#194>22.4. <#196> 22,4. <#196> Device probe and <#196> Sonda dispositivo e<#196>22.5. <#197> 22.5. <#197> USB Drivers Protocol <#197> USB DriversProtocolo <#197>23. <#200> 23. <#200> NewBus <#200> NewBus <#200>*XII.* <#201> *XII.* <#201> *Architectures* <#201> *Arquiteturas* <#201>24. <#202> 24. <#202> x86 Assembly Language <#202> x86 LinguagemAssembly <#202>24.1. <#202> 24.1. <#202>24.2. <#202> 24.2. <#202> The Tools <#202> As ferramentas <#202>24.3. <#203> 24.3. <#203> System Calls <#203> Chamadas do sistema <#203>24.4. <#205> 24,4. <#205> Return <#205> Voltar <#205>24.5. <#207> 24.5. <#207> Creating Portable <#207> Criação Portátil <#207>24.6. <#212> 24,6. <#212> Our First <#212> Nosso primeiro <#212>24.7. <#214> 24,7. <#214> Writing Unix <#214> Escrevendo Unix <#214>24.8. <#217> 24,8. <#217> Buffered Input and <#217> Entrada e tamponado<#217>24.9. <#224> 24.9. <#224> Command-line <#224> De linha de comando <#224>24.10. <#229> 24.10. <#229> Unix <#229> Unix <#229>

Page 5: 139920579 Versao Traduzida de Book

24.11. <#235> 24.11. <#235> Working with <#235> Trabalhando com <#235>24.12. <#247> 24.12. <#247>24.13. <#249> 24,13. <#249>25. <#250> 25. <#250>26. <#251> 26. <#251> IA-64 <#251> IA-64 <#251>*XIII.* <#252> *XIII.* <#252>27. <#253> 27. <#253> Truss <#253> Treliça <#253>*XIV.* <#254> *XIV.* <#254> *Compatibility* <#254> *Compatibilidade* <#254>28. <#255> 28. <#255> Linux <#255> Linux <#255>*XV.* <#256> *XV.* <#256>/5/ /5/------------------------------------------------------------------------*Page 6* *Page 6*

*List of Tables* *Lista de Tabelas*8-1. <#55> 8-1. <#55> Mutex <#55> Mutex <#55>8-2. <#57> 8-2. <#57> lockmgr(9) Lock <#57> lockmgr (9) Trava <#57>*List of Examples* *Lista de Exemplos*5-1. <#36> 5-1. <#36> A sample <#36> Uma amostra <#36>.emacs <#36> . Emacs <#36>/1/ /1/------------------------------------------------------------------------*Page 7* *Página 7*

*I. Introduction* *I. Introdução*------------------------------------------------------------------------*Page 8* *Page 8*

*Chapter 1.* *Capítulo 1.* *Developing on FreeBSD* *Desenvolver no FreeBSD*This will need to discuss FreeBSD as a development platform, the visionof BSD, architectural overview, layout of Isto terá de discutir FreeBSDcomo uma plataforma de desenvolvimento, a visão do BSD, visão geral daarquitetura, layout/usr/src, history, etc. / Usr / src, história, etcThank you for considering FreeBSD as your development platform! Obrigadopor considerar FreeBSD como sua plataforma de desenvolvimento! We hopeit will not let you down. Esperamos que ele não vai deixar você para baixo./1/ /1/------------------------------------------------------------------------*Page 9* *Page 9*

*Chapter 2.* *Capítulo 2.* *The BSD Vision* *A visão BSD*/1/ /1/------------------------------------------------------------------------*Page 10* *Page 10*

*Chapter 3.* *Capítulo 3.* *Architectural Overview* *Visão geral daarquitetura*/2/ /2/------------------------------------------------------------------------*Page 11* *Page 11*

*Chapter 4.* *Capítulo 4.* *The Layout of /usr/src* *O layout do arquivo/ usr / src*The complete source code to FreeBSD is available from our public CVSrepository. O código-fonte completo para o FreeBSD está disponível nonosso repositório CVS público. The source code is normally Ocódigo-fonte é normalmenteinstalled in instalado/usr/src / Usr / src

Page 6: 139920579 Versao Traduzida de Book

which contains the following subdirectories. que contém os seguintessubdirectórios.*Directory* *Diretório**Description* *Descrição*bin/ bin /Source for files in Fonte para arquivos em/bin / Bincontrib/ contrib /Source for files from contributed software. Fonte para arquivos desoftware contribuído.crypto/ crypto /DES source DES fonteetc/ etc /Source for files in Fonte para arquivos em/etc / Etcgames/ jogos /Source for files in Fonte para arquivos em/usr/games / Usr / gamesgnu/ gnu /Utilities covered by the GNU Public License Utilities abrangidos pelaLicença Pública GNUinclude/ include /Source for files in Fonte para arquivos em/usr/include / Usr / includekerberosIV/ kerberosIV /Source for Kerbereros version IV Fonte para Kerbereros versão IVkerberos5/ Kerberos5 /Source for Kerbereros version 5 Fonte para Kerbereros versão 5lib/ lib /Source for files in Fonte para arquivos em/usr/lib / Usr / liblibexec/ libexec /Source for files in Fonte para arquivos em/usr/libexec / Usr / libexecrelease/ release /Files required to produce a FreeBSD release Arquivos necessários paraproduzir uma versão do FreeBSDsbin/ sbin /Source for files in Fonte para arquivos em/sbin / Sbinsecure/ garantir /FreeSec sources Fontes FreeSecshare/ share /Source for files in Fonte para arquivos em/sbin / Sbinsys/ sys /Kernel source files Arquivos-fonte do kerneltools/ ferramentas /Tools used for maintenance and testing of FreeBSD Ferramentas utilizadaspara manutenção e testes de FreeBSDusr.bin/ usr.bin /Source for files in Fonte para arquivos em/usr/bin / Usr / binusr.sbin/ usr.sbin /Source for files in Fonte para arquivos em/usr/sbin / Usr / sbin/3/ /3/------------------------------------------------------------------------*Page 12* *Page 12*

Page 7: 139920579 Versao Traduzida de Book

*II.* *II.* *Basics* *Basics*------------------------------------------------------------------------*Page 13* *Page 13*

*Chapter 5.* *Capítulo 5.* *Programming Tools* *Ferramentas de Programação*/This chapter was written by James Raynard </ /Este capítulo foi escritopor James Raynard <//[email protected]/ /[email protected]//>./ />./ /Modifications for the Developers'/ /Modificações para osdesenvolvedores "//Handbook by Murray Stokely </ /Handbook por Murray Stokely <//[email protected]/ /[email protected]//>./ />./*5.1.* *5.1.* *Synopsis* *Sinopse*This document is an introduction to using some of the programming toolssupplied with FreeBSD, although much of Este documento é uma introduçãoao uso de alguma das ferramentas de programação fornecidas com oFreeBSD, embora grande parteit will be applicable to many other versions of Unix. ela será aplicávela muitas outras versões do Unix. It does /not/ attempt to describecoding in any detail. Ele /não/ tenta descrever a codificação em nenhumdetalhe. Most of the A maior parte dodocument assumes little or no previous programming knowledge, althoughit is hoped that most programmers will documento pressupõe oconhecimento de programação anterior pouca ou nenhuma, embora espera-seque a maioria dos programadoresfind something of value in it encontrar algo de valor nele*5.2.* *5.2.* *Introduction* *Introdução*FreeBSD offers an excellent development environment. FreeBSD oferece umambiente de desenvolvimento excelente. Compilers for C, C++, and Fortranand an assembler come Compiladores para C, C + + e Fortran e um montadorvirwith the basic system, not to mention a Perl interpreter and classicUnix tools such as com o sistema básico, para não mencionar uminterpretador Perl e ferramentas Unix clássicos comosed sedand eawk awk. . If that is not Se não for esseenough, there are many more compilers and interpreters in the Portscollection. suficiente, há muitas mais compiladores e intérpretes dacoleção Portas. FreeBSD is very compatible with FreeBSD é muitocompatível comstandards such as POSIX and ANSI C, as well with its own BSD heritage,so it is possible to write applications that padrões como POSIX e ANSIC, bem com a sua própria herança BSD, por isso é possível escreveraplicações quewill compile and run with little or no modification on a wide range ofplatforms. irá compilar e executar com pouca ou nenhuma modificação emuma ampla gama de plataformas.However, all this power can be rather overwhelming at first if you'venever written programs on a Unix platform No entanto, todo este poderpode ser um pouco esmagadora na primeira, se você nunca programasescritos em uma plataforma Unixbefore. antes. This document aims to help you get up and running,without getting too deeply into more advanced topics. Este documento temcomo objetivo ajudá-lo a se levantar e correr, sem entrar muitoprofundamente em tópicos mais avançados.The intention is that this document should give you enough of the basicsto be able to make some sense of the A intenção é que este documento

Page 8: 139920579 Versao Traduzida de Book

deve dar-lhe o suficiente dos princípios básicos para ser capaz de fazeralgum sentido dadocumentation. documentação.Most of the document requires little or no knowledge of programming,although it does assume a basic competence A maior parte do documentorequer pouco ou nenhum conhecimento de programação, embora isto assumeuma competência básicawith using Unix and a willingness to learn! com o uso de Unix e umavontade de aprender!*5.3.* *5.3.* *Introduction to Programming* *Introdução à Programação*A program is a set of instructions that tell the computer to do variousthings; sometimes the instruction it has to Um programa é um conjunto deinstruções que dizem ao computador para fazer várias coisas, às vezes ainstrução que tem paraperform depends on what happened when it performed a previousinstruction. realizar depende do que aconteceu quando ele executou umainstrução anterior. This section gives an overview of the Esta seçãoapresenta uma visão geral dotwo main ways in which you can give these instructions, or “commands” asthey are usually called. duas principais maneiras em que você pode darestas instruções, ou "comandos", como são normalmente chamados. One wayuses an Um modo usa uma/interpreter/ , the other a /compiler/ . /intérprete,/ o outro um/compilador./ As human languages are too difficult for a computer tounderstand in an Como as línguas humanas são muito difíceis para umcomputador para entender em umunambiguous way, commands are usually written in one or other languagesspecially designed for the purpose. forma inequívoca, os comandos sãogeralmente escritos em um ou outros idiomas, especialmente concebidospara o efeito./5/ /5/------------------------------------------------------------------------*Page 14* *Page 14*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*5.3.1.* *5.3.1.* *Interpreters* *Intérpretes*With an interpreter, the language comes as an environment, where youtype in commands at a prompt and the Com um intérprete, a linguagemsurge como um ambiente, onde você digita comandos em um prompt eoenvironment executes them for you. ambiente executa-los para você. Formore complicated programs, you can type the commands into a file and getPara programas mais complicados, você pode digitar os comandos em umarquivo e obterthe interpreter to load the file and execute the commands in it. ointérprete para carregar o arquivo e execute os comandos nele. Ifanything goes wrong, many interpreters will drop Se algo der errado,muitos intérpretes vai cairyou into a debugger to help you track down the problem. lo em umdepurador para ajudá-lo a rastrear o problema.The advantage of this is that you can see the results of your commandsimmediately, and mistakes can be corrected A vantagem disto é que vocêpode ver os resultados de seus comandos imediatamente, e os erros podemser corrigidosreadily. prontamente. The biggest disadvantage comes when you want toshare your programs with someone. A maior desvantagem é quando você quercompartilhar seus programas com alguém. They must have the Eles devem ter asame interpreter, or you must have some way of giving it to them, andthey need to understand how to use it. mesmo intérprete, ou você deveter alguma maneira de dar a eles, e eles precisam entender como usá-lo.Also Também

Page 9: 139920579 Versao Traduzida de Book

users may not appreciate being thrown into a debugger if they press thewrong key! os usuários não podem apreciar a ser jogado em um depurador,se pressione a tecla errada! From a performance point of De um ponto dedesempenhoview, interpreters can use up a lot of memory, and generally do notgenerate code as efficiently as compilers. ver, os intérpretes podemusar uma grande quantidade de memória, e geralmente não geram código deforma tão eficiente como compiladores.In my opinion, interpreted languages are the best way to start if youhave not done any programming before. Na minha opinião, linguagensinterpretadas são a melhor maneira para começar, se você não tiver feitoqualquer tipo de programação antes. This Estekind of environment is typically found with languages like Lisp,Smalltalk, Perl and Basic. tipo de ambiente é tipicamente encontrado comlinguagens como Lisp, Smalltalk, Perl e Basic. It could also be arguedTambém poderia ser argumentadothat the Unix shell ( que o shell Unix (sh sh, ,csh csh) is itself an interpreter, and many people do in fact write shell“scripts” to help with ) É por si só um intérprete, e muitas pessoasque, de facto, escrever shell "scripts" para ajudar comvarious “housekeeping” tasks on their machine. várias tarefas"domésticas" em sua máquina. Indeed, part of the original Unixphilosophy was to provide lots of De fato, parte da filosofia Unixoriginal era fornecer lotes desmall utility programs that could be linked together in shell scripts toperform useful tasks. pequenos programas utilitários que podem serligados entre si em shell scripts para realizar tarefas úteis.*5.3.2.* *5.3.2.* *Interpreters available with FreeBSD* *Intérpretesdisponíveis com FreeBSD*Here is a list of interpreters that are available as FreeBSD packages(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/), Aqui está uma lista deintérpretes que estão disponíveis como pacotes do FreeBSD(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/)with a brief discussion of some of the more popular interpretedlanguages. com uma breve discussão de algumas das linguagensinterpretadas mais populares.To get one of these packages, all you need to do is to click on thehotlink for the package, then run Para ganhar um destes pacotes, tudoque você precisa fazer é clicar sobre o link direto para o pacote, emseguida, execute# #*pkg_add /package name/* */nome do pacote/ pkg_add*as root. como root. Obviously, you will need to have a fully functionalFreeBSD 2.1.0 or later system for the package to work! Obviamente, vocêvai precisar ter um FreeBSD totalmente funcional 2.1.0 ou posterior dosistema para o pacote para o trabalho!BASIC BASICShort for Beginner's All-purpose Symbolic Instruction Code. Curto para oAll-purpose Symbolic Instruction Código novato. Developed in the 1950sfor teaching University Desenvolvido na década de 1950 para aUniversidade de ensinostudents to program and provided with every self-respecting personalcomputer in the 1980s, BASIC has been estudantes para o programa e desdeque com todos os computadores pessoais se preze na década de 1980, BASICfoithe first programming language for many programmers. a primeiralinguagem de programação para muitos programadores. It's also the

Page 10: 139920579 Versao Traduzida de Book

foundation for Visual Basic. É também a base para o Visual Basic.The Bywater Basic Interpreter(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/bwbasic-2.10.tgz) andthe The Interpreter Básico Bywater(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/bwbasic-2.10.tgz) eoPhil Cockroft's Basic Interpreter(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/pbasic-2.0.tgz)(formerly Intérprete Básico de Phil Cockcroft(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/pbasic-2.0.tgz)(anteriormenteRabbit Basic) are available as FreeBSD FreeBSD packages(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/) Coelho Basic) estãodisponíveis como pacotes do FreeBSD FreeBSD(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/)/6/ /6/------------------------------------------------------------------------*Page 15* *Page 15*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/Lisp CicioA language that was developed in the late 1950s as an alternative to the“number-crunching” languages that A linguagem que foi desenvolvida nadécada de 1950 como uma alternativa para as línguas "número" que esmagawere popular at the time. eram populares na época. Instead of beingbased on numbers, Lisp is based on lists; in fact the name is short forEm vez de se basear em números, Lisp é baseada em listas, na verdade onome é uma abreviação de“List Processing”. "Processamento List". Very popular in AI (ArtificialIntelligence) circles. Muito popular na IA (Inteligência Artificial)círculos.Lisp is an extremely powerful and sophisticated language, but can berather large and unwieldy. Lisp é uma linguagem extremamente poderosa esofisticada, mas pode ser bastante grande e pesado.FreeBSD has GNU Common Lisp(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/gcl-2.0.tgz) available as aFreeBSD tem GNU Common Lisp(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/gcl-2.0.tgz) disponível como umpackage. pacote.Perl PerlVery popular with system administrators for writing scripts; also oftenused on World Wide Web servers for Muito popular entre osadministradores do sistema para a criação de scripts, tambémfrequentemente usado em servidores World Wide Web parawriting CGI scripts. escrever scripts CGI.The latest version (version 5) comes with FreeBSD. A última versão(versão 5) vem com FreeBSD.Scheme EsquemaA dialect of Lisp that is rather more compact and cleaner than CommonLisp. Um dialeto de Lisp que é um pouco mais compacto e mais limpo queLisp Comum. Popular in Universities as it is Popular nas Universidades,pois ésimple enough to teach to undergraduates as a first language, while ithas a high enough level of abstraction to simples o suficiente paraensinar aos estudantes como primeira língua, enquanto ele tem um nívelbastante alto de abstração parabe used in research work. ser utilizado em trabalhos de investigação.FreeBSD has packages of the Elk Scheme Interpreter FreeBSD tem pacotesdo regime Interpreter Elk(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/elk-3.0.tgz), the MITScheme Interpreter

Page 11: 139920579 Versao Traduzida de Book

(Ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/elk-3.0.tgz), o regimeInterpreter MIT(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/mit-scheme-7.3.tgz) andthe SCM Scheme Interpreter(Ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/mit-scheme-7.3.tgz) edo Sistema Interpreter SCM(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/scm-4e1.tgz).(Ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/scm-4e1.tgz).Icon ÍconeThe Icon Programming Language(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/icon-9.0.tgz). ALinguagem de Programação Icon(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/icon-9.0.tgz).Logo LogotipoBrian Harvey's LOGO Interpreter(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/ucblogo-3.3.tgz).Intérprete LOGO de Brian Harvey(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/ucblogo-3.3.tgz).Python PítonThe Python Object-Oriented Programming Language O Python Object-OrientedProgramming Language(ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/python-1.2)(Ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/python-1.2)/7/ /7/------------------------------------------------------------------------*Page 16* *Page 16*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*5.3.3.* *5.3.3.* *Compilers* *Compiladores*Compilers are rather different. Compiladores são bastante diferentes.First of all, you write your code in a file (or files) using an editor.Primeiro de tudo, você escreve seu código em um arquivo (ou arquivos),utilizando um editor. You then run the Em seguida, execute ocompiler and see if it accepts your program. compilador e ver se eleaceita o seu programa. If it did not compile, grit your teeth and goback to the editor; if it did Se não compilar, ranger os dentes e voltarao editor e, se ele fezcompile and gave you a program, you can run it either at a shell commandprompt or in a debugger to see if it works compilar e deu-lhe umprograma, você pode executá-lo em um prompt de comando shell ou umdepurador para ver se funcionaproperly. adequadamente.1 1Obviously, this is not quite as direct as using an interpreter.Obviamente, isso não é tão direta como a utilização de um intérprete.However it allows you to do a lot of things which are No entanto,permite que você faça um monte de coisas que sãovery difficult or even impossible with an interpreter, such as writingcode which interacts closely with the operating muito difícil ou mesmoimpossível para um intérprete, como escrever código que interage deperto com a operaçãosystem—or even writing your own operating system! sistema, ou mesmoescrever o seu próprio sistema operacional! It's also useful if you needto write very efficient code, as the Também é útil se você precisarescrever código muito eficiente, como ocompiler can take its time and optimise the code, which would not beacceptable in an interpreter. compilador pode tomar o seu tempo eoptimizar o código, o que não seria aceitável um intérprete. Anddistributing a E distribuir umprogram written for a compiler is usually more straightforward than one

Page 12: 139920579 Versao Traduzida de Book

written for an interpreter—you can just give programa escrito para umcompilador é geralmente mais simples do que um escrito de um intérprete,você pode apenas darthem a copy of the executable, assuming they have the same operatingsystem as you. -lhes uma cópia do executável, assumindo que eles têm omesmo sistema operacional que você.Compiled languages include Pascal, C and C++. Linguagens compiladasincluem Pascal, C e C + +. C and C++ are rather unforgiving languages,and best suited to C e C + + são linguagens bastante implacável e maisadequado paramore experienced programmers; Pascal, on the other hand, was designed asan educational language, and is quite a programadores mais experientes,Pascal, por outro lado, foi concebida como uma linguagem educacional, eé bastantegood language to start with. boa linguagem para começar. Unfortunately,FreeBSD doesn't have any Pascal support, except for a Pascal-to-CInfelizmente, FreeBSD não tem qualquer apoio Pascal, com exceção de umPascal-to-Cconverter in the ports. conversor nos portos.As the edit-compile-run-debug cycle is rather tedious when usingseparate programs, many commercial compiler Como o ciclo deedição-compilação-run-debug é bastante tedioso quando usar programasseparados, muitos compilador comercialmakers have produced Integrated Development Environments (IDEs forshort). fabricantes têm produzido ambientes de desenvolvimento integrado(IDEs para o short). FreeBSD does not have an IDE as FreeBSD não tem umIDE comosuch; however it is possible to use Emacs for this purpose. tal, noentanto, é possível utilizar o Emacs para esta finalidade. This isdiscussed in Section 5.7 <#33> . Isso é discutido na Seção 5.7 <#33> .*5.4.* *5.4.* *Compiling with* *Compilando com**cc* *cc*This section deals only with the GNU compiler for C and C++, since thatcomes with the base FreeBSD system. Esta seção lida apenas com ocompilador GNU para C e C + +, uma vez que vem com o sistema FreeBSDbase. It Elecan be invoked by either pode ser invocada por qualquercc ccor ougcc gcc. . The details of producing a program with an interpreter varyconsiderably Os pormenores da produção de um programa com um intérpretevariar consideravelmentebetween interpreters, and are usually well covered in the documentationand on-line help for the interpreter. entre os intérpretes, e geralmentesão bem cobertos na documentação e ajuda on-line para o intérprete.Once you've written your masterpiece, the next step is to convert itinto something that will (hopefully!) run on Depois que você escreveusua obra-prima, o próximo passo é convertê-lo em algo que (com sorte)executado emFreeBSD. FreeBSD. This usually involves several steps, each of which isdone by a separate program. Isto geralmente envolve vários passos, cadaum dos quais é feito por um programa distinto.1. 1. Pre-process your source code to remove comments and do othertricks like expanding macros in C. Pré-processar o seu código-fonte pararemover comentários e fazer outros truques como expandir macros em C.2. 2. Check the syntax of your code to see if you have obeyed the rulesof the language. Verifique a sintaxe do seu código para ver se vocêtiver obedecido às regras do idioma. If you have not, it will Se vocênão tiver, ele vai

Page 13: 139920579 Versao Traduzida de Book

complain! reclamar!3. 3. Convert the source code into assembly language—this is very closeto machine code, but still understandable by Converter o código fonte emlinguagem assembly, este está muito perto de código de máquina, masainda assim compreensível porhumans. seres humanos. Allegedly. Alegadamente.2 24. 4. Convert the assembly language into machine code—yep, we aretalking bits and bytes, ones and zeros here. Converter a linguagem demontagem em código de máquina, sim, estamos a falar de bits e bytes, unse zeros aqui./8/ /8/------------------------------------------------------------------------*Page 17* *Page 17*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/5. 5. Check that you have used things like functions and globalvariables in a consistent way. Verifique se você usou coisas comofunções e variáveis ��globais de uma forma consistente. For example, ifyou Por exemplo, sehave called a non-existent function, it will complain. ter chamado umafunção inexistente, ele vai reclamar.6. 6. If you are trying to produce an executable from several sourcecode files, work out how to fit them all together. Se você está tentandoproduzir um executável a partir de vários arquivos de código fonte, otrabalho como encaixá-los todos juntos.7. 7. Work out how to produce something that the system's run-timeloader will be able to load into memory and run. Exercite-se comoproduzir algo que carregador de tempo de execução do sistema será capazde carregar na memória e executado.8. 8. Finally, write the executable on the file system. Finalmente,escreva o executável no sistema de arquivos.The word /compiling/ is often used to refer to just steps 1 to 4—theothers are referred to as /linking/ . A palavra /compilação/ éfrequentemente utilizado para referir apenas os passos 1 a 4 os outrossão referidos como /ligando./ Sometimes step 1 Às vezes passo 1is referred to as /pre-processing/ and steps 3-4 as /assembling/ . éreferido como /pré-processamento/ e os passos 3-4 como /a montagem./Fortunately, almost all this detail is hidden from you, as Felizmente,quase todos esses detalhes está escondido de você, comocc ccis a front end that manages calling all these programs é um front-endque gerencia chamando todos esses programaswith the right arguments for you; simply typing com os argumentos certospara você, basta digitar% %*cc foobar.c* *cc foobar.c*will cause causaráfoobar.c foobar.cto be compiled by all the steps above. ser elaboradas por todos ospassos acima. If you have more than one file to compile, just do Se vocêtiver mais de um arquivo para compilar, basta fazersomething like algo parecido% %*cc foo.c bar.c* *cc foo.c bar.c*Note that the syntax checking is just that—checking the syntax. Note-seque a verificação de sintaxe é exatamente isso, a verificação dasintaxe. It will not check for any logical mistakes you may Não vaiverificar se há erros lógicos Você podehave made, like putting the program into an infinite loop, or using a

Page 14: 139920579 Versao Traduzida de Book

bubble sort when you meant to use a binary sort. ter feito, como colocaro programa em um loop infinito, ou usando uma espécie de bolha quandovocê pretende usar uma classificação binária.3 3There are lots and lots of options for Há muitas e muitas opções paracc cc, which are all in the man page. , Que estão todos na página man. Hereare a few of the most important ones, Aqui estão algumas das maisimportantes,with examples of how to use them. com exemplos de como usá-los.-o /filename/ -O /nome do arquivo/The output name of the file. O nome de saída do arquivo. If you do notuse this option, Se você não usar esta opção,cc ccwill produce an executable called vai produzir um executável chamadoa.out a.out. .4 4% %*cc foobar.c* *cc foobar.c*/executable is/ /executável é//a.out/ /a.out/% %*cc -o foobar foobar.c* *cc-o foobar.c foobar*/executable is/ /executável é//foobar/ /foobar/-c -CJust compile the file, do not link it. Apenas compilar o arquivo, nãoligá-lo. Useful for toy programs where you just want to check thesyntax, or if you Útil para programas de brinquedos onde você querapenas verificar a sintaxe, ou se vocêare using a estiver usando umaMakefile Makefile. .% %*cc -c foobar.c* *cc-c foobar.c*/9/ /9/------------------------------------------------------------------------*Page 18* *Page 18*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/This will produce an /object file/ (not an executable) called Isso iráproduzir um /arquivo de objeto/ (e não um executável) chamadofoobar.o foobar.o. . This can be linked together with other Isto pode estar ligado emconjunto com outrosobject files into an executable. arquivos objeto em um arquivo executável.-g -GCreate a debug version of the executable. Criar uma versão de depuraçãodo executável. This makes the compiler put information into theexecutable about Isso faz com que o compilador colocar informações noexecutável sobrewhich line of which source file corresponds to which function call. quala linha que corresponde arquivo de origem para que chamar a função. Adebugger can use this information to show Um depurador pode usar estainformação para mostrarthe source code as you step through the program, which is /very/ useful;the disadvantage is that all this extra o código-fonte como você pisaatravés do programa, que é /muito/ útil, a desvantagem é que tudo issoadicional

Page 15: 139920579 Versao Traduzida de Book

information makes the program much bigger. faz com que o programa deinformação muito maior. Normally, you compile with Normalmente, vocêcompilar com-g -Gwhile you are developing a enquanto você estiver desenvolvendo umprogram and then compile a “release version” without programa e, emseguida, compilar uma versão "release" sem-g -Gwhen you're satisfied it works properly. Quando estiver satisfeito elefunciona corretamente.% %*cc -g foobar.c* *cc-g foobar.c*This will produce a debug version of the program. Isso vai produzir umaversão de depuração do programa.5 5-O -OCreate an optimised version of the executable. Criar uma versãootimizada do executável. The compiler performs various clever tricks totry and produce O compilador executa vários truques espertos para tentarproduziran executable that runs faster than normal. um executável que é maisrápido que o normal. You can add a number after the Você pode adicionarum número após o-O -Oto specify a higher level of para especificar um nível mais elevado deoptimisation, but this often exposes bugs in the compiler's optimiser.otimização, mas isso muitas vezes expõe erros no otimizador docompilador. For instance, the version of Por exemplo, a versãocc ccthat comes que vemwith the 2.1.0 release of FreeBSD is known to produce bad code with thecom a versão 2.1.0 do FreeBSD é conhecida por produzir código ruim com o-O2 -O2option in some circumstances. opção em algumas circunstâncias.Optimisation is usually only turned on when compiling a release version.Optimização normalmente só é ativado quando compilar uma versão delançamento.% %*cc -O -o foobar foobar.c* *cc-O-O foobar foobar.c*This will produce an optimised version of Isso vai produzir uma versãootimizada dofoobar foobar. .The following three flags will force Os três seguintes bandeiras forçarácc ccto check that your code complies to the relevant international standard,often para verificar se o seu código está em conformidade com a normainternacional relevante, muitas vezesreferred to as the ANSI standard, though strictly speaking it is an ISOstandard. referida como a norma ANSI, embora estritamente falando, é umanorma da ISO.-Wall -WallEnable all the warnings which the authors of Ativar todos os avisos queos autorescc ccbelieve are worthwhile. acreditar valem a pena. Despite the name, itwill not enable all Apesar do nome, não irá permitir que todosthe warnings as advertênciascc ccis capable of. é capaz de suportar.

Page 16: 139920579 Versao Traduzida de Book

/10/ /10/------------------------------------------------------------------------*Page 19* *Page 19*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/-ansi -AnsiTurn off most, but not all, of the non-ANSI C features provided byDesactivar a maioria, mas não todas, as características não-ANSI Cfornecidas peloscc cc. . Despite the name, it does not guarantee Apesar do nome, ele não garantestrictly that your code will comply to the standard. rigorosamente queseu código irá cumprir a norma.-pedantic -PedanteTurn off /all/ Desligue /todos os/cc cc's non-ANSI C features. 'S recursos não-ANSI C.Without these flags, Sem essas bandeiras,cc ccwill allow you to use some of its non-standard extensions to thestandard. permitirá que você use algumas de suas extensões não-padrãopara o padrão. Some of these are Alguns destes sãovery useful, but will not work with other compilers—in fact, one of themain aims of the standard is to allow people muito útil, mas nãofuncionará com outros compiladores-de fato, um dos principais objetivosda norma é permitir que as pessoasto write code that will work with any compiler on any system. escrevercódigo que irá funcionar com qualquer compilador em qualquer sistema.This is known as /portable code/ . Isto é conhecido como /o códigoportátil./Generally, you should try to make your code as portable as possible, asotherwise you may have to completely Geralmente, você deve tentar fazero seu código mais portável possível, caso contrário, você pode ter quecompletamentere-write the program later to get it to work somewhere else—and whoknows what you may be using in a few years re-escrever o programa maistarde para fazê-lo trabalhar em outro lugar e que sabe o que você podeestar usando em poucos anostime? tempo?% %*cc -Wall -ansi -pedantic -o foobar foobar.c* *cc-Wall-ansi-pedante-ofoobar.c foobar*This will produce an executable Isso irá produzir um executávelfoobar foobarafter checking depois de verificarfoobar.c foobar.cfor standard compliance. para o cumprimento das normas.-l /library/ /Biblioteca-l/Specify a function library to be used during when linking. Especifiqueuma biblioteca de funções para ser usado durante quando ligar.The most common example of this is when compiling a program that usessome of the mathematical functions O exemplo mais comum é quando acompilação de um programa que usa algumas das funções matemáticasin C. Unlike most other platforms, these are in a separate library fromthe standard C one and you have to tell em C. Ao contrário da maioria deoutras plataformas, estes estão em uma biblioteca separada do padrão C eum que você tem a dizerthe compiler to add it. o compilador para adicioná-lo.The rule is that if the library is called A regra é que se a bibliotecaé chamado

Page 17: 139920579 Versao Traduzida de Book

lib /something/ .a lib /alguma coisa./ uma, you give , Você dácc ccthe argument o argumento-l /something/ -L /algo/. . For Paraexample, the math library is exemplo, a biblioteca matemática élibm.a libm.a, so you give , Então você dácc ccthe argument o argumento-lm -Lm. . A common “gotcha” with the math A "pegadinha" comum com a matemáticalibrary is that it has to be the last library on the command line.biblioteca é que tem que ser a última biblioteca na linha de comando.% %*cc -o foobar foobar.c -lm* *cc-o foobar foobar.c-lm*This will link the math library functions into Isto irá ligar as funçõesde biblioteca de matemática emfoobar foobar. .If you are compiling C++ code, you need to add Se você está compilando ocódigo C + +, você precisa adicionar-lg++ -Lg + +, or Ou-lstdc++ -Lstdc + +if you are using FreeBSD 2.2 or later, to se você estiver usando FreeBSD2.2 ou posterior, parathe command line argument to link the C++ library functions. o argumentode linha de comando para ligar as funções C + + biblioteca.Alternatively, you can run Alternativamente, você pode executarc++ c + +instead of em vez decc cc, ,which does this for you. que faz isso para você.c++ c + +can also be invoked as também pode ser invocado comog++ g+ +on FreeBSD. em FreeBSD.% %*cc -o foobar foobar.cc -lg++* *cc-o foobar foobar.cc-lg + +*/For FreeBSD 2.1.6 and earlier/ /Para o FreeBSD 2.1.6 e anteriores/% %*cc -o foobar foobar.cc -lstdc++* /For FreeBSD 2.2 and later/ *cc-ofoobar foobar.cc-lstdc + +* /Para o FreeBSD 2.2 e mais tarde/% %*c++ -o foobar foobar.cc* *c + +-o foobar foobar.cc*/11/ /11/------------------------------------------------------------------------*Page 20* *Page 20*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/Each of these will both produce an executable Cada um destes iráproduzir tanto um executávelfoobar foobarfrom the C++ source file a partir do arquivo fonte C + +foobar.cc foobar.cc. . Note that, on Unix Note-se que, em Unixsystems, C++ source files traditionally end in sistemas, C + + arquivos

Page 18: 139920579 Versao Traduzida de Book

de origem tradicionalmente termina em.C . C, ,.cxx . CXXor ou.cc . Cc, rather than the MS-DOS style , Em vez do modelo MS-DOS.cpp . Cpp(which was (Que eraalready used for something else). já utilizado para outra coisa).gcc gccused to rely on this to work out what kind of compiler to use on theusado para contar com este trabalho que tipo de compilador para usar nosource file; however, this restriction no longer applies, so you may nowcall your C++ files arquivo de origem, no entanto, esta restrição não seaplica mais, então agora você pode chamar seus arquivos C + +.cpp . Cppwith impunity! impunemente!*5.4.1.* *5.4.1.* *Common* *Comum**cc* *cc**Queries and Problems* *Consultas e Problemas**1.* I am trying to write a program which uses the *1.* Estou tentandoescrever um programa que usa osin() sin ()function and I get an error like this. funcionar e eu recebo um errocomo este. What does it mean? O que isso significa?/var/tmp/cc0143941.o: Undefined symbol '_sin' referenced from textsegment / Var/tmp/cc0143941.o: símbolo Undefined "_sin 'referenciado apartir de segmento de textoWhen using mathematical functions like Ao usar funções matemáticas comosin() sin (), you have to tell , Você tem que dizercc ccto link in the math library, like so: de ligação na biblioteca dematemática, assim:% %*cc -o foobar foobar.c -lm* *cc-o foobar foobar.c-lm**2.* All right, I wrote this simple program to practice using *2.* Tudobem, eu escrevi este programa simples para praticar o uso de-lm -Lm. . All it does is raise 2.1 to the power of 6. Tudo que faz é levantar2.1 para o poder da 6.#include < stdio.h > # Include <stdio.h>int main() { int main () {float f; flutuar f;f = pow(2.1, 6); f = pow (2.1, 6);printf("2.1 ^ 6 = %f\n", f); printf ("2.1 ^ 6 =% f \ n", f);return 0; retornar 0;} }and I compiled it as: e eu compilei como:% %*cc temp.c -lm* *cc temp.c-lm*like you said I should, but I get this when I run it: como você disseque eu deveria, mas eu recebo isso quando eu executá-lo:/12/ /12/------------------------------------------------------------------------*Page 21* *Page 21*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/% %

Page 19: 139920579 Versao Traduzida de Book

*./a.out* *. / A.out*2.1 ^ 6 = 1023.000000 2.1 ^ 6 = 1023,000000This is /not/ the right answer! Esta /não/ é a resposta certa! What isgoing on? O que está acontecendo?When the compiler sees you call a function, it checks if it has alreadyseen a prototype for it. Quando o compilador vê você chamar uma função,ele verifica se ele já viu um protótipo para ele. If it has not, itassumes Se não tiver, ele assumethe function returns an int, which is definitely not what you want here.a função retorna um int, o que definitivamente não é o que você quer aqui.*3.* So how do I fix this? *3.* Então, como faço para corrigir isso?The prototypes for the mathematical functions are in Os protótipos paraas funções matemáticas são emmath.h math.h. . If you include this file, the compiler will be able to Se vocêincluir esse arquivo, o compilador será capaz defind the prototype and it will stop doing strange things to yourcalculation! encontrar o protótipo e ele vai parar de fazer coisasestranhas para o seu cálculo!#include < math.h > # Include <math.h>#include < stdio.h > # Include <stdio.h>int main() { int main () {... ...After recompiling it as you did before, run it: Depois de recompilar-locomo você fez antes, executá-lo:% %*./a.out* *. / A.out*2.1 ^ 6 = 85.766121 2.1 ^ 6 = 85,766121If you are using any of the mathematical functions, /always/ include Sevocê estiver usando qualquer uma das funções matemáticas, /inclua sempre/math.h math.hand remember to link in the math library. e lembre-se de vincular abiblioteca matemática.*4.* I compiled a file called *4.* Que eu compilei um arquivo chamadofoobar.c foobar.cand I cannot find an executable called e eu não consigo encontrar umexecutável chamadofoobar foobar. . Where's it gone? Onde é que ele foi?Remember, Lembre-se,cc ccwill call the executable vai chamar o executávela.out a.outunless you tell it differently. a menos que você diga a ele de formadiferente. Use the Use o-o /filename/ -O /nome do arquivo/option: opção:% %*cc -o foobar foobar.c* *cc-o foobar.c foobar**5.* OK, I have an executable called *5.* Bem, eu tenho um executávelchamadofoobar foobar, I can see it when I run , Eu posso vê-la quando eu corrols ls, but when I type in , Mas quando eu digitarfoobar foobarat the command no comandoprompt it tells me there is no such file. pedir ele me diz que não hátal arquivo. Why can it not find it? Por que pode não encontrá-lo?Unlike MS-DOS, Unix does not look in the current directory when it is

Page 20: 139920579 Versao Traduzida de Book

trying to find out which executable you want Ao contrário do MS-DOS,Unix não olha no diretório atual quando se está tentando descobrir qualexecutável que você desejait to run, unless you tell it to. que ele seja executado, a menos quevocê diga a ele. Either type Qualquer tipo./foobar . / Foobar, which means “run the file called , Que significa "executar o arquivochamadofoobar foobarin the current na actualdirectory”, or change your PATH environment variable so that it lookssomething like diretório ", ou alterar a variável de ambiente PATH paraque ele se parece com/13/ /13/------------------------------------------------------------------------*Page 22* *Page 22*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/bin:/usr/bin:/usr/local/bin:. bin :/ usr / bin :/ usr / local / bin:.The dot at the end means “look in the current directory if it is not inany of the others”. O ponto no final significa "olhar no diretórioatual, se não é em qualquer um dos outros."*6.* I called my executable *6.* Liguei para o meu executáveltest teste, but nothing happens when I run it. , Mas nada acontece quando euexecutá-lo. What is going on? O que está acontecendo?Most Unix systems have a program called A maioria dos sistemas Unix temum programa chamadotest testein em/usr/bin / Usr / binand the shell is picking that one up before it gets to eo escudo éescolher aquele up antes de chegar achecking the current directory. verificar o diretório atual. Eithertype: Qualquer tipo:% %*./test* *. / Teste*or choose a better name for your program! ou escolher um nome melhorpara o seu programa!*7.* I compiled my program and it seemed to run all right at first, thenthere was an error and it said something about *7.* Que eu compilei meuprograma e ele parecia correr tudo bem no início, em seguida, houve umerro e ele disse algo sobrecore dumped núcleo despejado. . What does that mean? O que significa isso?The name /core dump/ dates back to the very early days of Unix, when themachines used core memory for storing O /núcleo de despejo/ nome remontaaos primórdios do Unix, quando as máquinas usadas da memória principalpara armazenamentodata. dados. Basically, if the program failed under certain conditions,the system would write the contents of core memory Basicamente, se oprograma falhou sob certas condições, o sistema iria escrever o conteúdoda memória de núcleoto disk in a file called para o disco em um arquivo chamadocore núcleo, which the programmer could then pore over to find out what went wrong., Que o programador pode então debruçar sobre para descobrir o que deuerrado.*8.* Fascinating stuff, but what I am supposed to do now? *8.* Coisafascinante, mas o que eu devo fazer agora?

Page 21: 139920579 Versao Traduzida de Book

Use Usargdb gdbto analyse the core (see Section 5.6) <#29> . para analisar o núcleo(ver Seção 5.6) <#29> .*9.* When my program dumped core, it said something about a *9.* Ao meuprograma despejado núcleo, ele disse algo sobre umsegmentation fault falha de segmentação. . What's that? O que é isso?This basically means that your program tried to perform some sort ofillegal operation on memory; Unix is designed Isto significa basicamenteque o seu programa tentou realizar algum tipo de operação ilegal emmemória; Unix foi projetadoto protect the operating system and other programs from rogue programs.para proteger o sistema operacional e outros programas de programasmaliciosos.Common causes for this are: As causas mais comuns para isso são:• •Trying to write to a NULL pointer, eg Tentando escrever para um ponteiroNULL, por exemplo,char *foo = NULL; char * foo = NULL;strcpy(foo, "bang!"); strcpy (foo, "bang!");• •Using a pointer that hasn't been initialised, eg Usando um ponteiro quenão tenha sido iniciada, por exemplo,char *foo; char * foo;strcpy(foo, "bang!"); strcpy (foo, "bang!");/14/ /14/------------------------------------------------------------------------*Page 23* *Page 23*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/The pointer will have some random value that, with luck, will point intoan area of memory that isn't available to O ponteiro vai ter algum valoraleatório que, com sorte, irá apontar para uma área de memória que nãoestá disponível parayour program and the kernel will kill your program before it can do anydamage. seu programa eo kernel vai matar o seu programa antes que elepossa fazer qualquer dano. If you're unlucky, it'll point Se você éazarado, ele vai apontarsomewhere inside your own program and corrupt one of your datastructures, causing the program to fail em algum lugar dentro do seupróprio programa e corrupto uma das suas estruturas de dados, fazendocom que o programa falharmysteriously. misteriosamente.• •Trying to access past the end of an array, eg Tentativa de acesso após ofinal de uma matriz, por exemplo,int bar[20]; bar int [20];bar[27] = 6; bar [27] = 6;• •Trying to store something in read-only memory, eg Tentar armazenar algona memória só de leitura, por exemplo,char *foo = "My string"; char * foo = "Minha string";strcpy(foo, "bang!"); strcpy (foo, "bang!");Unix compilers often put string literals like Compiladores Unix muitasvezes colocar strings literais como"My string" "Minha string"into read-only areas of memory. em somente leitura áreas de memória.• •Doing naughty things with Fazer as coisas impertinentes com

Page 22: 139920579 Versao Traduzida de Book

malloc() malloc ()and efree() free (), eg , Por exemplo,char bar[80]; carvão bar [80];free(bar); livre (bar);or ouchar *foo = malloc(27); char * foo = malloc (27);free(foo); livre (foo);free(foo); livre (foo);Making one of these mistakes will not always lead to an error, but theyare always bad practice. Fazendo um desses erros nem sempre vai levar aum erro, mas eles estão sempre má prática. Some systems and Algunssistemas ecompilers are more tolerant than others, which is why programs that ranwell on one system can crash when you try compiladores são maistolerantes do que outros, razão pela qual os programas que funcionarambem em um sistema pode falhar quando você tentarthem on an another. los em uma outra./15/ /15/------------------------------------------------------------------------*Page 24* *Page 24*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*10.* Sometimes when I get a core dump it says *10.* Às vezes, quando eurecebo um dump de memória que dizbus error erro de ônibus. . It says in my Unix book that this means a hardware Diz no meu livroUnix que isso significa um hardwareproblem, but the computer still seems to be working. problema, mas aindaassim o computador parece estar funcionando. Is this true? Isso é verdade?No, fortunately not (unless of course you really do have a hardwareproblem...). Não, felizmente não (a menos que você realmente tem umproblema de hardware ...). This is usually another way of Este énormalmente um outro modo desaying that you accessed memory in a way you shouldn't have. dizendo quevocê acessou a memória de uma forma que não deveria ter.*11.* This dumping core business sounds as though it could be quiteuseful, if I can make it happen when I want to. *11.* Esse negócio denúcleo de dumping soa como se ele poderia ser bastante útil, se eu possofazer isso acontecer quando eu quiser.Can I do this, or do I have to wait until there's an error? Eu possofazer isso, ou eu tenho que esperar até que haja um erro?Yes, just go to another console or xterm, do Sim, basta ir para outroconsole ou xterm, fazer% %*ps* *ps*to find out the process ID of your program, and do para descobrir a IDde seu programa de processo e fazer% %*kill -ABRT /pid/* *matá-ABRT /pid/*where /pid/ is the process ID you looked up. onde /pid/ é o ID doprocesso que você olhou para cima.This is useful if your program has got stuck in an infinite loop, forinstance. Isto é útil se o seu programa ficou preso em um loop infinito,por exemplo. If your program happens to trap Se o seu programa acontecepara prenderSIGABRT, there are several other signals which have a similar effect.SIGABRT, existem vários outros sinais, que têm um efeito semelhante.Alternatively, you can create a core dump from inside your program, by

Page 23: 139920579 Versao Traduzida de Book

calling the Alternativamente, você pode criar um dump de memória dedentro do seu programa, chamando aabort() abort ()function. função. See the man Veja o homempage of abort(3) to learn more. Página de abortar (3) para saber mais.If you want to create a core dump from outside your program, but don'twant the process to terminate, you can use Se você deseja criar um dumpde memória fora do seu programa, mas não quer que o processo terminar,você pode usarthe ogcore gcoreprogram. programa. See the man page of gcore(1) for more information.Veja a página de manual de gcore (1) para obter mais informações.*5.5.* *5.5.* *Make* *Fazer**5.5.1.* *5.5.1.* *What is* *O que é**make* *fazer**?* *?*When you're working on a simple program with only one or two sourcefiles, typing in Quando você está trabalhando em um programa simples,com apenas um ou dois arquivos de origem, digitando% %*cc file1.c file2.c* *cc file1.c FILE2.C*is not too bad, but it quickly becomes very tedious when there areseveral files—and it can take a while to compile, não é tão ruim, masrapidamente se torna muito chato quando há vários arquivos e podedemorar um pouco para compilartoo. também./16/ /16/------------------------------------------------------------------------*Page 25* *Page 25*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/One way to get around this is to use object files and only recompile thesource file if the source code has changed. Uma maneira de contornareste problema é usar arquivos de objetos e apenas recompilar o arquivode origem se o código-fonte foi alterada. So Assimwe could have something like: poderíamos ter algo como:% %*cc file1.o file2.o* ... *file37.c* ... *cc arq1.o arq2.o* ...*file37.c* ...if we'd changed se tivéssemos mudadofile37.c file37.c, but not any of the others, since the last time we compiled. , Mas nãoqualquer um dos outros, já que a última vez que compilado. This mayspeed up the Isto pode acelerar ocompilation quite a bit, but doesn't solve the typing problem.compilação um pouco, mas não resolve o problema de digitação.Or we could write a shell script to solve the typing problem, but itwould have to re-compile everything, making it Ou poderíamos escrever umscript shell para resolver o problema de digitação, mas que teria devoltar a compilar tudo, tornando-severy inefficient on a large project. muito ineficiente em um grandeprojeto.What happens if we have hundreds of source files lying about? O queacontece se temos centenas de arquivos de origem mentindo? What if we'reworking in a team with other people E se nós estamos trabalhando em umaequipe com outras pessoaswho forget to tell us when they've changed one of their source filesthat we use? que se esqueça de nos dizer quando eles mudaram um dos seusarquivos de origem que usamos?

Page 24: 139920579 Versao Traduzida de Book

Perhaps we could put the two solutions together and write something likea shell script that would contain some kind Talvez pudéssemos colocar asduas soluções em conjunto e escrever algo como um script shell quecontêm algum tipoof magic rule saying when a source file needs compiling. de regra mágicadizer quando um arquivo de origem precisa de compilar. Now all we neednow is a program that can understand Agora, tudo o que precisamos agoraé um programa que pode compreenderthese rules, as it's a bit too complicated for the shell. estas regras,pois é um pouco complicado para o shell.This program is called Este programa é chamadomake fazer. . It reads in a file, called a /makefile/ , that tells it howdifferent files depend on each other, Ele lê um arquivo, chamado/makefile,/ que diz-lhe como arquivos diferentes dependem uns dos outros,and works out which files need to be re-compiled and which ones don't. efunciona quais arquivos precisam ser re-compilado e quais não. Forexample, a rule could say something like Por exemplo, uma regra poderiadizer algo como“if "Sefromboz.o fromboz.ois older than é mais velho do quefromboz.c fromboz.c, that means someone must have changed , Isso significa que alguém deveter mudadofromboz.c fromboz.c, so it needs to be , Por isso precisa serre-compiled.” The makefile also has rules telling make /how/ tore-compile the source file, making it a much more re-compilado. "Omakefile também tem regras que dizem /como/ fazer para voltar a compilaro arquivo de origem, tornando-se muito maispowerful tool. ferramenta poderosa.Makefiles are typically kept in the same directory as the source theyapply to, and can be called Makefiles são normalmente mantidos no mesmodiretório que a fonte se aplicam a, e pode ser chamadomakefile makefile, ,Makefile Makefileor ouMAKEFILE MAKEFILE. . Most programmers use the name A maioria dos programadores usam o nomeMakefile Makefile, as this puts it near the top of a directory , Pois isso coloca-loperto do topo de um diretóriolisting, where it can easily be seen. perfil, onde ele pode serfacilmente visto.6 6*5.5.2.* *5.5.2.* *Example of using* *Exemplo de utilização**make* *fazer*Here's a very simple make file: Aqui está um arquivo make muito simples:foo: foo.c foo: foo.ccc -o foo foo.c cc-o foo foo.cIt consists of two lines, a dependency line and a creation line. Écomposto por duas linhas, uma linha de dependência e uma linha de criação.The dependency line here consists of the name of the program (known asthe /target/ ), followed by a colon, then A linha de dependência aquiconsiste no nome do programa (conhecido como o /alvo),/ seguido de umcólon, entãowhitespace, then the name of the source file. espaços em branco, emseguida, o nome do arquivo de origem. When Quando

Page 25: 139920579 Versao Traduzida de Book

make fazerreads this line, it looks to see if lê essa linha, olha para ver sefoo fooexists; if it exists, it existe e, se ele existe,compares the time compara a horafoo foowas last modified to the time foi modificada para o último momentofoo.c foo.cwas last modified. foi modificada pela última vez. If Sefoo foodoes not exist, or is older than não existe, ou é mais velho do quefoo.c foo.c, it then looks at the creation line to find out what to do. , Então eleolha para a linha de criação para descobrir o que fazer. In other words,this is the rule for working out when Em outras palavras, esta é a regrapara trabalhar fora quandofoo.c foo.cneeds to be re-compiled. precisa ser re-compilado./17/ /17/------------------------------------------------------------------------*Page 26* *Page 26*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/The creation line starts with a tab (press the *tab* key) and then thecommand you would type to create A linha de criação começa com um guia(pressione a tecla *tab)* e, em seguida, o comando que você deve digitarpara criarfoo fooif you se vocêwere doing it at a command prompt. estavam fazendo isso em um prompt decomando. If Sefoo foois out of date, or does not exist, está desatualizado, ou não existe,make fazerthen executes this command to em seguida, executa o comando paracreate it. criá-lo. In other words, this is the rule which tells makehow to re-compile Em outras palavras, esta é a regra que diz como fazerpara voltar a compilarfoo.c foo.c. .So, when you type *make* , it will make sure that Então, quando vocêdigita *fazer,* ele vai ter certeza de quefoo foois up to date with respect to your latest changes to está atualizado comrelação a suas últimas alteraçõesfoo.c foo.c. . This Esteprinciple can be extended to princípio pode ser alargado aMakefile Makefiles with hundreds of targets—in fact, on FreeBSD, it is possible tocompile the s com centenas de alvos em verdade, em FreeBSD, é possívelcompilar aentire operating system just by typing *make world* in the appropriatedirectory! todo o sistema operacional apenas digitando *make world* nodiretório apropriado!Another useful property of makefiles is that the targets don't have tobe programs. Outra propriedade útil da makefiles é que os alvos nãoprecisam ser programas. For instance, we could have a Por exemplo,poderíamos ter ummake file that looks like this: fazer arquivo que se parece com isto:

Page 26: 139920579 Versao Traduzida de Book

foo: foo.c foo: foo.ccc -o foo foo.c cc-o foo foo.cinstall: instalar:cp foo /home/me cp foo / home / meWe can tell make which target we want to make by typing: Podemos dizerque fazer-alvo que queremos fazer, digitando:% %*make /target/* *tornar /alvo/*make fazerwill then only look at that target and ignore any others. então só olharpara o alvo e ignorar os outros. For example, if we type *make foo* withthe makefile Por exemplo, se digitar *fazer foo* com o makefileabove, make will ignore the install target. acima, faça irá ignorar odestino de instalação.If we just type *make* on its own, make will always look at the firsttarget and then stop without looking at any others. Se digitar apenas*fazer* por conta própria, certifique-se sempre olhar para o primeiroalvo e depois parar, sem olhar para os outros.So if we typed *make* here, it will just go to the foo target,re-compile Então, se nós digitamos *fazer* aqui, ele só vai para o alvofoo, re-compilaçãofoo fooif necessary, and then stop without going se necessário, e depois parar,sem passaron to the install target. para a meta de instalação.Notice that the install target doesn't actually depend on anything!Note-se que a meta de instalação na verdade não depende de nada! Thismeans that the command on the following line Isso significa que ocomando na linha seguinteis always executed when we try to make that target by typing *makeinstall* . é sempre executada quando tentamos fazer com que essa meta ocomando *make install.* In this case, it will copy Neste caso, ele copiafoo foointo emthe user's home directory. o diretório home do usuário. This is oftenused by application makefiles, so that the application can be installedin the Isso é muitas vezes utilizado por aplicação makefiles, de modoque a aplicação pode ser instalada nocorrect directory when it has been correctly compiled. corrigirdiretório quando foi compilado corretamente.This is a slightly confusing subject to try and explain. Este é umassunto um pouco confuso para tentar explicar. If you don't quiteunderstand how Se você não consegue entender comomake fazerworks, the best thing obras, a melhor coisato do is to write a simple program like “hello world” and a make filelike the one above and experiment. a fazer é escrever um programasimples, como "Olá mundo" e fazer um arquivo como o descrito acima eexperiência. Then Em seguidaprogress to using more than one source file, or having the source fileinclude a header file. progredir para usar mais de um arquivo de origem,ou com o arquivo de origem incluir um arquivo de cabeçalho. The Otouch tocarcommand is comando évery useful here—it changes the date on a file without you having toedit it. muito útil aqui, ele muda a data em um arquivo sem anecessidade de editá-lo.*5.5.3.* *5.5.3.* *Make and include-files* *Faça e incluem-arquivos*C code often starts with a list of files to include, for examplestdio.h. Código C muitas vezes começa com uma lista de arquivos para

Page 27: 139920579 Versao Traduzida de Book

incluir, por exemplo stdio.h. Some of these files are system-includefiles, Alguns destes arquivos são do sistema incluem-arquivos,some of them are from the project you're now working on: alguns delessão do projeto que você está trabalhando agora em:/18/ /18/------------------------------------------------------------------------*Page 27* *Page 27*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/#include < stdio.h > # Include <stdio.h>#include "foo.h" # Include "foo.h"int main(.... int main (....To make sure that this file is recompiled the moment Para certificar-sede que este arquivo é recompilado o momentofoo.h foo.his changed, you have to add it in your for alterado, você tem queadicioná-lo em seuMakefile Makefile: :foo: foo.c foo.h foo: foo.c foo.hThe moment your project is getting bigger and you have more and more owninclude-files to maintain, it will be a No momento em que o projeto estáficando maior e você tem mais e mais próprio incluem-arquivos paramanter, será umpain to keep track of all include files and the files which aredepending on it. dor de manter o controle de todos os arquivos deinclusão e os arquivos que estão dependendo dela. If you change aninclude-file but forget Se você alterar um arquivo-incluem, mas esquecerto recompile all the files which are depending on it, the results willbe devastating. recompilar todos os arquivos que dependem disso, osresultados serão devastadores.gcc gcchas an option to analyze your tem uma opção para analisar o seufiles and to produce a list of include-files and their dependencies:arquivos e para produzir uma lista de inclui-arquivos e suas dependências:-MM -MM. .If you add this to your Makefile: Se você adicionar isso ao seu Makefile:depend: dependem:gcc -E -MM *.c > .depend gcc-E-MM *. c>. dependerand run *make depend* , the file e executar *make depend,* o arquivo.depend . Dependerwill appear with a list of object-files, C-files and the include-files:aparecerá uma lista de arquivos-objeto, C-arquivos e os-arquivos incluem:foo.o: foo.c foo.h foo.o: foo.c foo.hIf you change Se você mudarfoo.h foo.h, next time you run , Da próxima vez que você executarmake fazerall files depending on todos os arquivos dependendofoo.h foo.hwill be recompiled. será recompilado.Don't forget to run Não se esqueça de executarmake depend fazer dependereach time you add an include-file to one of your files. cada vez quevocê adicionar uma include-file para um dos seus arquivos.*5.5.4.* *5.5.4.* *FreeBSD Makefiles* *FreeBSD Makefiles*Makefiles can be rather complicated to write. Makefiles pode ser umpouco complicado de escrever. Fortunately, BSD-based systems likeFreeBSD come with some very Felizmente, os sistemas baseados em BSD como

Page 28: 139920579 Versao Traduzida de Book

FreeBSD vem com alguns muitopowerful ones as part of the system. os poderosos, como parte dosistema. One very good example of this is the FreeBSD ports system. Umbom exemplo disso é o sistema de ports FreeBSD. Here's the essentialAqui está o essencialpart of a typical ports parte de um portos típicosMakefile Makefile: :MASTER_SITES= MASTER_SITES =ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/DISTFILES= DISTFILES =scheme-microcode+dist-7.3-freebsd.tgz esquema de microcódigo +dist-7.3-freebsd.tgz.include < bsd.port.mk > . Include <bsd.port.mk>Now, if we go to the directory for this port and type *make* , thefollowing happens: Agora, se formos para o diretório para esta porta etipo de *make,* acontece o seguinte:1. 1. A check is made to see if the source code for this port is alreadyon the system. A verificação é feita para ver se o código-fonte paraessa porta já está no sistema.2. 2. If it isn't, an FTP connection to the URL in MASTER_SITES is setup to download the source. Caso não seja, uma conexão FTP para o URL emMASTER_SITES está configurado para baixar a fonte./19/ /19/------------------------------------------------------------------------*Page 28* *Page 28*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/3. 3. The checksum for the source is calculated and compared it with onefor a known, good, copy of the source. A soma de verificação da fonte écalculado e comparado com um para um conhecido, bom, cópia da fonte.This Esteis to make sure that the source was not corrupted while in transit. éter a certeza de que a fonte não foi corrompido enquanto em trânsito.4. 4. Any changes required to make the source work on FreeBSD areapplied—this is known as /patching/ . Quaisquer alterações necessáriaspara tornar o trabalho a fonte em FreeBSD são aplicados, isto éconhecido como /patching./5. 5. Any special configuration needed for the source is done. Nenhumaconfiguração especial é necessária para que a fonte seja feito. (ManyUnix program distributions try to work out (Muitas distribuições doprograma Unix tentar descobrirwhich version of Unix they are being compiled on and which optional Unixfeatures are present—this is where qual versão do Unix estão sendocompilados e quais as características do Unix opcionais estão presentes,este é o lugar ondethey are given the information in the FreeBSD ports scenario). elesrecebem a informação no cenário portas FreeBSD).6. 6. The source code for the program is compiled. O código fonte para oprograma é compilado. In effect, we change to the directory where thesource was Com efeito, podemos mudar para o diretório onde a fonte eraunpacked and do descompactado e fazermake fazer—the program's own make file has the necessary information to build theprogram. -O próprio arquivo make do programa tem as informaçõesnecessárias para a construção do programa.7. 7. We now have a compiled version of the program. Temos agora umaversão compilada do programa. If we wish, we can test it now; when wefeel confident about Se quisermos, podemos testá-lo agora, quando se

Page 29: 139920579 Versao Traduzida de Book

sentir confiante sobrethe program, we can type *make install* . o programa, podemos digitar*make install.* This will cause the program and any supporting files itneeds to be Isso vai fazer com que o programa e os arquivos de suporteque ele precisa sercopied into the correct location; an entry is also made into a packagedatabase, so that the port can easily be copiado para a localizaçãocorrecta; uma entrada também é feita numa base de dados de pacote, demodo que a porta pode ser facilmenteuninstalled later if we change our mind about it. desinstalado maistarde, se mudarmos de idéia sobre isso.Now I think you'll agree that's rather impressive for a four linescript! Agora eu acho que você vai concordar que é bastanteimpressionante para um script de linha de quatro!The secret lies in the last line, which tells O segredo está na últimalinha, que contamake fazerto look in the system makefile called olhar no makefile sistema chamadobsd.port.mk bsd.port.mk. . It's easy to É fáciloverlook this line, but this is where all the clever stuff comesfrom—someone has written a makefile that tells ignorar esta linha, maseste é o lugar onde todas as coisas inteligente vem, alguém escreveu ummakefile que dizmake fazerto do all the things above (plus a couple of other things I didn'tmention, including handling any errors that may fazer todas as coisasacima (mais um par de outras coisas que eu não mencionei, incluindomanipulação quaisquer erros que possamoccur) and anyone can get access to that just by putting a single linein their own make file! ocorrer) e qualquer pessoa pode ter acesso a queapenas colocando uma única linha em seu próprio arquivo make!If you want to have a look at these system makefiles, they're in Se vocêquiser ter um olhar para esses sistema makefiles, eles estão em/usr/share/mk / Usr / share / mk, but it's probably best to wait until , Mas provavelmente é melhoresperar até queyou've had a bit of practice with makefiles, as they are verycomplicated (and if you do look at them, make sure you você teve umpouco de prática com makefiles, como eles são muito complicadas (e sevocê olhar para eles, certifique-sehave a flask of strong coffee handy!) ter um frasco de café forte calhar!)*5.5.5.* *5.5.5.* *More advanced uses of* *Usos mais avançados do**make* *fazer*Make Fazeris a very powerful tool, and can do much more than the simple exampleabove shows. é uma ferramenta muito poderosa, e pode fazer muito mais doque o simples exemplo acima mostra. Unfortunately, there areInfelizmente, existemseveral different versions of várias versões diferentes demake fazer, and they all differ considerably. , E todos eles diferemconsideravelmente. The best way to learn what they can do is A melhormaneira de saber o que eles podem fazer éprobably to read the documentation—hopefully this introduction will havegiven you a base from which you can do provavelmente para ler adocumentação do esperançosamente esta introdução terá dado uma base apartir da qual você pode fazerthis. isto.The version of make that comes with FreeBSD is the *Berkeley make* ;

Page 30: 139920579 Versao Traduzida de Book

there is a tutorial for it in A versão da marca que vem com o FreeBSD éo *Berkeley fazer,* há um tutorial para ele em/usr/share/doc/psd/12.make / Usr/share/doc/psd/12.make. . To view it, do Para vê-lo, fazê-% %*zmore paper.ascii.gz* *zmore paper.ascii.gz*in that directory. nesse diretório./20/ /20/------------------------------------------------------------------------*Page 29* *Page 29*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/Many applications in the ports use *GNU make* , which has a very goodset of “info” pages. Muitas aplicações nas portas de usar *o GNU make,*que tem um bom conjunto de "Info" páginas. If you have installed any Sevocê tiver instalado qualquerof these ports, *GNU make* will automatically have been installed asdestas portas, *GNU make* será automaticamente ter sido instalado comogmake gmake. . It's also available as a port and package Também está disponívelcomo um porto e um pacotein its own right. em seu próprio direito.To view the info pages for *GNU make* , you will have to edit the Paravisualizar as páginas de informação para *GNU make,* você terá que editar odir dirfile in the arquivo no/usr/local/info / Usr / local / infodirectory to add diretório para adicionaran entry for it. uma entrada para ele. This involves adding a line likeIsso envolve a adição de uma linha como* Make: (make). * Marca: (fazer).The GNU Make utility. O GNU Make utilidade.to the file. para o arquivo. Once you have done this, you can type*info* and then select make from the menu (or in *Emacs* , do *Ch*Depois de ter feito isso, você pode digitar *informações* e, em seguida,escolha fazer a partir do menu (ou no *Emacs,* fazer *Ch**i* ). *i).**5.6.* *5.6.* *Debugging* *Depuração**5.6.1.* *5.6.1.* *The Debugger* *O Debugger*The debugger that comes with FreeBSD is called O depurador que vem com oFreeBSD é chamadogdb gdb( *GNU debugger* ). *(Depurador GNU).* You start it up by typing Vocêiniciá-lo digitando% %*gdb /progname/* *gdb /nomeprog/*although most people prefer to run it inside *Emacs* . embora a maioriadas pessoas preferem executá-lo dentro *do Emacs.* You can do this by:Você pode fazer isso:*Mx gdb RET /progname/ RET* *Mx gdb /nomeprog/ RET RET*Using a debugger allows you to run the program under more controlledcircumstances. Usando um depurador permite que você execute o programaem circunstâncias mais controladas. Typically, you can step Normalmente,você pode entrarthrough the program a line at a time, inspect the value of variables,change them, tell the debugger to run up to a através do programa de umalinha de cada vez, inspecionar o valor de variáveis, alterá-los, dizerque o depurador para correr até acertain point and then stop, and so on. certo ponto e depois parar, eassim por diante. You can even attach to a program that's already

Page 31: 139920579 Versao Traduzida de Book

running, or load a core file to Você pode até mesmo anexar a um programaque já está em execução, ou carregar um arquivo de núcleo parainvestigate why the program crashed. investigar por que o programatravou. It's even possible to debug the kernel, though that's a littletrickier than the user É ainda possível depurar o kernel, no entanto,que é um pouco mais complicado do que o usuárioapplications we'll be discussing in this section. aplicações vamosdiscutir nesta seção.gdb gdbhas quite good on-line help, as well as a set of info pages, so thissection will concentrate on a few of the basic tem muito bom de ajudaon-line, bem como um conjunto de páginas de informações, por isso estaseção irá concentrar-se em alguns dos básicoscommands. comandos.Finally, if you find its text-based command-prompt style off-putting,there's a graphical front-end for it xxgdb Finalmente, se você encontraro seu estilo baseado em texto de prompt de comando off-putting, há umfront-end gráfico para ele xxgdb(../../ports/devel.html) in the ports collection. (.. /.. / Ports /devel.html) na coleção de ports.This section is intended to be an introduction to using Esta secçãopretende ser uma introdução ao usogdb gdband does not cover specialised topics such as debugging e não cobreassuntos especializados, tais como a depuraçãothe kernel. o kernel./21/ /21/------------------------------------------------------------------------*Page 30* *Page 30*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*5.6.2.* *5.6.2.* *Running a program in the debugger* *Executando umprograma no depurador*You'll need to have compiled the program with the Você precisa tercompilado o programa com a-g -Goption to get the most out of using opção para tirar o máximo proveitodo uso degdb gdb. . It will work without, Ele vai trabalhar fora,but you'll only see the name of the function you're in, instead of thesource code. mas você só vai ver o nome da função que você está dentro,em vez de o código fonte. If you see a line like: Se você ver uma linhacomo:... ... (no debugging symbols found) ... (Sem símbolos de depuraçãoencontrado) ...when quandogdb gdbstarts up, you'll know that the program wasn't compiled with theinicia-se, você vai saber que o programa não foi compilado com o-g -Goption. opção.At the Nogdb gdbprompt, type *break main* . prompt, digite *quebrar principal.* Thiswill tell the debugger to skip over the preliminary set-up code in theIsto irá dizer o depurador para pular o código set-up preliminar noprogram and start at the beginning of your code. programa e começar noinício do seu código. Now type *run* to start the program—it will startat the beginning of Agora digite *correr* para iniciar o programa, ele

Page 32: 139920579 Versao Traduzida de Book

vai começar no início dothe set-up code and then get stopped by the debugger when it calls ocódigo de set-up e, em seguida, ficar parado pelo depurador quando elechamamain() main (). . (If you've ever wondered where (Se você já se perguntou ondemain() main ()gets called from, now you know!). é chamado de, agora você sabe!).You can now step through the program, a line at a time, by pressingAgora você pode percorrer o programa, uma linha de cada vez, pressionandon n. . If you get to a function call, you can step into Se você chegar auma chamada de função, você pode entrar emit by pressing lo premindos s. . Once you're in a function call, you can return from stepping into afunction call by pressing Uma vez que você estiver em uma chamada defunção, você pode retornar de pisar em uma chamada de função, premindof f. . You Vocêcan also use Também é possível utilizarup para cimaand edown para baixoto take a quick look at the caller. para dar uma olhada rápida nointerlocutor.Here's a simple example of how to spot a mistake in a program with Aquiestá um exemplo simples de como identificar um erro em um programa comgdb gdb. . This is our program (with a deliberate Este é o nosso programa (coma deliberadamistake): erro):#include < stdio.h > # Include <stdio.h>int bazz(int anint); int bazz (int anInt);main() { main () {int i; int i;printf("This is my program\n"); printf ("Este é o meu programa \ n");bazz(i); bazz (i);return 0; retornar 0;} }int bazz(int anint) { int bazz (int anInt) {printf("You gave me %d\n", anint); printf ("Você me deu% d \ n", anInt);return anint; voltar anInt;} }This program sets i to be Este programa define i ser5 5and passes it to a function e passa para uma funçãobazz() bazz ()which prints out the number we gave it. que imprime o número que deu.When we compile and run the program we get Quando compilar e executar oprograma de chegarmos% %*cc -g -o temp temp.c* *cc-g-o temp temp.c*% %*./temp* *. / Temp*This is my program Este é o meu programaanint = 4231 anInt = 4231/22/ /22/------------------------------------------------------------------------*Page 31* *Page 31*

Page 33: 139920579 Versao Traduzida de Book

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/That wasn't what we expected! Isso não era o que esperávamos! Time tosee what's going on! Tempo para ver o que está acontecendo!% %*gdb temp* *gdb temperatura*GDB is free software and you are welcome to distribute copies of it GDBé um software livre e você está convidado a distribuir cópias do mesmounder certain conditions; type "show copying" to see the conditions. sobcertas condições, tipo "show copiar" para ver as condições.There is absolutely no warranty for GDB; type "show warranty" fordetails. Não há absolutamente nenhuma garantia para o GDB, tipo "show degarantia" para obter detalhes.GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free SoftwareFoundation, Inc. GDB 4.13 (i386-unknown-freebsd) Copyright 1994 FreeSoftware Foundation, Inc.(gdb) *break main* /Skip the set-up code/ (Gdb) *break principal* /Skipo código set-up/Breakpoint 1 at 0x160f: file temp.c, line 9. Breakpoint 1 em 0x160f:file temp.c, linha 9./gdb/ /gdb//puts breakpoint at/ /coloca ponto de interrupção na//main()/ /main ()/(gdb) *run* /Run as far as/ (Gdb) /*Run* Run, tanto quanto//main()/ /main ()/Starting program: /home/james/tmp/temp /Program starts running/ Programade partida: / home / james / tmp / /Programa de/ temperatura /começa afuncionar/Breakpoint 1, main () at temp.c:9 Breakpoint 1 main () em temp.c: 9/gdb/ /gdb//stops at/ /paradas em//main()/ /main ()/(gdb) *n* /Go to next line/ (Gdb) *n* /Ir para a próxima linha/This is my program /Program prints out/ Este é o meu /programa/ programa/imprime/(gdb) *s* /step into/ (Gdb) *s* /passo para//bazz()/ /bazz ()/bazz (anint=4231) at temp.c:17 bazz (anInt = 4,231) no temp.c: 17/gdb/ /gdb//displays stack frame/ /apresenta quadro de pilha/(gdb) (Gdb)Hang on a minute! Espere um minuto! How did anint get to be Como anIntchegar a ser4231 4231? ? Didn't we set it to be Não podemos defini-lo para ser5 5in emmain() main ()? ? Let's move up to Vamos passar paramain() main ()and ehave a look. dar uma olhada.(gdb) *up* /Move up call stack/ (Gdb) *para cima* /Mover para cima pilhade chamadas/#1 0x1625 in main () at temp.c:11 � 1 0x1625 em main () em temp.c: 11/gdb/ /gdb//displays stack frame/ /apresenta quadro de pilha/(gdb) *pi* /Show us the value of i/ (Gdb) *pi* /Mostra-nos o valor de i/$1 = 4231 $ 1 = 4231/gdb/ /gdb/

Page 34: 139920579 Versao Traduzida de Book

/displays/ /monitores//4231/ /4231/Oh dear! Oh dear! Looking at the code, we forgot to initialise i.Olhando para o código, que se esqueceu de inicializar i. We meant to putQuisemos colocar/.../ /.../main() { main () {int i; int i;i = 5; i = 5;printf("This is my program\n"); printf ("Este é o meu programa \ n");/.../ /.../but we left the mas deixamos ai=5; i = 5;line out. saída de linha. As we didn't initialise i, it had whatevernumber happened to be in that area of memory Como não inicializar i, quetinha o número que passou a ser na área de memóriawhen the program ran, which in this case happened to be quando oprograma executado, o qual, neste caso, por acaso4231 4231. ./23/ /23/------------------------------------------------------------------------*Page 32* *Page 32*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*Note:* *Nota:*gdb gdbdisplays the stack frame every time we go into or out of a function,even if we're using mostra o quadro de pilha cada vez que vamos paradentro ou fora de uma função, mesmo se estiver usandoup para cimaand edown para baixoto amove around the call stack. mover a pilha de chamadas. This shows thename of the function and the values of its arguments, which helps usIsso mostra o nome da função e os valores de seus argumentos, o que nosajuda akeep track of where we are and what's going on. manter o controle deonde estamos eo que está acontecendo. (The stack is a storage area wherethe program stores (A pilha é uma área de armazenamento, onde o programaarmazenainformation about the arguments passed to functions and where to go whenit returns from a function call). informações sobre os argumentospassados ��para as funções e para onde ir, quando ele retorna de umachamada de função).*5.6.3.* *5.6.3.* *Examining a core file* *Examinando um arquivo de núcleo*A core file is basically a file which contains the complete state of theprocess when it crashed. Um arquivo de núcleo é basicamente um arquivoque contém o estado completo do processo quando ele caiu. In “the goodold Em "o bom e velhodays”, programmers had to print out hex listings of core files and sweatover machine code manuals, but now life is a dia ", os programadorestinham que imprimir listagens hexadecimais dos arquivos centrais e suorsobre manuais de código de máquina, mas agora a vida é umbit easier. pouco mais fácil. Incidentally, under FreeBSD and other4.4BSD systems, a core file is called Aliás, no FreeBSD e outrossistemas 4.4BSD, um arquivo de núcleo é chamado/progname/ .core /nomeprog./ núcleoinstead of em vez de

Page 35: 139920579 Versao Traduzida de Book

just justocore núcleo, to make it clearer which program a core file belongs to. , Paratorná-la mais clara, que programa um arquivo de núcleo pertence.To examine a core file, start up Para examinar um arquivo de núcleo,start upgdb gdbin the usual way. da maneira usual. Instead of typing Em vez de digitarbreak quebraror ourun correr, type , Tipo(gdb) *core /progname/ .core* (Gdb) */nomeprog/ núcleo. Núcleo*If you're not in the same directory as the core file, you'll have to do*dir /path/to/core/file* first. Se você não estiver no mesmo diretórioque o arquivo de núcleo, você vai ter que fazer *dir / path / to / core/ arquivo* primeiro.You should see something like this: Você deve ver algo como isto:% %*gdb a.out* *gdb a.out*GDB is free software and you are welcome to distribute copies of it GDBé um software livre e você está convidado a distribuir cópias do mesmounder certain conditions; type "show copying" to see the conditions. sobcertas condições, tipo "show copiar" para ver as condições.There is absolutely no warranty for GDB; type "show warranty" fordetails. Não há absolutamente nenhuma garantia para o GDB, tipo "show degarantia" para obter detalhes.GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free SoftwareFoundation, Inc. GDB 4.13 (i386-unknown-freebsd) Copyright 1994 FreeSoftware Foundation, Inc.(gdb) *core a.out.core* (Gdb) *núcleo a.out.core*Core was generated by 'a.out'. Núcleo foi gerado por «a.out.Program terminated with signal 11, Segmentation fault. Programa terminoucom sinal de 11, Segmentation fault.Cannot access memory at address 0x7020796d. Não consegue acessar amemória no endereço 0x7020796d.#0 0x164a in bazz (anint=0x5) at temp.c:17 # 0 0x164a em bazz (anInt =0x5) ao temp.c: 17(gdb) (Gdb)In this case, the program was called Neste caso, o programa foi chamadoa.out a.out, so the core file is called , Então o arquivo de núcleo é chamadoa.out.core a.out.core. . We can see that the program Podemos ver que o programacrashed due to trying to access an area in memory that was not availableto it in a function called caiu devido a tentar aceder a uma área namemória que não estava disponível para ele em uma função chamadabazz bazz. .Sometimes it's useful to be able to see how a function was called, asthe problem could have occurred a long way up Às vezes é útil para sercapaz de ver como a função foi chamada, pois o problema pode terocorrido um longo caminho atéthe call stack in a complex program. a pilha de chamadas em um programacomplexo. The Obt btcommand causes causas de comandogdb gdbto print out a back-trace of the call stack: para imprimir um back-traçoda pilha de chamadas:

Page 36: 139920579 Versao Traduzida de Book

(gdb) *bt* (Gdb) *bt*#0 0x164a in bazz (anint=0x5) at temp.c:17 # 0 0x164a em bazz (anInt =0x5) ao temp.c: 17#1 0xefbfd888 in end () � 1 0xefbfd888 em end ()/24/ /24/------------------------------------------------------------------------*Page 33* *Page 33*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/#2 0x162c in main () at temp.c:11 � 2 0x162c em main () em temp.c: 11(gdb) (Gdb)The Oend() end ()function is called when a program crashes; in this case, the função échamada quando um programa falhar, neste caso, obazz() bazz ()function was called from função foi chamada demain() main (). .*5.6.4.* *5.6.4.* *Attaching to a running program* *Anexar a um programaem execução*One of the neatest features about Uma das mais puras características sobregdb gdbis that it can attach to a program that's already running. é que podeanexar a um programa que já está em execução. Of course, that É claro, queassumes you have sufficient permissions to do so. assume que você tempermissões suficientes para fazê-lo. A common problem is when you arestepping through a program Um problema comum é quando você estápercorrendo um programathat forks, and you want to trace the child, but the debugger will onlylet you trace the parent. que os garfos, e você deseja rastrear acriança, mas o depurador só vai deixar você seguir o pai.What you do is start up another O que você faz é iniciar outrogdb gdb, use , Utilizarps psto find the process ID for the child, and do para encontrar o ID doprocesso para a criança, e fazer(gdb) *attach /pid/* (Gdb) *anexar /pid/*in emgdb gdb, and then debug as usual. E, em seguida, depurar, como de costume.“That's all very well,” you're probably thinking, “but by the time I'vedone that, the child process will be over the "Isso é tudo muito bem",você provavelmente está pensando, "mas com o tempo eu fiz isso, oprocesso filho vai ser sobre ohill and far away”. colina e longe ". Fear not, gentle reader, here'show to do it (courtesy of the Não temas, gentil leitor, aqui está comofazê-lo (cortesia dogdb gdbinfo pages): páginas info):/.../ /.../if ((pid = fork()) < 0) /* _Always_ check this */ if ((pid = fork ())<0) / * _sempre_ verificar isso * /error(); erro ();else if (pid == 0) { /* child */ else if (pid == 0) {/ * filho * /int PauseMode = 1; int PAUSEMODE = 1;while (PauseMode) while (PAUSEMODE)sleep(10); /* Wait until someone attaches to us */ sleep (10); / *Espere até que alguém atribui a nós * /

Page 37: 139920579 Versao Traduzida de Book

/.../ /.../} else { /* parent */ } Else {/ * pai * //.../ /.../Now all you have to do is attach to the child, set PauseMode to Agoratudo que você tem a fazer é ligar para a criança, para definir PAUSEMODE0 0, and wait for the , E esperar que osleep() sleep ()call to return! chamar para voltar!/25/ /25/------------------------------------------------------------------------*Page 34* *Page 34*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*5.7.* *5.7.* *Using Emacs as a Development Environment* *Usando Emacscomo um ambiente de desenvolvimento**5.7.1.* *5.7.1.* *Emacs* *Emacs*Unfortunately, Unix systems don't come with the kind of Infelizmente, ossistemas Unix não vêm com o tipo deeverything-you-ever-wanted-and-lots-more-you-didn't-in-one-gigantic-packageintegrated development desenvolvimento integradotudo-que-nunca-quis-e-muito-mais-você-não-em-um-gigantesco-packageenvironments that other systems have. ambientes que outros sistemas de ter.7 7However, it is possible to set up your own environment. No entanto, épossível criar seu próprio ambiente. It may not be as Pode não ser tãopretty, and it may not be quite as integrated, but you can set it up theway you want it. bonita, e ele pode não ser tão integrado, mas você podeconfigurá-lo da maneira que você quiser. And it's free. E é grátis. Andyou have the E você tem asource to it. fonte a ele.The key to it all is Emacs. A chave para tudo isso é Emacs. Now thereare some people who loathe it, but many who love it. Agora, existemalgumas pessoas que detestá-lo, mas muitos que a amam. If you're one ofthe Se você é um dosformer, I'm afraid this section will hold little of interest to you.primeiro, eu tenho medo desta seção irá realizar pouco de seu interesse.Also, you'll need a fair amount of memory to run Além disso, você vaiprecisar de uma boa quantidade de memória para rodarit—I'd recommend 8MB in text mode and 16MB in X as the bare minimum toget reasonable performance. que-eu recomendo 8MB no modo texto e 16MB deX como o mínimo necessário para obter um desempenho razoável.Emacs is basically a highly customisable editor—indeed, it has beencustomised to the point where it's more like an Emacs é basicamente umaltamente personalizável editor de fato, ele foi customizado para oponto onde é mais como umoperating system than an editor! sistema operacional de um editor! Manydevelopers and sysadmins do in fact spend practically all their timeworking Muitos desenvolvedores e administradores de sistemas que, defacto, gastar praticamente todo o seu tempo de trabalhoinside Emacs, leaving it only to log out. dentro do Emacs, deixando-oapenas para sair.It's impossible even to summarise everything Emacs can do here, but hereare some of the features of interest to É impossível, mesmo para resumirtudo o Emacs pode fazer aqui, mas aqui estão algumas das característicasde interesse paradevelopers: desenvolvedores:• •Very powerful editor, allowing search-and-replace on both strings andregular expressions (patterns), jumping to Editor muito poderoso,

Page 38: 139920579 Versao Traduzida de Book

permitindo a busca e substituição em ambas as strings e expressõesregulares (padrões), saltando parastart/end of block expression, etc, etc. início / fim de expressãobloco, etc, etc• •Pull-down menus and online help. Menus pull-down e ajuda on-line.• •Language-dependent syntax highlighting and indentation. Destaque desintaxe dependentes do idioma e recuo.• •Completely customisable. Completamente customizável.• •You can compile and debug programs within Emacs. Você pode compilar edepurar programas dentro de Emacs.• •On a compilation error, you can jump to the offending line of sourcecode. Em um erro de compilação, você pode saltar para a linha ofensivado código-fonte.• •Friendly-ish front-end to the Amigável-ish front-end para oinfo Informaçõesprogram used for reading GNU hypertext documentation, including theprograma utilizado para a leitura de documentação GNU hipertexto,incluindo adocumentation on Emacs itself. documentação sobre si Emacs.• •Friendly front-end to Amigável front-end paragdb gdb, allowing you to look at the source code as you step through yourprogram. , O que lhe permite olhar o código fonte que você pisa atravésde seu programa.• •You can read Usenet news and mail while your program is compiling. Vocêpode ler notícias e e-mail Usenet enquanto o programa está compilando.And doubtless many more that I've overlooked. E, sem dúvida, muitos maisque eu tenha esquecido.Emacs can be installed on FreeBSD using the Emacs port(../../ports/editors.html). Emacs pode ser instalado no FreeBSD usando aporta Emacs (.. /.. / Ports / editors.html).Once it's installed, start it up and do *Ch t* to read an Emacstutorial—that means hold down the *control* key, press Uma vezinstalado, iniciá-lo e *fazê-Ch t* para ler um tutorial Emacs, quesignifica manter pressionada a tecla *de controle,* pressione*h* , let go of the *control* key, and then press *t* . *h,* solte atecla Ctrl *e,* em seguida, prima *t.* (Alternatively, you can you usethe mouse to select Emacs Tutorial (Alternativamente, você pode usar omouse para selecionar Emacs Tutorialfrom the Help menu). a partir do menu Ajuda)./26/ /26/------------------------------------------------------------------------*Page 35* *Page 35*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/Although Emacs does have menus, it's well worth learning the keybindings, as it's much quicker when you're Embora Emacs tem menus, valea pena aprender os atalhos de teclado, como é muito mais rápido quandovocê estáediting something to press a couple of keys than to try and find themouse and then click on the right place. edição algo para pressionar umpar de chaves do que tentar encontrar o mouse e clique no lugar certo.

Page 39: 139920579 Versao Traduzida de Book

And, E,when you're talking to seasoned Emacs users, you'll find they oftencasually throw around expressions like “ quando você está falando com osusuários de Emacs experientes, você vai encontrar muitas vezescasualmente jogar em torno de expressões como "Mx Mxreplace-s RET foo RET bar RET substituir-s foo RET RET RET bar” so it's useful to know what they mean. "Por isso é útil para saber oque eles significam. And in any case, Emacs has far too E, em qualquercaso, tem muito Emacsmany useful functions for them to all fit on the menu bars. muitasfunções úteis para eles todos se encaixam nas barras de menu.Fortunately, it's quite easy to pick up the key-bindings, as they'redisplayed next to the menu item. Felizmente, é muito fácil de pegar ascombinações de teclas, como eles são exibidos ao lado do item de menu.My advice is to Meu conselho éuse the menu item for, say, opening a file until you understand how itworks and feel confident with it, then try doing usar o item de menu,por exemplo, abrir um arquivo até que você entenda como ele funciona ese sentir confiante com ele, em seguida, tentar fazerCx Cf. Cx Cf. When you're happy with that, move on to another menucommand. Quando você está feliz com isso, mudar para outro comando de menu.If you can't remember what a particular combination of keys does, selectDescribe Key from the Help menu and Se você não consegue lembrar o queuma determinada combinação de teclas que, selecione Descreva chave nomenu Ajuda etype it in—Emacs will tell you what it does. digite-a-Emacs irádizer-lhe o que ele faz. You can also use the Command Apropos menu itemto find out all the Você também pode usar o item de menu Commandpropósito de descobrir tudo ocommands which contain a particular word in them, with the key bindingnext to it. comandos que contenham uma determinada palavra em si, com aligação de chave ao lado dele.By the way, the expression above means hold down the Meta key, press x,release the Meta key, type *replace-s* By the way, a expressão acimasignifica manter pressionada a tecla Meta, pressione x, solte a teclaMeta, tipo *substituir-s*(short for (Abreviação dereplace-string replace-string—another feature of Emacs is that you can abbreviate commands), pressthe return key, -Outra característica do Emacs é que você pode abreviarcomandos), pressione a tecla de retorno,type *foo* (the string you want replaced), press the return key, typebar (the string you want to replace tipo *foo* (a seqüência que vocêdeseja substituir), pressione a tecla de retorno, tipo de bar (aseqüência que você deseja substituirfoo foowith) and com) epress return again. pressione voltar. Emacs will then do thesearch-and-replace operation you've just requested. Emacs, então, fazero busca e substituição operação que acabou solicitado.If you're wondering what on earth the Meta key is, it's a special keythat many Unix workstations have. Se você está se perguntando o quediabos a chave Meta é, é uma chave especial que muitas estações detrabalho Unix tem.Unfortunately, PC's don't have one, so it's usually the *alt* key (or ifyou're unlucky, the escape key). Infelizmente, PC não tiver um, por issoé geralmente a *tecla* Alt (ou se você não está com sorte, a chave deescape).Oh, and to get out of Emacs, do Ah, e para sair do Emacs, fazer

Page 40: 139920579 Versao Traduzida de Book

Cx Cc Cx Cc(that means hold down the control key, press x, press c and release the(O que significa manter pressionada a tecla de controle, pressione x,pressione e solte o ccontrol key). chave de controle). If you have any unsaved files open,Emacs will ask you if you want to save them. Se você tem quaisquerarquivos não salvos abertos, Emacs vai perguntar se você quer salvá-los.(Ignore the bit in the (Ignore o bit nodocumentation where it says documentação onde dizCz Czis the usual way to leave Emacs—that leaves Emacs hanging around in theé a maneira usual de deixar Emacs, que deixa Emacs pendurado em torno dobackground, and is only really useful if you're on a system whichdoesn't have virtual terminals). fundo, e só é realmente útil se vocêestiver em um sistema que não tem terminais virtuais).*5.7.2.* *5.7.2.* *Configuring Emacs* *Configurando o Emacs*Emacs does many wonderful things; some of them are built in, some ofthem need to be configured. Emacs faz muitas coisas maravilhosas, algunsdeles são construídos, alguns deles precisam ser configurados.Instead of using a proprietary macro language for configuration, Emacsuses a version of Lisp specially adapted for Em vez de usar umalinguagem de macro proprietário para configuração, Emacs usa uma versãodo Lisp especialmente adaptados paraeditors, known as Emacs Lisp. editores, conhecidos como Emacs Lisp. Thiscan be quite useful if you want to go on and learn something like CommonLisp, Isso pode ser muito útil se você quer seguir em frente e aprenderalgo como Lisp comum,as it's considerably smaller than Common Lisp (although still quitebig!). como é consideravelmente menor do que Lisp Comum (embora aindamuito grande!).The best way to learn Emacs Lisp is to download the Emacs Tutorial Amelhor maneira de aprender Emacs Lisp é baixar o Tutorial Emacs(ftp://prep.ai.mit.edu:pub/gnu/elisp-manual-19-2.4.tar.gz)(Ftp://prep.ai.mit.edu:pub/gnu/elisp-manual-19-2.4.tar.gz)However, there's no need to actually know any Lisp to get started withconfiguring Emacs, as I've included a sample No entanto, não hánecessidade de realmente conhecer qualquer Lisp para começar aconfigurar o Emacs, como já incluiu uma amostra.emacs . Emacsfile, which should be enough to get you started. arquivo, que deve sersuficiente para você começar. Just copy it into your home directory andrestart Emacs if Basta copiá-lo em seu diretório home e reinicie o Emacs seit's already running; it will read the commands from the file and(hopefully) give you a useful basic setup. ele já está em execução, eleirá ler os comandos do arquivo e (espero) dar-lhe uma configuraçãobásica útil./27/ /27/------------------------------------------------------------------------*Page 36* *Page 36*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*5.7.3.* *5.7.3.* *A sample* *Uma amostra**.emacs* *. Emacs**file* *arquivo*Unfortunately, there's far too much here to explain it in detail;however there are one or two points worth mentioning. Infelizmente, nãoé demais aqui para explicar em detalhes, mas há um ou dois pontos quemerecem destaque.• •Everything beginning with a Tudo começa com um

Page 41: 139920579 Versao Traduzida de Book

; ;is a comment and is ignored by Emacs. é um comentário e é ignorado peloEmacs.• •In the first line, the Na primeira linha, o-*- Emacs-Lisp -*- - * - Emacs-Lisp - * -is so that we can edit the É assim que podemos editar o.emacs . Emacsfile itself within Emacs and get all apresentar-se dentro de Emacs eobter todasthe fancy features for editing Emacs Lisp. os recursos especiais paraedição Emacs Lisp. Emacs usually tries to guess this based on thefilename, and may not get Emacs geralmente tenta adivinhar isso com baseno nome do arquivo, e não pode ficarit right for o certo para.emacs . Emacs. .• •The tab key is bound to an indentation function in some modes, so whenyou press the tab key, it will indent the A tecla TAB é obrigado a umafunção de recuo em alguns modos, então quando você pressionar a teclatab, ele vai recuar ocurrent line of code. linha de código atual. If you want to put a tabcharacter in whatever you're writing, hold the control key down while Sevocê quiser colocar um caractere de tabulação em que você estáescrevendo, segure a tecla Ctrl pressionada enquantoyou're pressing the tab key. você está pressionando a tecla tab.• •This file supports syntax highlighting for C, C++, Perl, Lisp andScheme, by guessing the language from the Este arquivo suporta destaquede sintaxe para C, C + +, Perl, Lisp e Scheme, por adivinhar a linguagem dofilename. nome do arquivo.• •Emacs already has a pre-defined function called Emacs já tem uma funçãopré-definida chamadanext-error erro-next. . In a compilation output window, this allows you to Em uma janela desaída de compilação, isso permite que vocêmove from one compilation error to the next by doing mover-se de um errode compilação para o próximo, fazendoMn Mn; we define a complementary function, , Definimos uma função complementar,previous-error erro anterior, that allows you to go to a previous error by doing , Que permite quevocê vá a um erro anterior, fazendoMp Mp. . The nicest feature of all is that A melhor característica de tudo é queCc CcCc Ccwill open up the source file in which the error occurred and jump to theappropriate line. vai abrir o arquivo de origem em que o erro ocorreu esaltar para a linha apropriada.• •We enable Emacs's ability to act as a server, so that if you're doingsomething outside Emacs and you want to edit Nós permitimos a capacidadedo Emacs para atuar como um servidor, de modo que se você está fazendoalgo fora Emacs e que deseja editara file, you can just type in um arquivo, você pode simplesmente digitar% %*emacsclient /filename/* *emacsclient /nome/*

Page 42: 139920579 Versao Traduzida de Book

and then you can edit the file in your Emacs! e, em seguida, você podeeditar o arquivo em seu Emacs!8 8*Example 5-1.* *Exemplo 5-1.* *A sample* *Uma amostra**.emacs* *. Emacs**file* *arquivo*;; -*-Emacs-Lisp-*- ,, - *-Emacs-Lisp-* -;; This file is designed to be re-evaled; use the variable first-time ;;Este arquivo foi projetada para ser re-evaled; usar o primeiro tempovariável;; to avoid any problems with this. ,, Para evitar quaisquer problemascom isso.(defvar first-time t (Defvar primeiro tempo t"Flag signifying this is the first time that .emacs has been evaled")"Bandeira significando esta é a primeira vez que isso. Emacs foi evaled");; Meta ;; Meta(global-set-key "\M- " 'set-mark-command) (Global-set-key "\ M-"'set-mark-comando)(global-set-key "\M-\Ch" 'backward-kill-word) (Global-set-key "\ M \ Ch""backward-kill-word)(global-set-key "\M-\Cr" 'query-replace) (Global-set-key "\ M \ Cr '"query-replace)(global-set-key "\Mr" 'replace-string) (Global-set-key "\ Mr"'substituir-string)(global-set-key "\Mg" 'goto-line) (Global-set-key "\ Mg" 'Goto-line)/28/ /28/------------------------------------------------------------------------*Page 37* *Page 37*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/(global-set-key "\Mh" 'help-command) (Global-set-key "\ mh" 'comando help);; Function keys As teclas de função;;(global-set-key [f1] 'manual-entry) (Global-set-key [F1] "entrada manual)(global-set-key [f2] 'info) (Global-set-key [f2] 'info)(global-set-key [f3] 'repeat-complex-command) (Global-set-key [f3]'repeat-complexo de comando)(global-set-key [f4] 'advertised-undo) (Global-set-key [f4]'anunciado-desfazer)(global-set-key [f5] 'eval-current-buffer) (Global-set-key [f5]'eval-atual-buffer)(global-set-key [f6] 'buffer-menu) (Global-set-key "-menu buffer [F6])(global-set-key [f7] 'other-window) (Global-set-key [F7] 'outro-janela)(global-set-key [f8] 'find-file) ('Encontrar-arquivo global-set-key [F8])(global-set-key [f9] 'save-buffer) (Global-set-key [F9] 'save-buffer)(global-set-key [f10] 'next-error) ('Erro próximo-global-set-key [F10])(global-set-key [f11] 'compile) (Global-set-key [f11] 'compilação)(global-set-key [f12] 'grep) (Global-set-key [f12] 'grep)(global-set-key [C-f1] 'compile) (Global-set-key [C-f1] 'compilação)(global-set-key [C-f2] 'grep) (Global-set-key [C-f2] 'grep)(global-set-key [C-f3] 'next-error) (Global-set-key [C-f3] 'erro próxima)(global-set-key [C-f4] 'previous-error) (Global-set-key [C-f4]'anterior-erro)(global-set-key [C-f5] 'display-faces) (Global-set-key [C-F5]'display-faces)(global-set-key [C-f8] 'dired) (Global-set-key [C-f8] 'dired)(global-set-key [C-f10] 'kill-compilation) (Global-set-key [C-f10]'matar-compilação);; Keypad bindings Ligações de teclado;;(global-set-key [up] "\Cp") (Global-set-key [up] "\ Cp")(global-set-key [down] "\Cn") (Global-set-key [para baixo] "\ Cn")

Page 43: 139920579 Versao Traduzida de Book

(global-set-key [left] "\Cb") (Global-set-key [left] "\ Cb")(global-set-key [right] "\Cf") (Global-set-key [right] "\ Cf")(global-set-key [home] "\Ca") (Global-set-key [casa] "\ Ca")(global-set-key [end] "\Ce") (Global-set-key [final] "\ Ce")(global-set-key [prior] "\Mv") (Global-set-key [antes] "\ Mv")(global-set-key [next] "\Cv") (Global-set-key [próximo] "\ Cv")(global-set-key [C-up] "\M-\Cb") (Global-set-key [C-up] "\ M \ Cb")(global-set-key [C-down] "\M-\Cf") (Global-set-key [C-down] "\ M \ Cf")(global-set-key [C-left] "\Mb") (Global-set-key [C-esquerda] "\ Mb")(global-set-key [C-right] "\Mf") (Global-set-key [C-direita] "\ mf")(global-set-key [C-home] "\M- < ") (Global-set-key [C-home] "\ M-<")(global-set-key [C-end] "\M- > ") (Global-set-key [C-end] "\ M->")(global-set-key [C-prior] "\M- < ") (Global-set-key [C-anterior] "\ M-<")(global-set-key [C-next] "\M- > ") (Global-set-key [C-next] "\ M->");; Mouse ;; Rato(global-set-key [mouse-3] 'imenu) (Global-set-key [mouse-3] 'iMenu);; Misc ;; Miscelânea/29/ /29/------------------------------------------------------------------------*Page 38* *Page 38*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/(global-set-key [C-tab] "\Cq\t") ; Control tab quotes a tab.(Global-set-key [C-guia] "\ Cq \ t"); guia Controle cita uma guia.(setq backup-by-copying-when-mismatch t) (Setq debackup-by-cópia-quando-incompatibilidade t);; Treat 'y' or < CR > as yes, 'n' as no. ;; Trate 'y' ou <CR> como sim,'n' como nenhum.(fset 'yes-or-no-p 'y-or-np) (Fset "sim-ou-não-p 'y-ou-np)(define-key query-replace-map [return] 'act) (Define-keyquery-replace-map [return] 'act)(define-key query-replace-map [?\Cm] 'act) (Define-key query-replace-map[? \ Cm] 'act);; Load packages ;; Pacotes de carga(require 'desktop) (Require 'desktop)(require 'tar-mode) (Require 'de modo tar);; Pretty diff mode ;; Modo Bonita diff(autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff"t) (Autoload 'Ediff-buffers "ediff" "Intelligent Emacs interface paradiff" t)(autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t)(Autoload 'ediff-files "ediff" "Intelligent Emacs interface para diff" t)(autoload 'ediff-files-remote "ediff" (Ediff-files-remote "ediff"autoload '"Intelligent Emacs interface to diff") "Intelligent Emacs interface paradiff")(if first-time (Se pela primeira vez(setq auto-mode-alist (Setq auto-mode-alist(append '(("\\.cpp$" . c++-mode) (Append '(("\ \. Cpp $". C + +-mode)("\\.hpp$" . c++-mode) ("\ \. UHE $". C + +-mode)("\\.lsp$" . lisp-mode) (Lisp-mode "\ \. Lsp $").("\\.scm$" . scheme-mode) ("\ \. Scm $". Modo de esquema)("\\.pl$" . perl-mode) (Perl-mode "\ \. Pl $").) auto-mode-alist))) ) Auto-mode-alist)));; Auto font lock mode ;; Modo de bloqueio automático da fonte(defvar font-lock-auto-mode-list (Font-lock-auto-mode-list defvar(list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode'perl-mode 'scheme- ('C-mode' lista c + +-mode 'c + +-c-mode' lisp-mode'emacs-lisp-mode perl-mode' esquema demode) mode)

Page 44: 139920579 Versao Traduzida de Book

"List of modes to always start in font-lock-mode") "Lista de modos deiniciar sempre em modo lock-fonte")(defvar font-lock-mode-keyword-alist (Defvar font-lock-mode-keyword-alist'((c++-c-mode . c-font-lock-keywords) '((C + +-c-mode.C-font-lock-palavras-chave)(perl-mode . perl-font-lock-keywords)) (Perl-mode.Perl-font-lock-palavras-chave))"Associations between modes and keywords") "Associações entre os modos epalavras-chave")(defun font-lock-auto-mode-select () (Defun font-modo-auto-lock-select ()"Automatically select font-lock-mode if the current major mode is"Selecionar automaticamente-lock-mode fonte se o modo mais atual éin font-lock-auto-mode-list" em font-lock-auto-mode-list "(if (memq major-mode font-lock-auto-mode-list) (If (memq major-modefont-lock-auto-mode-lista)(progn (Progn(font-lock-mode t)) (-Lock-mode fonte t))) )/30/ /30/------------------------------------------------------------------------*Page 39* *Page 39*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/) )(global-set-key [M-f1] 'font-lock-fontify-buffer) (Global-set-key [M-f1]'font-lock-fontify-buffer);; New dabbrev stuff ;; New stuff dabbrev;(require 'new-dabbrev) , (Require 'new-dabbrev)(setq dabbrev-always-check-other-buffers t) (Setqdabbrev-sempre-check-outro-buffers t)(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_") (Setqdabbrev-abrev-char-regexp "\ \ sw \ \ | \ \ s_")(add-hook 'emacs-lisp-mode-hook (Add-hook 'emacs-lisp-mode-hook'(lambda () '(Lambda ()(set (make-local-variable 'dabbrev-case-fold-search) nil) (Definido(caso dabbrev-fold-busca tornar-local-variável) nil)(set (make-local-variable 'dabbrev-case-replace) nil))) (Conjunto(make-local-variável 'dabbrev-case-replace) nil)))(add-hook 'c-mode-hook (Add-hook 'c-mode-hook'(lambda () '(Lambda ()(set (make-local-variable 'dabbrev-case-fold-search) nil) (Definido(caso dabbrev-fold-busca tornar-local-variável) nil)(set (make-local-variable 'dabbrev-case-replace) nil))) (Definido(tornar-local-variável dabbrev-case-replace) nil)))(add-hook 'text-mode-hook (Add-hook 'text-mode-hook'(lambda () '(Lambda ()(set (make-local-variable 'dabbrev-case-fold-search) t) (Conjunto(make-local-variável 'caso dabbrev-fold-search) t)(set (make-local-variable 'dabbrev-case-replace) t))) (Conjunto(make-local-variável 'dabbrev-case-replace) t)));; C++ and C mode... ,, C + + e C modo ...(defun my-c++-mode-hook () (Defun my-c + +-mode-hook ()(setq tab-width 4) (Setq guia de largura 4)(define-key c++-mode-map "\Cm" 'reindent-then-newline-and-indent)(Define-key c + +-mode-map "\ Cm" 'reindent-então-nova linha-e-travessão)(define-key c++-mode-map "\C-ce" 'c-comment-edit) (Define-key c ++-mode-map "\ C-ce" 'c-comment-edit)(setq c++-auto-hungry-initial-state 'none) (Setq c ++-auto-fome-initial-state 'none)(setq c++-delete-function 'backward-delete-char) (Setq c +

Page 45: 139920579 Versao Traduzida de Book

+-delete-função 'backward-delete-char)(setq c++-tab-always-indent t) (Setq c + +-tab-sempre-travessão t)(setq c-indent-level 4) (Setq c-nível travessão 4)(setq c-continued-statement-offset 4) (Setq c-contínuo-statement-offset 4)(setq c++-empty-arglist-indent 4)) (Setq c + +-empty-arglist-travessão 4))(defun my-c-mode-hook () (Defun my-c-mode-hook ()(setq tab-width 4) (Setq guia de largura 4)(define-key c-mode-map "\Cm" 'reindent-then-newline-and-indent)(Define-key c-mode-map "\ Cm" 'reindent-então-nova linha-e-travessão)(define-key c-mode-map "\C-ce" 'c-comment-edit) (Define-key c-mode-map"\ C-ce" 'c-comment-edit)(setq c-auto-hungry-initial-state 'none) (Setq c-auto-fome-initial-state'none)(setq c-delete-function 'backward-delete-char) (Setq c-delete-função'backward-delete-char)(setq c-tab-always-indent t) (Setq c-tab-sempre-travessão t);; BSD-ish indentation style ;; Estilo recuo BSD-ish(setq c-indent-level 4) (Setq c-nível travessão 4)(setq c-continued-statement-offset 4) (Setq c-contínuo-statement-offset 4)(setq c-brace-offset -4) (Setq c-cinta-offset -4)(setq c-argdecl-indent 0) (Setq c-argdecl-travessão 0)/31/ /31/------------------------------------------------------------------------*Page 40* *Page 40*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/(setq c-label-offset -4)) (Setq c-label-offset -4));; Perl mode Modo Perl;;(defun my-perl-mode-hook () (Defun my-perl-mode-hook ()(setq tab-width 4) (Setq guia de largura 4)(define-key c++-mode-map "\Cm" 'reindent-then-newline-and-indent)(Define-key c + +-mode-map "\ Cm" 'reindent-então-nova linha-e-travessão)(setq perl-indent-level 4) (Setq perl-nível travessão 4)(setq perl-continued-statement-offset 4)) (Setqperl-contínuo-statement-offset 4));; Scheme mode... ;; Modo Scheme ...(defun my-scheme-mode-hook () (Defun my-esquema-mode-hook ()(define-key scheme-mode-map "\Cm" 'reindent-then-newline-and-indent))(Define-key esquema-mode-map "\ Cm" 'reindent-então-novalinha-e-travessão));; Emacs-Lisp mode... ;; Emacs-Lisp modo ...(defun my-lisp-mode-hook () (Defun my-lisp-mode-hook ()(define-key lisp-mode-map "\Cm" 'reindent-then-newline-and-indent)(Define-key lisp-mode-map "\ Cm" 'reindent-então-nova linha-e-travessão)(define-key lisp-mode-map "\Ci" 'lisp-indent-line) (Define-keylisp-mode-map-line lisp-indent "\ Ci '")(define-key lisp-mode-map "\Cj" 'eval-print-last-sexp)) (Define-keylisp-mode-map "\ Cj" 'eval-print-last-sexp));; Add all of the hooks... ;; Adicionar todos os ganchos ...(add-hook 'c++-mode-hook 'my-c++-mode-hook) (Add-hook 'c + +-mode-hook'my-c + +-mode-hook)(add-hook 'c-mode-hook 'my-c-mode-hook) (Add-hook 'c-mode-hook'my-c-mode-hook)(add-hook 'scheme-mode-hook 'my-scheme-mode-hook) (Add-hook"regime-mode-hook 'my-esquema-mode-hook)(add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook) (Add-hook'emacs-lisp-mode-hook' my-lisp-mode-hook)(add-hook 'lisp-mode-hook 'my-lisp-mode-hook) (Add-hook "lisp-mode-hook'my-lisp-mode-hook)(add-hook 'perl-mode-hook 'my-perl-mode-hook) (Add-hook 'perl-mode-hook'

Page 46: 139920579 Versao Traduzida de Book

my-perl-mode-hook);; Complement to next-error ;; Complementar ao erro-next(defun previous-error (n) (Erro anterior-defun (n)"Visit previous compilation error message and corresponding sourcecode." "Visite mensagem de erro de compilação anterior e correspondentecódigo fonte."(interactive "p") (Interactive "p")(next-error (- n))) (Próxima de erro (- n)));; Misc... ;; Vários ...(transient-mark-mode 1) (Transitório-mark-mode 1)(setq mark-even-if-inactive t) (Setq marca-even-se-inativos t)(setq visible-bell nil) (Setq visible-bell nil)(setq next-line-add-newlines nil) (Setq próxima linha add-newlines nil)(setq compile-command "make") (Compilação comando setq "make")(setq suggest-key-bindings nil) (Setq sugerir-combinações de teclas nil)(put 'eval-expression 'disabled nil) (Colocar 'eval-expressão' nilpessoas com deficiência)(put 'narrow-to-region 'disabled nil) (Colocar 'narrow-to-região nilpessoas com deficiência)(put 'set-goal-column 'disabled nil) (Colocar 'set-goal-coluna' nilpessoas com deficiência);; Elisp archive searching ;; Elisp arquivo busca/32/ /32/------------------------------------------------------------------------*Page 41* *Page 41*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/(autoload 'format-lisp-code-directory "lispdir" nil t) (Autoload"formato-lisp-code-diretório" lispdir "nil t)(autoload 'lisp-dir-apropos "lispdir" nil t) (Autoload 'lisp-dir-apropos"lispdir" nil t)(autoload 'lisp-dir-retrieve "lispdir" nil t) (Autoload'lisp-dir-recuperar "lispdir" nil t)(autoload 'lisp-dir-verify "lispdir" nil t) (Autoload 'lisp-dir-verify"lispdir" nil t);; Font lock mode ;; Modo de bloqueio Font(defun my-make-face (face colour &optional bold) (Defun my-faz-de-face(cor da face e opcional negrito)"Create a face from a colour and optionally make it bold" "Criar umrosto a partir de uma cor e, opcionalmente, torná-lo bold"(make-face face) (Certifique-face face)(copy-face 'default face) (Copy-face 'face default)(set-face-foreground face colour) (Cor da cara set-face-primeiro plano)(if bold (make-face-bold face)) (Se negrito (face tornar-face-negrito))) )(if (eq window-system 'x) (If (eq janela sistema 'x)(progn (Progn(my-make-face 'blue "blue") (My-fazer-face "azul" blue ")(my-make-face 'red "red") (My-fazer-face "vermelho" vermelho ")(my-make-face 'green "dark green") (My-fazer-face "verde" verde escuro ")(setq font-lock-comment-face 'blue) (Setq font-lock-comment-face 'azul)(setq font-lock-string-face 'bold) (Setq font-lock-string-face 'negrito)(setq font-lock-type-face 'bold) (Setq font-lock-type-face 'negrito)(setq font-lock-keyword-face 'bold) (Setq font-lock-keyword-face 'negrito)(setq font-lock-function-name-face 'red) (Setqfont-lock-function-name-face 'vermelho)(setq font-lock-doc-string-face 'green) (Setq font-lock-doc-string-face'verde)(add-hook 'find-file-hooks 'font-lock-auto-mode-select) (Add-hook'find-file-ganchos' font-lock-auto-mode-select)

Page 47: 139920579 Versao Traduzida de Book

(setq baud-rate 1000000) (Setq baud-rate 1000000)(global-set-key "\C-cmm" 'menu-bar-mode) ("\ C-cmm" 'menu-bar-modemundial-set-key)(global-set-key "\C-cms" 'scroll-bar-mode) (Global-set-key "\ C-cms"'-bar-mode rolagem)(global-set-key [backspace] 'backward-delete-char) (Global-set-key[backspace] 'delete-backward-char); ;(global-set-key [delete] 'delete-char) (Global-set-key [delete]'delete-char)(standard-display-european t) (Standard-display-european t)(load-library "iso-transl"))) (Load-library "iso-transl")));; X11 or PC using direct screen writes ;; X11 ou PC usando a teladireto escreve(if window-system (Se window-system(progn (Progn;; ;;(global-set-key [M-f1] 'hilit-repaint-command) (Global-set-key [M-f1]'Hilit-pintar-comando);; ;;(global-set-key [M-f2] [?\Cu M-f1]) (Global-set-key [M-f2] [? \ Cu M-f1])(setq hilit-mode-enable-list (Setq Hilit-mode-enable-lista'(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode '(E não emmodo texto c-mode c + + de modo emacs-lisp-mode lisp-modescheme-mode) modo de esquema)hilit-auto-highlight nil nil Hilit-auto-destaquehilit-auto-rehighlight 'visible Hilit-auto-rehighlight "visível/33/ /33/------------------------------------------------------------------------*Page 42* *Page 42*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/hilit-inhibit-hooks nil Hilit-inibir-ganchos nilhilit-inhibit-rebinding t) Hilit-inibir-religação t)(require 'hilit19) (Require 'hilit19)(require 'paren)) (Require 'parêntese))(setq baud-rate 2400) ; For slow serial connections (Setq baud-rate2400), para conexões seriais lentas) );; TTY type terminal ;; Tipo de terminal TTY(if (and (not window-system) (If (e (não window-system)(not (equal system-type 'ms-dos))) (Not (tipo de sistema igual "MS-DOS)))(progn (Progn(if first-time (Se pela primeira vez(progn (Progn(keyboard-translate ?\Ch ?\C-?) (Teclado traduzir? \ Ch? \ C-?)(keyboard-translate ?\C-? ?\Ch))))) (Teclado traduzir? \ C-? \ Ch)))));; Under UNIX ;; Sob UNIX(if (not (equal system-type 'ms-dos)) (If (not (tipo de sistema igual"MS-DOS))(progn (Progn(if first-time (Se pela primeira vez(server-start)))) (Server-start))));; Add any face changes here ;; Adicionar quaisquer alterações cara aqui(add-hook 'term-setup-hook 'my-term-setup-hook) (Add-hook"termo-setup-hook 'meu prazo-setup-hook)(defun my-term-setup-hook () (Defun meu prazo-setup-hook ()(if (eq window-system 'pc) (Se pc (eq window-system ')(progn (Progn;; (set-face-background 'default "red") ,, (Set-face-fundo "default"

Page 48: 139920579 Versao Traduzida de Book

vermelho ")))) )));; Restore the "desktop" - do this as late as possible ;; Restaurar o"desktop" - faça isso o mais tarde possível(if first-time (Se pela primeira vez(progn (Progn(desktop-load-default) (Desktop-load-padrão)(desktop-read))) (Desktop-read)));; Indicate that this file has been read at least once ;; Indicar queeste arquivo foi lido pelo menos uma vez(setq first-time nil) (Setq nulo pela primeira vez);; No need to debug anything now ;; Não há necessidade de depurar nadaagora(setq debug-on-error nil) (Setq nil-on-error debug);; All done ;; Tudo feito(message "All done, %s%s" (user-login-name) ".") (Mensagem "Tudo feito,%s% s" (user-login-name) ".")/34/ /34/------------------------------------------------------------------------*Page 43* *Page 43*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/*5.7.4.* *5.7.4.* *Extending the Range of Languages Emacs Understands**Ampliando o leque de línguas Emacs Compreende*Now, this is all very well if you only want to program in the languagesalready catered for in the Agora, tudo isso é muito bem se você sódeseja programar nas línguas já previstos no.emacs . Emacsfile (C, C++, arquivo (C, C + +,Perl, Lisp and Scheme), but what happens if a new language called“whizbang” comes out, full of exciting features? Perl, Lisp e Scheme),mas o que acontece se uma nova linguagem chamada "whizbang" vem de fora,cheio de recursos interessantes?The first thing to do is find out if whizbang comes with any files thattell Emacs about the language. A primeira coisa a fazer é descobrir sewhizbang vem com todos os arquivos que contam Emacs sobre a língua.These usually Estes geralmenteend in final em.el . El, short for “Emacs Lisp”. , Abreviação de "Emacs Lisp". For example, ifwhizbang is a FreeBSD port, we can locate these files by doing Porexemplo, se whizbang é uma porta FreeBSD, podemos localizar essesarquivos, fazendo% %*find /usr/ports/lang/whizbang -name "*.el" -print* *find / usr / ports/ lang / whizbang-name "*. el"-print*and install them by copying them into the Emacs site Lisp directory. einstalá-los, copiando-os para o diretório local Lisp Emacs. On FreeBSD2.1.0-RELEASE, this is No FreeBSD 2.1.0-RELEASE, este é/usr/local/share/emacs/site-lisp / Usr / local / share / emacs / site-lisp. .So for example, if the output from the find command was Assim, porexemplo, se a saída do comando find foi/usr/ports/lang/whizbang/work/misc/whizbang.el / Usr / ports / lang /whizbang / trabalho / misc / whizbang.elwe would do faríamos# #*cp /usr/ports/lang/whizbang/work/misc/whizbang.el/usr/local/share/emacs/site-lisp* *CP / usr / ports / lang / whizbang /trabalho / misc / whizbang.el / usr / local / share / emacs / site-lisp*

Page 49: 139920579 Versao Traduzida de Book

Next, we need to decide what extension whizbang source files have. Emseguida, precisamos decidir o que arquivos de origem whizbang extensãotem. Let's say for the sake of argument that they all Vamos dizer, porcausa do argumento de que todos elesend in final em.wiz . Wiz. . We need to add an entry to our Nós precisamos adicionar uma entradapara o nosso.emacs . Emacsfile to make sure Emacs will be able to use the information in arquivopara ter certeza Emacs será capaz de usar as informaçõeswhizbang.el whizbang.el. .Find the auto-mode-alist entry in Encontre a entrada auto-mode-alist em.emacs . Emacsand add a line for whizbang, such as: e adicionar uma linha parawhizbang, tais como:/.../ /.../("\\.lsp$" . lisp-mode) (Lisp-mode "\ \. Lsp $").("\\.wiz$" . whizbang-mode) '("\ \. Wiz $". Modo whizbang)("\\.scm$" . scheme-mode) ("\ \. Scm $". Modo de esquema)/.../ /.../This means that Emacs will automatically go into Isso significa que oEmacs entrará automaticamente nowhizbang-mode de modo whizbangwhen you edit a file ending in quando você editar um arquivo que termina em.wiz . Wiz. .Just below this, you'll find the font-lock-auto-mode-list entry. Logoabaixo disso, você encontrará a entrada font-lock-auto-mode-list. AddAdicionarwhizbang-mode de modo whizbangto it like so: para ele assim:;; Auto font lock mode ;; Modo de bloqueio automático da fonte(defvar font-lock-auto-mode-list (Font-lock-auto-mode-list defvar/35/ /35/------------------------------------------------------------------------*Page 44* *Page 44*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/(list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'whizbang-mode'lisp-mode 'perl- ('C-mode' lista c + +-mode 'c + +-c-mode'whizbang-mode 'emacs-lisp-mode lisp-mode' perl-mode 'scheme-mode) modo "de modo esquema)"List of modes to always start in font-lock-mode") "Lista de modos deiniciar sempre em modo lock-fonte")This means that Emacs will always enable Isto significa que o Emacssempre permitirfont-lock-mode -mode fonte-lock(ie syntax highlighting) when editing a (Ou seja, destaque de sintaxe),quando a edição de um.wiz . Wizfile. arquivo.And that's all that's needed. E isso é tudo o que é necessário. Ifthere's anything else you want done automatically when you open up a Sehá alguma coisa que você quer que seja feito automaticamente quando vocêabrir um.wiz . Wizfile, you arquivo, vocêcan add a pode adicionar uma

Page 50: 139920579 Versao Traduzida de Book

whizbang-mode hook de modo whizbang gancho(see (Vermy-scheme-mode-hook my-esquema-mode-hookfor a simple example that adds para um exemplo simples que adicionaauto-indent auto-travessão). ).*5.8.* *5.8.* *Further Reading* *Leitura*• •Brian Harvey and Matthew Wright /Simply Scheme/ MIT 1994. Brian Harvey eMatthew Wright /Simplesmente Scheme/ MIT 1994. ISBN 0-262-08226-8 ISBN0-262-08226-8• •Randall Schwartz /Learning Perl/ O'Reilly 1993 ISBN 1-56592-042-2Randall Schwartz /Learning Perl/ O'Reilly 1993 ISBN 1-56592-042-2• •Patrick Henry Winston and Berthold Klaus Paul Horn /Lisp (3rd Edition)/Addison-Wesley 1989 ISBN Patrick Henry Winston e Berthold Klaus PaulHorn /Lisp (3rd Edition)/ Addison-Wesley 1989 ISBN0-201-08319-1 0-201-08319-1• •Brian W. Kernighan and Rob Pike /The Unix Programming Environment/Prentice-Hall 1984 ISBN 0-13-937681-X Brian W. Kernighan e Rob Pike /Oambiente de programação Unix/ Prentice-Hall 1984 ISBN 0-13-937681-X• •Brian W. Kernighan and Dennis M. Ritchie /The C Programming Language(2nd Edition)/ Prentice-Hall 1988 Brian W. Kernighan e Dennis M.Ritchie, /The C Programming Language (2nd Edition)/ Prentice-Hall 1988ISBN 0-13-110362-8 ISBN 0-13-110362-8• •Bjarne Stroustrup /The C++ Programming Language/ Addison-Wesley 1991ISBN 0-201-53992-6 Bjarne Stroustrup /A + + Programming Language/Addison-Wesley, 1991 ISBN 0-201-53992-6 /C/• •W. Richard Stevens /Advanced Programming in the Unix Environment/Addison-Wesley 1992 ISBN 0-201-56317-7 W. Richard Stevens /ProgramaçãoAvançada no ambiente Unix/ Addison-Wesley, 1992 ISBN 0-201-56317-7• •W. Richard Stevens /Unix Network Programming/ Prentice-Hall 1990 ISBN0-13-949876-1 W. Richard Stevens /Unix Rede Programação/ Prentice-Hall1990 ISBN 0-13-949876-1*Notes* *Notas*1. 1. If you run it in the shell, you may get a core dump. Se vocêexecutá-lo no shell, você pode obter um core dump.2. 2. To be strictly accurate, Para sermos rigorosos,cc ccconverts the source code into its own, machine-independent /p-code/instead of converte o código fonte em si próprio, /p-código/independente de máquina em vez deassembly language at this stage. linguagem assembly neste estágio.3. 3. In case you didn't know, a binary sort is an efficient way ofsorting things into order and a bubble sort isn't. No caso de você nãosabia, a classificação binária é uma forma eficiente de classificar ascoisas em ordem e uma espécie de bolha não é.4. 4. The reasons for this are buried in the mists of history. As razõespara isso são enterrados nas brumas da história.5. 5. Note, we didn't use the Note-se, nós não usamos o-o -Oflag to specify the executable name, so we will get an executable calledflag para especificar o nome do arquivo executável, então teremos umexecutável chamado

Page 51: 139920579 Versao Traduzida de Book

a.out a.out. .Producing a debug version called Produzindo uma versão de depuração chamadofoobar foobaris left as an exercise for the reader! é deixado como um exercício parao leitor!6. 6. They don't use the Eles não usam oMAKEFILE MAKEFILEform as block capitals are often used for documentation files like formacomo letras maiúsculas são frequentemente utilizados para arquivos dedocumentação comoREADME README. ./36/ /36/------------------------------------------------------------------------*Page 45* *Page 45*

/Chapter 5./ /Capítulo 5./ /Programming Tools/ /Ferramentas de Programação/7. 7. At least, not unless you pay out very large sums of money. Pelomenos, não a menos que você pagar grandes somas de dinheiro.8. 8. Many Emacs users set their EDITOR environment to Muitos usuáriosdo Emacs definiu seu ambiente EDITOR paraemacsclient emacsclientso this happens every time they need to edit então isso acontece cadavez que precisa editara file. um arquivo./37/ /37/------------------------------------------------------------------------*Page 46* *Page 46*

*Chapter 6.* *Capítulo 6.* *Secure Programming* *Programação Segura*This chapter was written by Murray Stokely < Este capítulo foi escritopor Murray Stokely <[email protected] [email protected]>. >.*6.1.* *6.1.* *Synopsis* *Sinopse*This chapter describes some of the security issues that have plaguedUnix programmers for decades and some of the Este capítulo descrevealguns dos problemas de segurança que têm atormentado os programadoresUnix por décadas e algumas dasnew tools available to help programmers avoid writing exploitable code.novas ferramentas disponíveis para ajudar os programadores a evitarescrever código explorável.*6.2.* *6.2.* *Secure Design Methodology* *Seguro Metodologia de Design*Writing secure applications takes a very scrutinous and pessimisticoutlook on life. Escrevendo aplicações seguras tem uma visão muitoscrutinous e pessimista da vida. Applications should be run with Ascandidaturas deverão ser executados comthe principle of “least privilege” so that no process is ever runningwith more than the bare minimum access that it o princípio da "menorprivilégio" de modo que nenhum processo está sempre correndo com mais doque o acesso mínimo queneeds to accomplish its function. precisa para realizar a sua função.Previously tested code should be reused whenever possible to avoidcommon Código previamente testados devem ser reutilizados sempre quepossível para evitar comummistakes that others may have already fixed. erros que outros já podeter fixado.One of the pitfalls of the Unix environment is how easy it is to makeassumptions about the sanity of the environment. Uma das armadilhas do

Page 52: 139920579 Versao Traduzida de Book

ambiente Unix é o quão fácil é fazer suposições sobre a sanidade do meioambiente.Applications should never trust user input (in all its forms), systemresources, inter-process communication, or the Aplicações nunca devemconfiar entrada do usuário (em todas as suas formas), os recursos dosistema, inter-processo de comunicação, ou atiming of events. cronometragem de eventos. Unix processes do notexecute synchronously so logical operations are rarely atomic. ProcessosUnix não executar de forma síncrona para que as operações lógicas sãoraramente atômica.*6.3.* *6.3.* *Buffer Overflows* *Buffer overflows*Buffer Overflows have been around since the very beginnings of theVon-Neuman 1 Buffer overflows existem desde os primórdios da Von-Neuman1 <#257> architecture. arquitetura. They first gained Eles primeiro ganhouwidespread notoriety in 1988 with the Morris Internet worm. notoriedadeem 1988 com o worm Morris Internet. Unfortunately, the same basic attackremains effective Infelizmente, o mesmo ataque básico permanece eficaztoday. hoje. Of the 17 CERT security advisories of 1999, 10 of them weredirectly caused by buffer-overflow software Dos 17 CERT alertas desegurança 1999, 10 deles foram diretamente causados ��por software deestouro de bufferbugs. Pernalonga. By far the most common type of buffer overflow attackis based on corrupting the stack. De longe o tipo mais comum de tampãode ataque de sobrecarga é baseado em corromper a pilha.Most modern computer systems use a stack to pass arguments to proceduresand to store local variables. A maioria dos computadores modernosutilizam uma pilha para passar argumentos para os procedimentos e paraarmazenar variáveis ��locais. A stack is a Uma pilha é umlast in first out (LIFO) buffer in the high memory area of a processimage. Last In First Out (LIFO) tampão na área de memória alta a imagemdo processo de. When a program invokes a function a new Quando umprograma chama uma função de um novo"stack frame" is created. "Quadro de pilha" é criado. This stack frameconsists of the arguments passed to the function as well as a dynamicEste quadro de pilha consiste dos argumentos passados ��para a função,bem como a dinâmicaamount of local variable space. quantidade de espaço variável local. The"stack pointer" is a register that holds the current location of the topof the stack. O "ponteiro de pilha" é um registo que contém o localactual do topo da pilha.Since this value is constantly changing as new values are pushed ontothe top of the stack, many implementations Uma vez que este valor estáconstantemente a mudar à medida que novos valores são colocados na partesuperior da pilha, muitas implementaçõesalso provide a "frame pointer" that is located near the beginning of astack frame so that local variables can more também fornecer um"ponteiro" que está localizada perto do início de um quadro de pilha,para que as variáveis ��locais podem maiseasily be addressed relative to this value. facilmente ser tratadas emrelação a esse valor. <#257> 1 The return address for function 1 Oendereço de retorno para a funçãocalls is also stored on the stack, and this chamadas é também armazenadona pilha, e estais the cause of stack-overflow exploits since overflowing a localvariable in a function can overwrite the return é a causa de exploits deestouro de pilha desde que transborda uma variável local em uma funçãopode sobrescrever o retornoaddress of that function, potentially allowing a malicious user toexecute any code he or she wants. tratar dessa função, potencialmentepermitindo que um usuário mal-intencionado para executar qualquer código

Page 53: 139920579 Versao Traduzida de Book

que ele ou ela quer./38/ /38/------------------------------------------------------------------------*Page 47* *Page 47*

/Chapter 6./ /Capítulo 6./ /Secure Programming/ /Programação Segura/Although stack-based attacks are by far the most common, it would alsobe possible to overrun the stack with a Embora ataques baseados pilhasão, de longe, o mais comum, mas também seria possível invadido a pilhacom umaheap-based (malloc/free) attack. ataque na pilha (malloc / free).The C programming language does not perform automatic bounds checking onarrays or pointers as many other A linguagem de programação C nãorealiza verificação automática de limites para arrays ou ponteiros comomuitos outroslanguages do. linguagens fazer. In addition, the standard C library isfilled with a handful of very dangerous functions. Além disso, abiblioteca C padrão está cheio de um punhado de funções muito perigosas.strcpy strcpy(char *dest, const char *src) (Char * dest, const char * src)May overflow the dest buffer Pode transbordar o buffer deststrcat strcat(char *dest, const char *src) (Char * dest, const char * src)May overflow the dest buffer Pode transbordar o buffer destgetwd getwd(char *buf) (Char * buf)May overflow the buf buffer Pode transbordar o buffer bufgets fica(char *s) (Char * s)May overflow the s buffer Pode transbordar o buffer s[vf]scanf [FV] scanf(const char *format, ...) (Const char * formato, ...)May overflow its arguments. Pode transbordar seus argumentos.realpath realpath(char *path, char resolved_path[]) (Char * path, char resolved_path [])May overflow the path buffer Pode transbordar o buffer caminho[v]sprintf [V] sprintf(char *str, const char *format, ...) (Char * str, const char * format, ...)May overflow the str buffer. Pode transbordar o buffer str.*6.3.1.* *6.3.1.* *Example Buffer Overflow* *Exemplo Buffer Overflow*The following example code contains a buffer overflow designed tooverwrite the return address and skip the O seguinte exemplo de códigocontém um buffer overflow projetado para substituir o endereço doremetente e ignorar oinstruction immediately following the function call. instruçãoimediatamente após a chamada de função. (Inspired by 4 <#257> )(Inspirado por 4 <#257> )#include # Include<stdio.h> <stdio.h>void manipulate(char *buffer) { anular a manipular (char * buffer) {char newbuffer[80]; carbonizar newbuffer [80];strcpy(newbuffer,buffer); strcpy (newbuffer, buffer);} }int main() { int main () {char ch,buffer[4096]; char ch, buffer [4096];int i=0; int i = 0;while ((buffer[i++] = getchar()) != '\n') {}; while ((buffer [i + +] =getchar ()) = '\ n') {};i=1; i = 1;manipulate(buffer); manipular (buffer);

Page 54: 139920579 Versao Traduzida de Book

i=2; i = 2;printf("The value of i is : %d\n",i); printf ("O valor de i é:% d \ n", i);return 0; retornar 0;} }Let us examine what the memory image of this process would look like ifwe were to input 160 spaces into our little Vamos examinar o que aimagem da memória desse processo seria se estivéssemos a entrada de 160espaços em nosso pequenoprogram before hitting return. programa antes de bater retorno./39/ /39/------------------------------------------------------------------------*Page 48* *Page 48*

/Chapter 6./ /Capítulo 6./ /Secure Programming/ /Programação Segura/[XXX figure here!] [XXX figura aqui!]Obviously more malicious input can be devised to execute actual compiledinstructions (such as exec(/bin/sh)). Entrada, obviamente, maismalicioso pode ser concebido para executar instruções reais compilados(como exec (/ bin / sh)).*6.3.2.* *6.3.2.* *Avoiding Buffer Overflows* *Evitando Buffer Overflow*The most straightforward solution to the problem of stack-overflows isto always use length restricted memory and A solução mais simples para oproblema da pilha-overflows é sempre usar comprimento memória restrita estring copy functions. corda funções de cópia.strncpy strncpyand estrncat strncatare part of the standard C library. são parte da biblioteca C padrão.These functions accept a length Estas funções aceitam um comprimentovalue as a parameter which should be no larger than the size of thedestination buffer. valor como um parâmetro que não deverá ser maior doque o tamanho do buffer de destino. These functions will then copy Essasfunções serão, em seguida, copiarup to 'length' bytes from the source to the destination. até bytes'length' da origem para o destino. However there are a number ofproblems with these functions. No entanto, há um certo número deproblemas com estas funções.Neither function guarantees NUL termination if the size of the inputbuffer is as large as the destination. Nem função garante terminação NULse o tamanho do buffer de entrada é tão grande como o destino. Thelength O comprimentoparameter is also used inconsistently between strncpy and strncat so itis easy for programmers to get confused as to parâmetro também éutilizado de forma inconsistente entre strncpy e strncat por isso éfácil para os programadores a ficar confuso quanto aotheir proper usage. seu uso adequado. There is also a significantperformance loss compared to Há também uma perda significativa dedesempenho em comparação comstrcpy strcpywhen copying a short string into ao copiar uma seqüência curta ema large buffer since um buffer grande desdestrncpy strncpyNUL fills up the the size specified. NUL enche o do tamanho especificado.In OpenBSD, another memory copy implementation has been created to getaround these problem. No OpenBSD, outra implementação de cópia dememória foi criada para contornar esses problemas. The Ostrlcpy strlcpyand estrlcat strlcatfunctions guarantee that they will always null terminate the destination

Page 55: 139920579 Versao Traduzida de Book

string when given a non-zero funções garantir que eles sempre nuloencerrar a seqüência de destino quando recebe um diferente de zerolength argument. comprimento argumento. For more information about thesefunctions se e <#257> 6. Para mais informações sobre estas funções se e<#257> 6. The OpenBSD O OpenBSDstrlcpy strlcpyand estrlcat strlcatinstructions have been in FreeBSD since 3.3. instruções têm sido desdeFreeBSD 3.3.*6.3.2.1.* *6.3.2.1.* *Compiler based run-time bounds checking**Compiler baseados limites de tempo de execução verificação*Unfortunately there is still a very large assortment of code in publicuse which blindly copies memory around Infelizmente, ainda há uma grandevariedade de código de uso público que cegamente copia memória em tornowithout using any of the bounded copy routines we just discussed. sem ouso de qualquer uma das rotinas de cópia delimitadas que acabamos dediscutir. Fortunately, there is another solution. Felizmente, existe umaoutra solução. Several Várioscompiler add-ons and libraries exist to do Run-time bounds checking inC/C++. existe compilador add-ons e bibliotecas para fazer limites detempo de execução check-in C / C + +.StackGuard is one such add-on that is implemented as a small patch tothe gcc code generator. StackGuard é um tal add-on que é implementadocomo um pequeno pedaço para o gerador de código gcc. From the StackGuardDo StackGuardwebsite, http://immunix.org/stackguard.html : website,http://immunix.org/stackguard.html:"StackGuard detects and defeats stack smashing attacks by protecting thereturn address on the stack from being altered. "StackGuard detecta ederrotas pilha ataques sensacionais, protegendo o endereço de retorno napilha de ser alterada.StackGuard places a "canary" word next to the return address when afunction is called. StackGuard coloca um "canário" palavra ao lado doendereço de retorno quando uma função é chamada. If the canary word hasbeen altered Se a palavra canário foi alteradawhen the function returns, then a stack smashing attack has beenattempted, and the program responds by emitting an , quando o retorno dafunção, então um ataque sensacional pilha foi tentado, eo programaresponde emitindo umintruder alert into syslog, and then halts." de detecção de intrusão emsyslog, e, em seguida, pára. ""StackGuard is implemented as a small patch to the gcc code generator,specifically the function_prolog() and "StackGuard é implementado comoum pequeno pedaço para o gerador de código gcc, especificamente ofunction_prolog () efunction_epilog() routines. function_epilog (rotinas). function_prolog()has been enhanced to lay down canaries on the stack when functionsstart, and function_prolog () foi aprimorado para estabelecer canáriosna pilha quando as funções de começar, efunction_epilog() checks canary integrity when the function exits.function_epilog () verifica a integridade canário quando a funçãotermina. Any attempt at corrupting the return address is thus Qualquertentativa de corromper o endereço de retorno é, portanto,detected before the function returns." detectado antes a função retorna. "/40/ /40/------------------------------------------------------------------------*Page 49* *Page 49*

/Chapter 6./ /Capítulo 6./ /Secure Programming/ /Programação Segura/

Page 56: 139920579 Versao Traduzida de Book

Recompiling your application with StackGuard is an effective means ofstopping most buffer-overflow attacks, but it Recompilar seu aplicativocom StackGuard é um meio eficaz de impedir a maioria dos ataques deestouro de buffer, mascan still be compromised. ainda pode ser comprometida.*6.3.2.2.* *6.3.2.2.* *Library based run-time bounds checking**Biblioteca limites baseados em tempo de execução verificação*Compiler-based mechanisms are completely useless for binary-onlysoftware for which you cannot recompile. Mecanismos baseados nocompilador são completamente inúteis para somente binário software parao qual você não pode recompilar. For Parathese situations there are a number of libraries which re-implement theunsafe functions of the C-library ( Nessas situações, há uma série debibliotecas que re-implementar as funções inseguras do C-biblioteca (strcpy strcpy, ,fscanf fscanf, ,getwd getwd, etc..) and ensure that these functions can never write past the stackpointer. , Etc.) E garantir que estas funções nunca pode escreverpassado o ponteiro da pilha.• •libsafe libsafe• •libverify libverify• •libparnoia libparnoiaUnfortunately these library-based defenses have a number ofshortcomings. Infelizmente, essas defesas baseadas em biblioteca tem umasérie de deficiências. These libraries only protect against a Essasbibliotecas só proteger contra avery small set of security related issues and they neglect to fix theactual problem. muito pequeno conjunto de questões relacionadas com asegurança e se esquecem de corrigir o problema real. These defenses mayfail if the Essas defesas podem falhar se oapplication was compiled with -fomit-frame-pointer. aplicação foicompilada com-fomit-frame-pointer. Also, the LD_PRELOAD andLD_LIBRARY_PATH Além disso, o LD_PRELOAD e LD_LIBRARY_PATHenvironment variables can be overwritten/unset by the user. variáveis ��de ambiente pode ser substituído / desactivado pelo utilizador.*6.4.* *6.4.* *SetUID issues* *Questões Setuid*There are at least 6 different IDs associated with any given process. Hápelo menos seis diferentes identificações associadas a um determinadoprocesso. Because of this you have to be very careful with Devido aisso, você tem que ter muito cuidado comthe access that your process has at any given time. o acesso que oprocesso tem a qualquer momento. In particular, all seteuid applicationsshould give up their Em particular, todas as aplicações seteuid devedesistir de suaprivileges as soon as it is no longer required. privilégios, assim quenão é mais necessário.The real user ID can only be changed by a superuser process. O ID dousuário real só pode ser alterada por um processo de superusuário. The*login* program sets this when a user initially logs O programa de*login* define este quando um usuário efetua inicialmentein and it is seldom changed. e raramente é alterada.The effective user ID is set by the O ID de usuário efetivo é definido peloexec() exec ()functions if a program has its seteuid bit set. funções Se um programa

Page 57: 139920579 Versao Traduzida de Book

tem o seu conjunto de bits seteuid. An application can call Umaplicativo pode chamarseteuid() seteuid ()at any time to set the effective user ID to either the real user ID orthe saved set-user-ID. a qualquer momento para definir o ID de usuárioefetivo para o ID do usuário real ou o salvou set-user-ID. When theQuando oeffective user ID is set by ID de usuário efetivo é definido peloexec() exec ()functions, the previous value is saved in the saved set-user-ID.funções, o valor anterior é guardada na salvou set-user-ID.*6.5.* *6.5.* *Limiting your program's environment* *Limitando oambiente do seu programa*The traditional method of restricting a process is with the O métodotradicional de restrição de um processo é com ochroot() chroot ()system call. chamada de sistema. This system call changes the root Estachamada de sistema muda a raizdirectory from which all other paths are referenced for a process andany child processes. diretório a partir do qual todos os outros caminhossão referenciados por um processo e todos os processos filho. For thiscall to succeed the Para esta chamada para suceder oprocess must have execute (search) permission on the directory beingreferenced. processo deve ter executar (pesquisa) permissão no diretórioque está sendo referenciado. The new environment does not O novoambiente não/41/ /41/------------------------------------------------------------------------*Page 50* *Página 50*

/Chapter 6./ /Capítulo 6./ /Secure Programming/ /Programação Segura/actually take effect until you realmente ter efeito até que vocêchdir() chdir ()into your new environment. em seu novo ambiente. It should also be notedthat a process can easily Também deve ser notado que um processo podefacilmentebreak out of a chroot environment if it has root privilege. sair de umambiente chroot se tem privilégios de root. This could be accomplishedby creating device nodes to Isto pode ser realizado através da criaçãode nós de dispositivos pararead kernel memory, attaching a debugger to a process outside of thejail, or in many other creative ways. leia memória do kernel, anexar umdepurador a um processo fora da prisão, ou de muitas outras maneirascriativas.The behavior of the O comportamento dochroot() chroot ()system call can be controlled somewhat with thekern.chroot_allow_open_directories de chamada do sistema pode sercontrolada de alguma forma com os kern.chroot_allow_open_directoriessysctl sysctlvariable. variável. When this value is set to 0, Quando este valor fordefinido para 0,chroot() chroot ()will fail with EPERM if there are any directories open. falhará comEPERM se existem diretórios abertos. If set Se definidoto the default value of 1, then para o valor padrão de 1, entãochroot() chroot ()will fail with EPERM if there are any directories open and the processis falhará com EPERM se existem diretórios aberta eo processo éalready subject to a já objecto de um

Page 58: 139920579 Versao Traduzida de Book

chroot() chroot ()call. chamar. For any other value, the check for open directories willbe bypassed completely. Para qualquer outro valor, o cheque dediretórios abertos serão ignorados completamente.*6.5.1.* *6.5.1.* *FreeBSD's jail functionality* *Funcionalidade prisãodo FreeBSD*The concept of a Jail extends upon the O conceito de uma cadeiaestende-se sobre ochroot() chroot ()by limiting the powers of the superuser to create a true 'virtuallimitando os poderes do super usuário para criar um verdadeiro 'virtualserver'. servidor '. Once a prison is setup all network communicationmust take place through the specified IP address, and the Uma vez que aprisão é a instalação toda a comunicação da rede deve ocorrer através doendereço IP especificado eopower of "root privilege" in this jail is severely constrained. poder de"privilégios de root" nesta prisão é severamente restrita.While in a prison, any tests of superuser power within the kernel usingthe Enquanto na prisão, todos os testes de poder de superusuário dentrodo kernel usando osuser() suser ()call will fail. chamada falhará. However, some No entanto, algunscalls to chamadas parasuser() suser ()have been changed to a new interface foram mudados para uma nova interfacesuser_xxx() suser_xxx (). . This function is responsible for recognizing Esta função éresponsável por reconheceror denying access to superuser power for imprisoned processes. ou negaro acesso ao poder de superusuário para os processos de presos.A superuser process within a jailed environment has the power to : Umprocesso de superusuário em um ambiente de preso tem o poder de:• •Manipulate credential with Manipular com credencialsetuid setuid, ,seteuid seteuid, ,setgid setgid, ,setegid setegid, ,setgroups setgroups, ,setreuid setreuid, ,setregid setregid, ,setlogin setlogin• •Set resource limits with Definir limites de recursos comsetrlimit setrlimit• •Modify some sysctl nodes (kern.hostname) Modificar alguns nós sysctl(kern.hostname)• •chroot() chroot ()• •Set flags on a vnode: Definir sinalizadores em uma vnode:chflags chflags

Page 59: 139920579 Versao Traduzida de Book

, ,fchflags fchflags• •Set attributes of a vnode such as file permission, owner, group, size,access time, and modification time. Definir atributos de um vnode comopermissão de arquivo, dono, grupo, tamanho, tempo de acesso e tempo demodificação.• •Bind to privileged ports in the Internet domain (ports < 1024) Vinculara portas privilegiadas no domínio Internet (portas <1024)Jail Prisãois a very useful tool for running applications in a secure environmentbut it does have some shortcomings. É uma ferramenta muito útil para aexecução de aplicativos em um ambiente seguro, mas ele tem algumasdeficiências.Currently, the IPC mechanisms have not been converted to theActualmente, os mecanismos de IPC não ter sido convertido para osuser_xxx suser_xxxso applications such as MySQL can not para aplicações como o MySQL não podebe run within a jail. ser executado dentro de uma prisão. Superuseraccess may have a very limited meaning within a jail, but there is noway to specify Acesso de superusuário pode ter um significado muitolimitado dentro de uma prisão, mas não há nenhuma maneira de especificarexactly what "very limited" means. exatamente o que significa "muitolimitados".*6.5.2.* *6.5.2.* *POSIX.1e Process Capabilities* *POSIX.1e capacidadesde processo*Posix has released a working draft that adds event auditing, accesscontrol lists, fine grained privileges, information Posix lançou umprojecto de trabalho que adiciona a auditoria de eventos, listas decontrole de acesso, privilégios de granulação fina, as informaçõeslabeling, and mandatory access control. etiquetagem, e controle deacesso obrigatório./42/ /42/------------------------------------------------------------------------*Page 51* *Page 51*

/Chapter 6./ /Capítulo 6./ /Secure Programming/ /Programação Segura/This is a work in progress and is the focus of the TrustedBSD(http://www.trustedbsd.org) project. Este é um trabalho em andamento e éo foco do projeto TrustedBSD (http://www.trustedbsd.org). Some of theinitial Alguns dos inicialwork has been committed to FreeBSD-current (cap_set_proc(3)). trabalhotem sido comprometida com o FreeBSD-CURRENT (cap_set_proc (3)).*6.6.* *6.6.* *Trust* *Confie*An application should never assume that anything about the usersenvironment is sane. Um aplicativo nunca deve assumir que qualquer coisasobre o ambiente de usuários é sã. This includes (but is certainly Istoinclui (mas é certamentenot limited to) : user input, signals, environment variables, resources,IPC, mmaps, the file system working directory, não limitado a): aentrada do usuário, os sinais, variáveis ��de ambiente, recursos, IPC,mmaps, o sistema de arquivos do diretório de trabalho,file descriptors, the # of open files, etc. descritores de arquivo, o #de arquivos abertos, etcYou should never assume that you can catch all forms of invalid inputthat a user might supply. Você nunca deve assumir que você pode pegartodas as formas de entrada inválida que um usuário pode fornecer.Instead, your Em vez disso, o seuapplication should use positive filtering to only allow a specific

Page 60: 139920579 Versao Traduzida de Book

subset of inputs that you deem safe. aplicativo deve usar filtragempositivas para permitir que apenas um subconjunto específico de inputsque você considere seguro. Improper data Dados incorretosvalidation has been the cause of many exploits, especially with CGIscripts on the world wide web. validação tem sido a causa de muitasfaçanhas, especialmente com scripts CGI na world wide web. For filenamesPara nomes de arquivosyou need to be extra careful about paths ("../", "/"), symbolic links,and shell escape characters. você precisa ser extremamente cuidadososobre os caminhos (".. /", "/"), links simbólicos e caracteres de escapede shell.Perl has a really cool feature called "Taint" mode which can be used toprevent scripts for using data derived outside Perl tem umacaracterística muito legal chamado modo "Mácula", que pode ser usadopara impedir que os scripts para o uso de dados provenientes de forathe program in an unsafe way. o programa de forma insegura. This modewill check command line arguments, environment variables, locale Estemodo irá verificar os argumentos de linha de comando, variáveis ��deambiente de localeinformation, the results of certain syscalls ( informações, osresultados de certos syscalls (readdir() readdir (), ,readlink() readlink (), ,getpwxxx() getpwxxx (), and all file input. E, em todas as entradas do arquivo.*6.7.* *6.7.* *Race Conditions* *Condições de corrida*A race condition is anomalous behavior caused by the unexpecteddependence on the relative timing of events. A condição de corrida é umcomportamento anômalo causado pela dependência inesperada no temporelativo de eventos. In Emother words, a programmer incorrectly assumed that a particular eventwould always happen before another. outras palavras, um programadorassume incorretamente que um determinado evento que sempre aconteceantes de outra.Some of the common causes of race conditions are signals, access checks,and file opens. Algumas das causas mais comuns de condições de corridasão sinais, verificações de acesso e abre o arquivo. Signals areasynchronous Sinais são assíncronasevents by nature so special care must be taken in dealing with them.eventos de natureza tão especial cuidado deve ser tomado para lidar comeles. Checking access with Verificando o acesso comaccess(2) de acesso (2)then em seguidaopen(2) abrir (2)is clearly non-atomic. é claramente não-atômica. Users can move files inbetween the two calls. Os usuários podem mover arquivos entre as duaschamadas. Instead, privileged applications Em vez disso, as aplicaçõesprivilegiadasshould deveriaseteuid() seteuid ()and then call e, em seguida, chamaropen() open ()directly. diretamente. Along the same lines, an application shouldalways set a proper Na mesma linha, um aplicativo deve sempre definiruma adequadaumask before umask antesopen() open ()to obviate the need for spurious para evitar a necessidade de espúrio

Page 61: 139920579 Versao Traduzida de Book

chmod() chmod ()calls. chamadas./43/ /43/------------------------------------------------------------------------*Page 52* *Page 52*

*III.* *III.* *Kernel* *Núcleo*------------------------------------------------------------------------*Page 53* *Page 53*

*Chapter 7.* *Capítulo 7.* *History of the Unix Kernel* *História doKernel Unix*Some history of the Unix/BSD kernel, system calls, how do processeswork, blocking, scheduling, threads (kernel), Um pouco de história dokernel do Unix / BSD, chamadas de sistema, como é que os processos detrabalho, bloqueio de programação, tópicos (kernel),context switching, signals, interrupts, modules, etc. troca de contexto,os sinais, as interrupções, módulos, etc/45/ /45/------------------------------------------------------------------------*Page 54* *Page 54*

*Chapter 8.* *Capítulo 8.* *Locking Notes* *Bloqueio Notas*/This chapter is maintained by the FreeBSD SMP Next Generation Project</ /Este capítulo é mantida pela SMP Next Generation Projeto FreeBSD <//[email protected]/ /[email protected]//>./ />./This document outlines the locking used in the FreeBSD kernel to permiteffective multi-processing within the Este documento descreve o bloqueiousado no kernel do FreeBSD para permitir eficaz multi-processamentodentro dokernel. kernel. Locking can be achieved via several means. O bloqueiopode ser conseguido através de vários meios. Data structures can beprotected by mutexes or lockmgr(9) locks. Estruturas de dados podem serprotegidos por (9) fechaduras semáforos ou lockmgr.A few variables are protected simply by always using atomic operationsto access them. Algumas variáveis ��são protegidos simplesmente sempreusando operações atômicas para acessá-los.*8.1.* *8.1.* *Mutexes* *Semáforos*A mutex is simply a lock used to guarantee mutual exclusion. Um mutex ésimplesmente um cadeado usado para garantir a exclusão mútua.Specifically, a mutex may only be owned by one entity Especificamente,um mutex só pode ser possuído por uma entidadeat a time. de cada vez. If another entity wishes to obtain a mutex thatis already owned, it must wait until the mutex is released. Se outraentidade deseja obter um mutex que já pertence, ele deve esperar até queo mutex seja liberado. In Emthe FreeBSD kernel, mutexes are owned by processes. o kernel FreeBSD,mutexes são de propriedade de processos.Mutexes may be recursively acquired, but they are intended to be heldfor a short period of time. Mutexes pode ser adquirido de formarecursiva, mas destinam-se a ser realizado durante um curto período detempo. Specifically, one Especificamente, umamay not sleep while holding a mutex. não pode dormir, mantendo um mutex.If you need to hold a lock across a sleep, use a lockmgr(9) lock. Sevocê precisa para realizar um bloqueio em um sono, use uma (9) bloqueiolockmgr.Each mutex has several properties of interest: Cada mutex tem váriaspropriedades de interesse:Variable Name Nome da variável

Page 62: 139920579 Versao Traduzida de Book

The name of the struct mtx variable in the kernel source. O nome davariável mtx struct no fonte do kernel.Logical Name Nome lógicoThe name of the mutex assigned to it by O nome do mutex que lhe éatribuída pormtx_init mtx_init. . This name is displayed in KTR trace messages and witness Esse nome éexibido em mensagens de rastreamento KTR e testemunhaserrors and warnings and is used to distinguish mutexes in the witnesscode. erros e avisos e é usado para distinguir semáforos no códigotestemunha.Type TipoThe type of the mutex in terms of the O tipo de mutex em termos daMTX_* Mtx_ *flags. flags. The meaning for each flag is related to its meaning as Osignificado de cada bandeira está relacionado ao seu significado comodocumented in mutex(9). documentada em mutex (9).MTX_DEF MTX_DEFA sleep mutex Um mutex sonoMTX_SPIN MTX_SPINA spin mutex Um spin mutexMTX_COLD MTX_COLDThis mutex is initialized very early. Este mutex é inicializado muitocedo. Thus, it must be declared via Assim, deve ser declarada viaMUTEX_DECLARE MUTEX_DECLARE, and the , E oMTX_COLD MTX_COLDflag bandeiramust be passed to deve ser passada paramtx_init mtx_init. ./46/ /46/------------------------------------------------------------------------*Page 55* *Page 55*

/Chapter 8./ /Capítulo 8./ /Locking Notes/ /Bloqueio Notas/MTX_TOPHALF MTX_TOPHALFThis spin mutex does not disable interrupts. Este mutex rotação nãodesabilitar interrupções.MTX_NORECURSE MTX_NORECURSEThis mutex is not allowed to recurse. Este mutex não é permitido recursivo.Protectees ProtecteesA list of data structures or data structure members that this entryprotects. Uma lista de estruturas de dados ou membros de estrutura dedados que esta entrada protege. For data structure members, the namePara os membros da estrutura de dados, o nomewill be in the form of structure name. /member name/ . será na forma denome de estrutura. /nome do membro./Dependent Functions Funções dependentesFunctions that can only be called if this mutex is held. Funções que sópodem ser chamados se este mutex é realizada.*Table 8-1.* *Tabela 8-1.* *Mutex List* *Mutex Lista**Variable Name* *Nome da variável**Logical Name* *Nome lógico**Type* *Tipo**Protectees* *Protectees**Dependent* *Dependente**Functions* *Funções*/47/ /47/------------------------------------------------------------------------

Page 63: 139920579 Versao Traduzida de Book

*Page 56* *Page 56*

/Chapter 8./ /Capítulo 8./ /Locking Notes/ /Bloqueio Notas/*Variable Name* *Nome da variável**Logical Name* *Nome lógico**Type* *Tipo**Protectees* *Protectees**Dependent* *Dependente**Functions* *Funções*sched_lock sched_lock“sched lock” "Lock sched"MTX_SPIN MTX_SPIN| |MTX_COLD MTX_COLD_gmonparam _gmonparam, ,cnt.v_swtch cnt.v_swtch, ,cp_time cp_time, ,curpriority curpriority, ,mtx. /mtx_blocked/ , mtx. /mtx_blocked,/mtx. /mtx_contested/ , mtx. /mtx_contested,/proc. /p_contested/ , proc. /p_contested,/proc. /p_blocked/ , proc. /p_blocked,/proc. /p_flag/ proc. /p_flag/( (P_PROFIL P_PROFILXXX, XXX,P_INMEM P_INMEM, ,P_SINTR P_SINTR, ,P_TIMEOUT P_TIMEOUT, ,P_SWAPINREQ P_SWAPINREQXXX, XXX,P_INMEN P_INMENXXX), XXX),proc. /p_nice/ , proc. /p_nice,/proc. /p_procq/ , proc. /p_procq,/proc. /p_blocked/ , proc. /p_blocked,/proc. /p_estcpu/ , proc. /p_estcpu,/proc. /p_nativepri/ , proc. /p_nativepri,/proc. /p_priority/ , proc. /p_priority,/proc. /p_usrpri/ , proc. /p_usrpri,/proc. /p_rtprio/ , proc. /p_rtprio,/proc. /p_rqindex/ , proc. /p_rqindex,/proc. /p_stats-/ /p_stats-Proc.//>p_prof/ , /> P_prof,/proc. /p_stats-/ /p_stats-Proc.//>p_ru/ , proc. /p_stat/ , />/ /P_ru,/ proc. /P_stat,/proc. /p_cpticks/ Proc. /p_cpticks/proc. /p_iticks/ , proc. /p_iticks,/proc. /p_uticks/ , proc. /p_uticks,/proc. /p_sticks/ , proc. /p_sticks,/proc. /p_swtime/ , proc. /p_swtime,/proc. /p_slptime/ , proc. /p_slptime,/proc. /p_runtime/ , proc. /p_runtime,/

Page 64: 139920579 Versao Traduzida de Book

proc. /p_pctcpu/ , proc. /p_pctcpu,/proc. /p_oncpu/ , proc. /p_oncpu,/proc. /p_asleep/ , proc. /p_asleep,/proc. /p_wchan/ , proc. /p_wchan,/proc. /p_wmesg/ , proc. /p_wmesg,/proc. /p_slpq/ , proc. /p_slpq,/proc. /p_vmspace/ proc. /p_vmspace/(XXX - in (XXX - emstatclock statclock), )pscnt pscnt, ,slpque slpque, ,itqueuebits itqueuebits, ,itqueues itqueues, ,rtqueuebits rtqueuebits, ,rtqueues rtqueues, ,queuebits queuebits, ,queues filas, ,idqueuebits idqueuebits, ,setrunqueue setrunqueue, ,remrunqueue remrunqueue, ,mi_switch mi_switch, ,chooseproc chooseproc, ,schedclock schedclock, ,resetpriority resetpriority, ,updatepri updatepri, ,maybe_resched maybe_resched, ,cpu_switch cpu_switch, ,cpu_throw cpu_throw/48/ /48/------------------------------------------------------------------------*Page 57* *Page 57*

/Chapter 8./ /Capítulo 8./ /Locking Notes/ /Bloqueio Notas/*Variable Name* *Nome da variável**Logical Name* *Nome lógico**Type* *Tipo**Protectees* *Protectees**Dependent* *Dependente**Functions* *Funções*vm86pcb_lock vm86pcb_lock“vm86pcb lock” "Lock vm86pcb"

Page 65: 139920579 Versao Traduzida de Book

MTX_DEF MTX_DEF| |MTX_COLD vm86pcb MTX_COLD vm86pcbvm86_bioscall vm86_bioscallGiant Gigante“Giant” "Gigante"MTX_DEF MTX_DEF| |MTX_COLD MTX_COLDnearly everything quase tudolots grande quantidadecallout_lock callout_lock“callout lock” "Chamada lock"MTX_SPIN MTX_SPINcallfree callfree, ,callwheel callwheel, ,nextsoftcheck nextsoftcheck, ,proc. /p_itcallout/ , proc. /p_itcallout,/proc. /p_slpcallout/ , proc. /p_slpcallout,/softticks softticks, ,ticks carrapatos*8.2.* *8.2.* *Lock Manager Locks* *Lock Manager Locks*Locks that are provided via the lockmgr(9) interface are lock managerlocks. Fechaduras que são fornecidos através do (9) Interface lockmgrsão bloqueios gerente de bloqueio. These locks are reader-writer locksand Esses bloqueios são bloqueios de leitor-gravador emay be held by a sleeping process. pode ser realizada por um processo dedormir.*Table 8-2.* *Tabela 8-2.* *lockmgr(9) Lock List* *lockmgr (9) Lista deBloqueio**Variable Name* *Nome da variável**Protectees* *Protectees*allproc_lock allproc_lockallproc zombproc pidhashtbl allproc zombproc pidhashtblproc. /p_list/ proc. /p_list/proc. /p_hash/ proc. /p_hash/nextpid nextpidproctree_lock proctree_lockproc. /p_chi/ proc. /p_chi/*8.3.* *8.3.* *Atomically Protected Variables* *Variáveis ��atomicamenteProtegidas*An atomically protected variable is a special variable that is notprotected by an explicit lock. Uma variável protegido atomicamente é umavariável especial que não está protegida por uma fechadura explícito.Instead, all data Em vez disso, todos os dadosaccesses to the variables use special atomic operations as described inatomic(9). acessos às variáveis ��usar operações atómicas especiais comodescrito na atómica (9). Very few variables are treated this Muitopoucas variáveis ��são tratados destaway, although other synchronization primitives such as mutexes areimplemented with atomically protected variables. Assim, embora outrosprimitivos de sincronização, como semáforos são implementados comvariáveis ��protegidos atomicamente.• •astpending astpending• •

Page 66: 139920579 Versao Traduzida de Book

mtx. /mtx_lock/ mtx. /mtx_lock//49/ /49/------------------------------------------------------------------------*Page 58* *Page 58*

*IV.* *IV.* *Memory Management* *Gerenciamento de Memória*------------------------------------------------------------------------*Page 59* *Page 59*

*Chapter 9.* *Capítulo 9.* *Virtual Memory System* *Sistema de MemóriaVirtual**9.1.* *9.1.* *The FreeBSD VM System* *O Sistema VM FreeBSD*/Contributed by Matthew Dillon </ /Contribuição de Matthew Dillon <//[email protected]/ /[email protected]//>./ />./ /6 Feb 1999/ /6 de fevereiro de 1999/*9.1.1.* *9.1.1.* *Management of physical memory—* *Gestão de memóriafísica**vm_page_t* *vm_page_t*Physical memory is managed on a page-by-page basis through the Memóriafísica é gerenciado em uma base página por página por meio dovm_page_t vm_page_tstructure. estrutura. Pages of physical memory Páginas de memória físicaare categorized through the placement of their respective sãoclassificados por meio da colocação do respectivovm_page_t vm_page_tstructures on one of several paging queues. estruturas sobre uma dasvárias filas de paging.A page can be in a wired, active, inactive, cache, or free state. Apágina pode estar em um fio, ativo, inativo, cache, ou estado livre.Except for the wired state, the page is typically placed Exceto para oestado ligado, a página é geralmente colocadoin a doubly link list queue representing the state that it is in. Wiredpages are not placed on any queue. em um link lista fila duplamenterepresentando o estado que está dentro páginas com fio não são colocadosem qualquer fila.FreeBSD implements a more involved paging queue for cached and freepages in order to implement page coloring. FreeBSD implementa uma filade paginação mais envolvido para páginas em cache e livre, a fim deimplementar a página de coloração.Each of these states involves multiple queues arranged according to thesize of the processor's L1 and L2 caches. Cada um destes estados envolvevárias filas organizadas de acordo com o tamanho da L1 do processador ecaches L2.When a new page needs to be allocated, FreeBSD attempts to obtain onethat is reasonably well aligned from the Quando uma nova página tem deser atribuída, FreeBSD tenta obter um que seja razoavelmente bemalinhados dopoint of view of the L1 and L2 caches relative to the VM object the pageis being allocated for. ponto de vista dos caches L1 e L2 em relação aoobjeto VM a página está sendo alocado para.Additionally, a page may be held with a reference count or locked with abusy count. Além disso, uma página pode ser realizada com uma contagemde referência ou bloqueado com uma contagem de ocupado. The VM systemalso O sistema VM tambémimplements an “ultimate locked” state for a page using the PG_BUSY bitin the page's flags. implementa um "final bloqueado" estado para umapágina usando o bit PG_BUSY em bandeiras da página.In general terms, each of the paging queues operates in a LRU fashion.Em termos gerais, cada uma das filas de paging opera de uma forma LRU. Apage is typically placed in a wired or active A página é geralmente

Page 67: 139920579 Versao Traduzida de Book

colocado em uma rede com fio ou ativostate initially. indicar inicialmente. When wired, the page is usuallyassociated with a page table somewhere. Quando conectado, a página égeralmente associada a uma tabela de página em algum lugar. The VMsystem ages the As idades sistema VM ospage by scanning pages in a more active paging queue (LRU) in order tomove them to a less-active paging queue. página, a digitalização depáginas em uma fila de paginação mais ativo (LRU), a fim de movê-lospara uma fila de paginação menos ativos.Pages that get moved into the cache are still associated with a VMobject but are candidates for immediate reuse. Páginas que se mudarampara o cache ainda está associado a um objeto VM, mas são candidatos àreutilização imediata.Pages in the free queue are truly free. Páginas na fila livre sãoverdadeiramente livres. FreeBSD attempts to minimize the number of pagesin the free queue, but a FreeBSD tenta minimizar o número de páginas nafila livre, mas acertain minimum number of truly free pages must be maintained in orderto accommodate page allocation at determinado número mínimo de páginasverdadeiramente livres deve ser mantida, a fim de acomodar a alocação depáginainterrupt time. interromper o tempo.If a process attempts to access a page that does not exist in its pagetable but does exist in one of the paging queues ( Se um processo tentaacessar uma página que não existe em sua tabela de página, mas nãoexiste em uma das filas de paginação (such as the inactive or cache queues), a relatively inexpensive pagereactivation fault occurs which causes the page to tais como as filasinativos ou cache), uma falha de reativação página relativamente baratoocorre que faz com que a páginabe reactivated. ser reativado. If the page does not exist in systemmemory at all, the process must block while the page is brought in Se apágina não existe na memória do sistema em tudo, o processo devebloquear enquanto a página é trazidafrom disk. do disco.FreeBSD dynamically tunes its paging queues and attempts to maintainreasonable ratios of pages in the various FreeBSD dinamicamente músicassuas filas de paginação e as tentativas de manter relações razoáveis ��de páginas nas diversasqueues as well as attempts to maintain a reasonable breakdown of cleanvs dirty pages. filas, bem como as tentativas de manter um colapsorazoável vs páginas sujas limpas. The amount of rebalancing A quantidadede reequilíbriothat occurs depends on the system's memory load. que ocorre depende dacarga da memória do sistema. This rebalancing is implemented by thepageout daemon and Este reequilíbrio é implementado pelo daemon pageout einvolves laundering dirty pages (syncing them with their backing store),noticing when pages are activity referenced envolve lavagem de páginassujas (sincronizando-os com a sua loja de suporte), percebendo quando aspáginas são atividade referenciada(resetting their position in the LRU queues or moving them betweenqueues), migrating pages between queues when (Repor a sua posição nasfilas de LRU ou movê-los entre filas), migrando páginas entre filas quandothe queues are out of balance, and so forth. as filas estão fora deequilíbrio, e assim por diante. FreeBSD's VM system is willing to take areasonable number of Sistema VM do FreeBSD está disposto a assumir umnúmero razoável de/51/ /51/------------------------------------------------------------------------*Page 60* *Página 60*

Page 68: 139920579 Versao Traduzida de Book

/Chapter 9./ /Capítulo 9./ /Virtual Memory System/ /Sistema de MemóriaVirtual/reactivation page faults to determine how active or how idle a pageactually is. falhas de página de reativação para determinar como ativoou inativo como uma página realmente é. This leads to better decisionsbeing Isso leva a melhores decisões sendomade as to when to launder or swap-out a page. feito quanto ao momentode lavar ou trocar-out uma página.*9.1.2.* *9.1.2.* *The unified buffer cache—* *O cache-buffer unificado**vm_object_t* *vm_object_t*FreeBSD implements the idea of a generic “VM object”. FreeBSD implementaa idéia de um genérico "objeto VM". VM objects can be associated withbacking store of various Objetos VM pode ser associado com armazenamentode apoio de váriostypes—unbacked, swap-backed, physical device-backed, or file-backedstorage. tipos, sem lastro troca-backed, física dispositivo suportado,ou arquivo-backed armazenamento. Since the filesystem uses the same Umavez que o sistema de ficheiros utiliza a mesmaVM objects to manage in-core data relating to files, the result is aunified buffer cache. Objetos VM para gerenciar dados em centraisrelativas aos arquivos, o resultado é um buffer cache unificado.VM objects can be /shadowed/ . Objetos VM pode ser /sombreada./ That is,they can be stacked on top of each other. Isto é, eles podem serempilhados em cima uns dos outros. For example, you might have a Porexemplo, você pode ter umswap-backed VM object stacked on top of a file-backed VM object in orderto implement a MAP_PRIVATE troca-backed objeto VM empilhados em cima deum objeto VM arquivo com backup, a fim de implementar um MAP_PRIVATEmmap()ing. mmap () ing. This stacking is also used to implement varioussharing properties, including, copy-on-write, for forked Esteempilhamento também é usado para implementar várias propriedades decompartilhamento, incluindo, copy-on-write, para bifurcadaaddress spaces. espaços de endereço.It should be noted that a Deve notar-se que umavm_page_t vm_page_tcan only be associated with one VM object at a time. só pode serassociada com um objeto da VM de cada vez. The VM object O objeto da VMshadowing implements the perceived sharing of the same page acrossmultiple instances. sombreamento implementa a partilha percebido damesma página em várias instâncias.*9.1.3.* *9.1.3.* *Filesystem I/O—* *Filesystem I/O-**struct buf* *struct buf*vnode-backed VM objects, such as file-backed objects, generally need tomaintain their own clean/dirty info objetos VM vnode apoiados, comoarquivos apoiados objetos, geralmente precisam manter sua própriainformação limpa / sujaindependent from the VM system's idea of clean/dirty. independente daidéia do sistema VM de limpa / suja. For example, when the VM systemdecides to synchronize a Por exemplo, quando o sistema VM parasincronizar um decidephysical page to its backing store, the VM system needs to mark the pageclean before the page is actually written to página física para sua lojade apoio, o sistema VM precisa marcar a página em branco antes que apágina é realmente escrito paraits backing s tore. o seu apoio s rasgou. Additionally, filesystems needto be able to map portions of a file or file metadata into KVM in Alémdisso, os sistemas de arquivos precisam ser capazes de mapear partes deum arquivo ou arquivo de metadados em KVM emorder to operate on it. Para operar sobre ele.

Page 69: 139920579 Versao Traduzida de Book

The entities used to manage this are known as filesystem buffers, Asentidades usadas para gerenciar essa são conhecidas como buffers dosistema de arquivos,struct buf struct buf's, and also known as 'S, e também conhecido comobp bp's. 'S. When a Quando umfilesystem needs to operate on a portion of a VM object, it typicallymaps part of the object into a struct buf and the sistema de arquivosprecisa para operar em uma parte de um objeto de VM, que normalmentemapeia parte do objeto em um buf struct eomaps the pages in the struct buf into KVM. mapeia as páginas no bufstruct em KVM. In the same manner, disk I/O is typically issued bymapping portions of Da mesma forma, o disco I / O é normalmente emitidapor porções de mapeamento deobjects into buffer structures and then issuing the I/O on the bufferstructures. objetos em estruturas de buffer e em seguida, emitir o I / Oem estruturas de buffer. The underlying vm_page_t's are O subjacentevm_page_t de sãotypically busied for the duration of the I/O. normalmente ocupava para aduração do I / O. Filesystem buffers also have their own notion of beingbusy, which is Buffers do sistema de arquivos também têm a sua próprianoção de ser ocupado, o que éuseful to filesystem driver code which would rather operate onfilesystem buffers instead of hard VM pages. útil para o código dodriver do sistema de arquivos que preferem operar em buffers do sistemade arquivos em vez de páginas VM difíceis.FreeBSD reserves a limited amount of KVM to hold mappings from structbufs, but it should be made clear that this FreeBSD reserva umaquantidade limitada de KVM para realizar mapeamentos de struct bufs, masdeve ficar claro que esteKVM is used solely to hold mappings and does not limit the ability tocache data. KVM é usado apenas para manter mapeamentos e não limita acapacidade de dados em cache. Physical data caching is strictly a Cachede dados físico é estritamente umafunction of função devm_page_t vm_page_t's, not filesystem buffers. 'S, não buffers do sistema de arquivos.However, since filesystem buffers are used placehold I/O, they do Noentanto, como buffers do sistema de arquivos são usados ��placehold I /O, que fazeminherently limit the amount of concurrent I/O possible. inerentementelimitar a quantidade de Concurrent I / O possível. As there are usuallya few thousand filesystem buffers Como geralmente há alguns milhares debuffers do sistema de arquivosavailable, this is not usually a problem. disponível, isto não énormalmente um problema./52/ /52/------------------------------------------------------------------------*Page 61* *Page 61*

/Chapter 9./ /Capítulo 9./ /Virtual Memory System/ /Sistema de MemóriaVirtual/*9.1.4.* *9.1.4.* *Mapping Page Tables - vm_map_t, vm_entry_t**Mapeamento de página Tabelas - vm_map_t, vm_entry_t*FreeBSD separates the physical page table topology from the VM system.FreeBSD separa a topologia da tabela de página físico do sistema VM. Allhard per-process page tables can be Todos por processo mesas rígidospágina pode serreconstructed on the fly and are usually considered throwaway.

Page 70: 139920579 Versao Traduzida de Book

reconstruído em tempo real e são geralmente considerados descartáveis.Special page tables such as those managing KVM are Tabelas especiais depágina, como aqueles que gerenciam KVM sãotypically permanently preallocated. tipicamente pré-alocadospermanentemente. These page tables are not throwaway. Estas tabelas depáginas não são descartáveis.FreeBSD associates portions of vm_objects with address ranges in virtualmemory through FreeBSD associados porções de vm_objects com intervalosde endereços de memória virtual por meio devm_map_t vm_map_tand evm_entry_t vm_entry_tstructures. estruturas. Page tables are directly synthesized from theTabelas de páginas são diretamente sintetizado a partir dovm_map_t vm_map_t/ /vm_entry_t vm_entry_t/ /vm_object_t vm_object_thierarchy. hierarquia. Remember when I mentioned that physical pages areonly directly associated with a Lembra quando eu mencionei que páginasfísicas só estão diretamente associados com avm_object vm_object. . Well, Bem,that isn't quite true. que não é bem verdade.vm_page_t vm_page_t's are also linked into page tables that they are actively associatedwith. 'S também estão ligados em tabelas de páginas que estãoactivamente associados. One Umvm_page_t vm_page_tcan be linked into several /pmaps/ , as page tables are called. pode serligado em várias /pmaps,/ como tabelas de páginas são chamados. However,the hierarchical association holds No entanto, a associação hierárquicamantémso all references to the same page in the same object reference the samepara todas as referências para a mesma página na mesma referência deobjeto da mesmavm_page_t vm_page_tand thus give us buffer cache e assim nos dar buffer cacheunification across the board. unificação através da placa.*9.1.5.* *9.1.5.* *KVM Memory Mapping* *KVM Mapeamento de Memória*FreeBSD uses KVM to hold various kernel structures. FreeBSD usa KVM paramanter várias estruturas do kernel. The single largest entity held inKVM is the filesystem buffer O único maior entidade realizada em KVM é obuffer do sistema de arquivoscache. cache. That is, mappings relating to Ou seja, os mapeamentosrelativas àstruct buf struct bufentities. entidades.Unlike Linux, FreeBSD does NOT map all of physical memory into KVM. Aocontrário de Linux, FreeBSD não mapeia toda a memória física em KVM.This means that FreeBSD can handle Isto significa que o FreeBSD podemanipularmemory configurations up to 4G on 32 bit platforms. configurações dememória de até 4G em plataformas de 32 bits. In fact, if the mmu werecapable of it, FreeBSD could Na verdade, se o mmu eram capazes disso,FreeBSD poderiatheoretically handle memory configurations up to 8TB on a 32 bitplatform. teoricamente lidar com configurações de memória de até 8 TB emuma plataforma de 32 bits. However, since most 32 bit platforms are No

Page 71: 139920579 Versao Traduzida de Book

entanto, como a maioria das plataformas de 32 bits sãoonly capable of mapping 4GB of ram, this is a moot point. só é capaz demapear 4GB de memória RAM, este é um ponto discutível.KVM is managed through several mechanisms. KVM é gerido através devários mecanismos. The main mechanism used to manage KVM is the /zoneallocator/ . O principal mecanismo utilizado para gerenciar KVM é o/alocador zona./The zone allocator takes a chunk of KVM and splits it up intoconstant-sized blocks of memory in order to allocate a O alocador zonaleva um pedaço de KVM e divide-se em blocos de tamanho constante dememória, a fim de alocar umspecific type of structure. tipo específico de estrutura. You can useVocê pode usarvmstat -m vmstat-mto get an overview of current KVM utilization broken down by para obteruma visão geral da utilização KVM actual, porzone. zona.*9.1.6.* *9.1.6.* *Tuning the FreeBSD VM system* *Ajustando o sistema VMFreeBSD*A concerted effort has been made to make the FreeBSD kernel dynamicallytune itself. Um esforço tem sido feito para tornar o kernel FreeBSDajustar-se dinamicamente. Typically you do not need to Normalmente, vocênão precisamess with anything beyond the mexer com nada além domaxusers maxusersand eNMBCLUSTERS NMBCLUSTERSkernel config options. opções de configuração do kernel. That is, kernelcompilation Ou seja, a compilação do kerneloptions specified in (typically) opções especificadas no (tipicamente)/usr/src/sys/i386/conf/ /CONFIG_FILE/ / Usr/src/sys/i386/conf //CONFIG_FILE/. . A description of all available kernel A descrição de todos os kerneldisponívelconfiguration options can be found in opções de configuração podem serencontrados em/usr/src/sys/i386/conf/LINT / Usr/src/sys/i386/conf/LINT. .In a large system configuration you may wish to increase Em umaconfiguração de sistema de grande você pode desejar aumentarmaxusers maxusers. . Values typically range from 10 to 128. Valores tipicamente variar de10 a 128. Note Notathat raising que o aumentomaxusers maxuserstoo high can cause the system to overflow available KVM resulting inunpredictable demasiado elevada pode causar o sistema para transbordarKVM disponíveis resultando em imprevisíveloperation. operação. It is better to leave maxusers at some reasonablenumber and add other options, such as É melhor deixar maxusers em algumnúmero razoável e adicionar outras opções, tais comoNMBCLUSTERS NMBCLUSTERS, to , Aincrease specific resources. aumentar os recursos específicos./53/ /53/------------------------------------------------------------------------*Page 62* *Page 62*

/Chapter 9./ /Capítulo 9./ /Virtual Memory System/ /Sistema de MemóriaVirtual/

Page 72: 139920579 Versao Traduzida de Book

If your system is going to use the network heavily, you may want toincrease Se o seu sistema vai usar a rede fortemente, você pode quereraumentarNMBCLUSTERS NMBCLUSTERS. . Typical values range Faixa de valores típicosfrom 1024 to 4096. 1024-4096.The ONBUF NBUFparameter is also traditionally used to scale the system. parâmetrotambém é tradicionalmente usado para dimensionar o sistema. Thisparameter determines the amount of KVA the Este parâmetro determina aquantidade de KVA asystem can use to map filesystem buffers for I/O. sistema pode ser usadopara mapear buffers do sistema de arquivos para I / O. Note that thisparameter has nothing whatsoever to do with the Note-se que esteparâmetro não tem nada a ver com ounified buffer cache! buffer cache unificado! This parameter isdynamically tuned in 3.0-CURRENT and later kernels and should generallyEste parâmetro é ajustado dinamicamente em kernels 3.0-CURRENT e maistarde e geralmente devenot be adjusted manually. não ser ajustado manualmente. We recommendthat you /not/ try to specify an Nós recomendamos que você /não/ tenteespecificar umNBUF NBUFparameter. parâmetro. Let the system pick it. Deixe o sistema pegá-lo.Too Tambémsmall a value can result in extremely inefficient filesystem operationwhile too large a value can starve the page pequeno valor pode resultarem operação de sistema de arquivos extremamente ineficiente, enquanto umvalor muito grande pode morrer de fome a páginaqueues by causing too many pages to become wired down. filas por causarmuitas páginas para se tornar fio para baixo.By default, FreeBSD kernels are not optimized. Por padrão, o kernelFreeBSD não são otimizados. You can set debugging and optimization flagswith the Você pode definir de depuração e optimização bandeiras com omakeoptions makeoptionsdirective in the kernel configuration. directiva na configuração dokernel. Note that you should not use Note que você não deve usar-g -Gunless you can accommodate a menos que você pode acomodarthe large (typically 7 MB+) kernels that result. os grandes (tipicamente7 MB +) kernels esse resultado.makeoptions makeoptionsDEBUG="-g" DEBUG = "-g"makeoptions makeoptionsCOPTFLAGS="-O -pipe" COPTFLAGS = "-O-pipe"Sysctl provides a way to tune kernel parameters at run-time. Sysctlfornece uma maneira de ajustar os parâmetros do kernel em tempo deexecução. You typically do not need to mess with any of the sysctl Vocênormalmente não precisa mexer com qualquer um dos sysctlvariables, especially the VM related ones. variáveis, especialmente asVM relacionadas.Run time VM and system tuning is relatively straightforward. Tempo deexecução VM e ajuste do sistema é relativamente simples. First, usesoftupdates on your UFS/FFS filesystems Primeiro, use softupdates em seusistema de arquivos UFS / FFSwhenever possible. sempre que possível./usr/src/contrib/sys/softupdates/README / Usr / src / contrib / sys /softupdates / READMEcontains instructions (and restrictions) on contém instruções (e

Page 73: 139920579 Versao Traduzida de Book

restrições) sobrehow to configure it up. como configurá-lo para cima.Second, configure sufficient swap. Em segundo lugar, configurar permutasuficiente. You should have a swap partition configured on each physicaldisk, up to four, Você deve ter uma partição swap configurado em cadadisco físico, até quatro,even on your “work” disks. mesmo em seus discos "trabalho". You shouldhave at least 2x the swap space as you have main memory, and possiblyeven Você deve ter pelo menos 2x o espaço de swap que você tenha memóriaprincipal, e possivelmente até mesmomore if you do not have a lot of memory. mais se você não tem um montede memória. You should also size your swap partition based on themaximum memory Você deve também o tamanho do seu partição swap com basena memória máximaconfiguration you ever intend to put on the machine so you do not haveto repartition your disks later on. configuração que você já pretendecolocar na máquina, assim você não tem que repartir seus discos maistarde. If you want Se você quiserto be able to accommodate a crash dump, your first swap partition mustbe at least as large as main memory and para ser capaz de acomodar umdespejo de memória, sua primeira partição swap deve ser pelo menos tãogrande como a memória principal e/var/crash / Var / crashmust have sufficient free space to hold the dump. deve ter espaço livresuficiente para armazenar o lixo.NFS-based swap is perfectly acceptable on -4.x or later systems, but youmust be aware that the NFS server will take Troca baseada em NFS éperfeitamente aceitável no 4.x ou sistemas posteriores, mas você deveestar ciente de que o servidor NFS vai demorarthe brunt of the paging load. o peso da carga de paginação./54/ /54/------------------------------------------------------------------------*Page 63* *Page 63*

*Chapter 10.* *Capítulo 10.* *DMA* *DMA**10.1.* *10.1.* *DMA: What it is and How it Works* *DMA: O que é e comofunciona*/Copyright © 1995,1997 Frank Durda IV </ /Copyright © 1995,1997 FrankDurda IV <//[email protected]/ /[email protected]//>, All Rights Reserved./ /> Todos os direitos reservados./ /10 December1996./ /10 de dezembro de 1996./ /Last/ /Último//Update 8 October 1997./ /Atualizar 08 de outubro de 1997./Direct Memory Access (DMA) is a method of allowing data to be moved fromone location to another in a computer Acesso Direto à Memória (DMA) é ummétodo de permitir que os dados sejam transferidos de um local paraoutro em um computadorwithout intervention from the central processor (CPU). sem a intervençãodo processador central (CPU).The way that the DMA function is implemented varies between computerarchitectures, so this discussion will limit A maneira que a função DMAé implementada varia entre arquiteturas de computadores, assim que estadiscussão vai limitaritself to the implementation and workings of the DMA subsystem on theIBM Personal Computer (PC), the IBM -se à implementação e funcionamentodo subsistema DMA no IBM Personal Computer (PC), a IBMPC/AT and all of its successors and clones. PC / AT e todos os seussucessores e clones.The PC DMA subsystem is based on the Intel 8237 DMA controller. Osubsistema DMA PC baseia-se no controlador Intel 8237 de DMA. The 8237

Page 74: 139920579 Versao Traduzida de Book

contains four DMA channels that can O 8237 contém quatro canais DMA quepodebe programmed independently and any one of the channels may be active atany moment. ser programado de forma independente e em qualquer um doscanais pode ser activo a qualquer momento. These channels are Essescanais sãonumbered 0, 1, 2 and 3. numerados de 0, 1, 2 e 3. Starting with thePC/AT, IBM added a second 8237 chip, and numbered those channels 4, 5,Começando com o PC / AT, IBM adicionado um segundo chip de 8237, econtados os canais 4, 5,6 and 7. 6 e 7.The original DMA controller (0, 1, 2 and 3) moves one byte in eachtransfer. O controlador de DMA inicial (0, 1, 2 e 3) move-se um byte decada transferência. The second DMA controller (4, 5, 6, O segundocontrolador de DMA (4, 5, 6,and 7) moves 16-bits from two adjacent memory locations in eachtransfer, with the first byte always coming from an e 7) move 16 bits apartir de duas localizações de memória adjacentes em cada transferência,com o primeiro byte vindo sempre a partir de umeven-numbered address. endereço par. The two controllers are identicalcomponents and the difference in transfer size is caused by Os doiscontroladores de componentes são idênticos e a diferença de tamanho detransferência é causada pelathe way the second controller is wired into the system. a maneira como osegundo controlador é ligado ao sistema.The 8237 has two electrical signals for each channel, named DRQ and-DACK. O 8237 tem dois sinais elétricos para cada canal, chamado DRQe-DACK. There are additional signals with the Existem sinais adicionaiscom onames HRQ (Hold Request), HLDA (Hold Acknowledge), -EOP (End ofProcess), and the bus control signals nomes HRQ (Hold Request), HLDA(Hold Acknowledge),-EOP (Fim do processo), e os sinais de controle deônibus-MEMR (Memory Read), -MEMW (Memory Write), -IOR (I/O Read), and -IOW(I/O Write). -MEMR (Leia Memória),-MEMW (gravação em memória),-IOR (I /O Read), e IOW (I / O Write).The 8237 DMA is known as a “fly-by” DMA controller. O DMA 8237 éconhecido como um "fly-by" controlador de DMA. This means that the databeing moved from one location to Isto significa que os dados sejamtransferidos de um local paraanother does not pass through the DMA chip and is not stored in the DMAchip. outro não passa através do chip de DMA e não é armazenado no chipde DMA. Subsequently, the DMA can only Em seguida, o DMA só podetransfer data between an I/O port and a memory address, but not betweentwo I/O ports or two memory locations. transferência de dados entre umaporta de I / O e um endereço de memória, mas não entre as duas portas deI / O ou dois locais de memória.*Note:* The 8237 does allow two channels to be connected together toallow memory-to-memory DMA operations *Nota:* O 8237 não permite doiscanais a serem ligados entre si para permitir que as operações de DMA dememória para memóriain a non-“fly-by” mode, but nobody in the PC industry uses this scarceresource this way since it is faster to move em um não-"fly-by" modo,mas ninguém na indústria do PC utiliza este recurso escasso dessa forma,pois é mais rápido para moverdata between memory locations using the CPU. dados entre posições dememória usando a CPU.In the PC architecture, each DMA channel is normally activated only whenthe hardware that uses a given DMA Na arquitetura PC, cada canal de DMAé normalmente ativado apenas quando o hardware que usa um determinado DMA

Page 75: 139920579 Versao Traduzida de Book

channel requests a transfer by asserting the DRQ line for that channel.solicita um canal de transferência, afirmando a linha DRQ para esse canal./55/ /55/------------------------------------------------------------------------*Page 64* *Página 64*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/*10.1.1.* *10.1.1.* *A Sample DMA transfer* *A Amostra transferência DMA*Here is an example of the steps that occur to cause and perform a DMAtransfer. Aqui é um exemplo dos passos que ocorrem para causar eexecutar uma transferência de DMA. In this example, the floppy diskNeste exemplo, o disco flexívelcontroller (FDC) has just read a byte from a diskette and wants the DMAto place it in memory at location controlador (FDC) acaba de ler um bytede um disquete e quer que o DMA para colocá-lo na memória local0x00123456. 0x00123456. The process begins by the FDC asserting the DRQ2signal (the DRQ line for DMA channel 2) to alert O processo começa pelaafirmação do sinal FDC DRQ2 (a linha DRQ canal DMA 2) para alertarthe DMA controller. o controlador de DMA.The DMA controller will note that the DRQ2 signal is asserted. Ocontrolador de DMA vai notar que o sinal DRQ2 é afirmado. The DMAcontroller will then make sure that DMA O controlador de DMA, então,certifique-se que o DMAchannel 2 has been programmed and is unmasked (enabled). o canal 2 foiprogramado e é desmascarado (habilitados). The DMA controller also makessure that none of the O controlador de DMA também garante que nenhum dosother DMA channels are active or want to be active and have a higherpriority. outros canais DMA são ativos ou quer ser ativo e ter umaprioridade maior. Once these checks are complete, the Uma vez que estasverificações forem concluídas, oDMA asks the CPU to release the bus so that the DMA may use the bus. DMApede ao CPU para libertar o barramento de modo que podem usar o DMA doautocarro. The DMA requests the bus by asserting the O DMA solicita oônibus, afirmando aHRQ signal which goes to the CPU. HRQ sinal que vai para a CPU.The CPU detects the HRQ signal, and will complete executing the currentinstruction. A CPU detecta o sinal HRQ, e vai completar a execução dainstrução corrente. Once the processor has Uma vez que o processador temreached a state where it can release the bus, it will. chegou a umestado onde ele pode liberar o ônibus, ele vai. Now all of the signalsnormally generated by the CPU (-MEMR, Agora, todos os sinais normalmentegeradas pela CPU (-MEMR,-MEMW, -IOR, -IOW and a few others) are placed in a tri-stated condition(neither high or low) and then the CPU -MEMW, IOR-,-IOW e alguns outros)são colocados numa condição de tri-determinado (não de alta ou baixa) e,em seguida, a CPUasserts the HLDA signal which tells the DMA controller that it is now incharge of the bus. afirma o sinal HLDA que indica ao controlador DMA queestá agora a cargo do ônibus.Depending on the processor, the CPU may be able to execute a fewadditional instructions now that it no longer has Dependendo doprocessador, a CPU pode ser capaz de executar algumas instruçõesadicionais, que agora já não temthe bus, but the CPU will eventually have to wait when it reaches aninstruction that must read something from o ônibus, mas a CPU acabarápor ter de esperar quando se atinge uma instrução que deve ler algo dememory that is not in the internal processor cache or pipeline. memóriaque não está no cache do processador interno ou pipeline.Now that the DMA “is in charge”, the DMA activates its -MEMR, -MEMW,-IOR, -IOW output signals, and the Sinais de saída, agora que o DMA

Page 76: 139920579 Versao Traduzida de Book

"está no comando", o DMA ativa seu-MEMR, MEMW-,-IOR,-IOW, e osaddress outputs from the DMA are set to 0x3456, which will be used todirect the byte that is about to transferred to saídas de endereços doDMA são ajustados para 0x3456, que irá ser utilizado para orientar obyte que é transferida para sobre aa specific memory location. um local específico da memória.The DMA will then let the device that requested the DMA transfer knowthat the transfer is commencing. O DMA, então, deixar o dispositivo quesolicitou a transferência DMA sabem que a transferência está começando.This is Isto édone by asserting the -DACK signal, or in the case of the floppy diskcontroller, -DACK2 is asserted. feito, afirmando sinal the-DACK, ou nocaso de o controlador de disquete,-DACK2 é afirmado.The floppy disk controller is now responsible for placing the byte to betransferred on the bus Data lines. O controlador de disquete é agoraresponsável pela colocação do byte a ser transferido nas linhas dobarramento de dados. Unless the A menos que ofloppy controller needs more time to get the data byte on the bus (andif the peripheral does need more time it alerts controlador de disqueteprecisa de mais tempo para obter o byte de dados no ônibus (e se operiférico não precisa de mais tempo ele alertathe DMA via the READY signal), the DMA will wait one DMA clock, and thende-assert the -MEMW and -IOR o DMA via o sinal READY), o DMA vai esperarum DMA relógio e, em seguida, de-afirmar o MEMW e IORsignals so that the memory will latch and store the byte that was on thebus, and the FDC will know that the byte has sinais de modo que amemória de fecho e guardar o byte que estava no autocarro, eo FDC saberáque o byte tembeen transferred. foi transferido.Since the DMA cycle only transfers a single byte at a time, the FDC nowdrops the DRQ2 signal, so the DMA knows Uma vez que o ciclo de DMAapenas transfere um byte único de cada vez, o FDC agora cai DRQ2 osinal, de modo que o DMA sabethat it is no longer needed. que não é mais necessário. The DMA willde-assert the -DACK2 signal, so that the FDC knows it must stop placingO DMA será de-afirmar o DACK2 sinal, para que o FDC sabe que deve pararde colocardata on the bus. dados sobre o barramento.The DMA will now check to see if any of the other DMA channels have anywork to do. O DMA agora irá verificar para ver se algum dos outroscanais DMA têm qualquer trabalho a fazer. If none of the channels haveSe nenhum dos canais têmtheir DRQ lines asserted, the DMA controller has completed its work andwill now tri-state the -MEMR, -MEMW, suas linhas DRQ afirmou, ocontrolador de DMA concluiu seu trabalho e agora tri-state o MEMR,-MEMW,-IOR, -IOW and address signals. -IOR,-IOW sinais de endereço e.Finally, the DMA will de-assert the HRQ signal. Finalmente, o DMA seráde-afirmar o sinal HRQ. The CPU sees this, and de-asserts the HOLDAsignal. A CPU vê isso, e de-afirma o sinal Holda. Now the Agora, oCPU activates its -MEMR, -MEMW, -IOR, -IOW and address lines, and itresumes executing instructions and CPU ativa seu-MEMR, MEMW-,-IOR, IOW-elinhas de endereço, e ele volta a executar as instruções eaccessing main memory and the peripherals. acessar a memória principal eos periféricos./56/ /56/------------------------------------------------------------------------*Page 65* *Página 65*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/For a typical floppy disk sector, the above process is repeated 512

Page 77: 139920579 Versao Traduzida de Book

times, once for each byte. Para um sector típica de disquete, o processoanterior é repetido 512 vezes, uma para cada byte. Each time a byte isCada vez que um byte étransferred, the address register in the DMA is incremented and thecounter in the DMA that shows how many bytes transferido, o registo deendereços no DMA é incrementado eo contador no DMA que mostra quantos bytesare to be transferred is decremented. estão a ser transferidos é diminuída.When the counter reaches zero, the DMA asserts the EOP signal, whichindicates that the counter has reached zero Quando o contador atingirzero, o DMA afirma o sinal EOP, o que indica que o contador chegar a zeroand no more data will be transferred until the DMA controller isreprogrammed by the CPU. e não mais dados serão transferidos até que ocontrolador de DMA é reprogramado pela CPU. This event is also calledEste evento é também chamadathe Terminal Count (TC). Conde Terminal (TC). There is only one EOPsignal, and since only DMA channel can be active at any instant, Háapenas um sinal EOP, e uma vez que só canal DMA pode estar ativo emqualquer instante,the DMA channel that is currently active must be the DMA channel thatjust completed its task. o canal de DMA que está ativo deve ser o canalde DMA, que acaba de completar sua tarefa.If a peripheral wants to generate an interrupt when the transfer of abuffer is complete, it can test for its -DACKn Se um periférico querpara gerar uma interrupção, quando a transferência de um tampão écompleta, pode testar para a sua-DACKnsignal and the EOP signal both being asserted at the same time. sinal eo sinal de EOP sendo ambos afirmado, ao mesmo tempo. When that happens,it means the DMA will not Quando isso acontece, significa que o DMA não vaitransfer any more information for that peripheral without interventionby the CPU. transferência de mais alguma informação para que periféricosem intervenção do CPU. The peripheral can then assert one O periféricopode, então, afirmar umaof the interrupt signals to get the processors' attention. dos sinais deinterrupção para chamar a atenção dos processadores. In the PCarchitecture, the DMA chip itself is not capable of Na arquitectura dePC, o chip DMA si só não é capaz degenerating an interrupt. gerar uma interrupção. The peripheral and itsassociated hardware is responsible for generating any interrupt that Operiférico e seu hardware associado é responsável por gerar qualquerinterrupção queoccurs. ocorre. Subsequently, it is possible to have a peripheral thatuses DMA but does not use interrupts. Subsequentemente, é possível terum periférico que utiliza DMA, mas não utiliza as interrupções.It is important to understand that although the CPU always releases thebus to the DMA when the DMA makes the É importante compreender que,embora a CPU sempre libera o autocarro para o DMA quando o DMA torna orequest, this action is invisible to both applications and the operatingsystems, except for slight changes in the pedido, esta ação é invisívelpara os aplicativos e sistemas operacionais, com exceção de pequenasmudanças naamount of time the processor takes to execute instructions when the DMAis active. quantidade de tempo que o processador leva para executar asinstruções quando o DMA está ativo. Subsequently, the processorSubsequentemente, o processadormust poll the peripheral, poll the registers in the DMA chip, or receivean interrupt from the peripheral to know for tem de consultar operiférico, votação dos registros no chip DMA, ou receber umainterrupção do periférico para saber comcertain when a DMA transfer has completed. certo quando umatransferência DMA foi concluída.

Page 78: 139920579 Versao Traduzida de Book

*10.1.2.* *10.1.2.* *DMA Page Registers and 16Meg address spacelimitations* *Da página de DMA Registos e 16meg limitações de espaço deendereço*You may have noticed earlier that instead of the DMA setting the addresslines to 0x00123456 as we said earlier, the Você deve ter percebido maiscedo que em vez da configuração DMA linhas o endereço 0x00123456 Comodissemos anteriormente, oDMA only set 0x3456. DMA apenas definir 0x3456. The reason for thistakes a bit of explaining. A razão para isto leva um pouco de explicação.When the original IBM PC was designed, IBM elected to use both DMA andinterrupt controller chips that were Quando o IBM PC original foiprojetado, a IBM optou por usar tanto DMA e chips controladores deinterrupção que foramdesigned for use with the 8085, an 8-bit processor with an address spaceof 16 bits (64K). concebidos para utilização com o 8085, um processadorde 8 bits, com um espaço de endereço de 16 bits (64 K). Since the IBM PCDesde que o PC IBMsupported more than 64K of memory, something had to be done to allow theDMA to read or write memory locations apoiou mais de 64 K de memória,algo tinha que ser feito para que o DMA para ler ou escrever posições dememóriaabove the 64K mark. acima da marca de 64K. What IBM did to solve thisproblem was to add an external data latch for each DMA channel O que aIBM fez para resolver este problema foi adicionar uma trava de dadosexterna para cada canal de DMAthat holds the upper bits of the address to be read to or written from.que contém os bits superiores do endereço a ser lido ou escrito da.Whenever a DMA channel is active, the contents Sempre que um canal deDMA está ativo, o conteúdoof that latch are written to the address bus and kept there until theDMA operation for the channel ends. de que trava são gravados nobarramento de endereços e mantidos lá até que a operação DMA para ocanal termina. IBM called IBM chamadothese latches “Page Registers”. essas travas "Page Registros".So for our example above, the DMA would put the 0x3456 part of theaddress on the bus, and the Page Register for Assim, para o nossoexemplo acima, o DMA colocaria o 0x3456 parte do endereço no ônibus, eapágina Registre-seDMA channel 2 would put 0x0012xxxx on the bus. DMA canal 2 colocaria0x0012xxxx no ônibus. Together, these two values form the completeaddress in memory Juntos, estes dois valores formam o endereço completona memóriathat is to be accessed. que é para ser acedida.Because the Page Register latch is independent of the DMA chip, the areaof memory to be read or written must not Porque o Register travar apágina é independente do chip de DMA, a área de memória a ser lido ouescrito não devespan a 64K physical boundary. abrangem uma fronteira física 64K. Forexample, if the DMA accesses memory location 0xffff, after that transferthe Por exemplo, se a memória DMA acessa 0xfff localização, após o que atransferênciaDMA will then increment the address register and the DMA will access thenext byte at location 0x0000, not DMA então irá incrementar o registo deendereços eo DMA vai acessar o próximo byte na posição 0x0000, não0x10000. 0x10000. The results of letting this happen are probably notintended. Os resultados de deixar isto acontecer, provavelmente, não sedestinam./57/ /57/------------------------------------------------------------------------*Page 66* *Página 66*

Page 79: 139920579 Versao Traduzida de Book

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/*Note:* “Physical” 64K boundaries should not be confused with 8086-mode64K “Segments”, which are created by *Nota:* "físico" limites de 64K nãodeve ser confundido com 8086 de modo 64K "Segmentos", que são criados pormathematically adding a segment register with an offset register.matematicamente adicionando um registrador de segmento com um registo dedeslocamento. Page Registers have no address overlap and Registros dapágina não têm sobreposição de endereços eare mathematically OR-ed together. são matematicamente OR-ed juntos.To further complicate matters, the external DMA address latches on thePC/AT hold only eight bits, so that gives us Para complicar ainda mais,o endereço DMA externo travas na PC / AT conter apenas oito bits, demodo que nos dá8+16=24 bits, which means that the DMA can only point at memorylocations between 0 and 16Meg. 8 +16 = 24 bits, o que significa que oDMA só pode apontar para posições de memória entre 0 e 16meg. For newerPara mais recentecomputers that allow more than 16Meg of memory, the standardPC-compatible DMA cannot access memory computadores que permitem mais de16meg de memória, o padrão DMA compatível com PC não consegue acessar amemórialocations above 16Meg. locais acima 16meg.To get around this restriction, operating systems will reserve a RAMbuffer in an area below 16Meg that also does Para contornar estalimitação, sistemas operacionais vai reservar um buffer de memória RAMem uma área abaixo 16meg que também faznot span a physical 64K boundary. não abrangem um limite de 64K física.Then the DMA will be programmed to transfer data from the peripheral andinto Em seguida, o DMA será programado para transferir dados de e para operiféricothat buffer. que o tampão. Once the DMA has moved the data into thisbuffer, the operating system will then copy the data from the Uma vezque o DMA transferiu os dados para este tampão, o sistema operativoentão copiar os dados dobuffer to the address where the data is really supposed to be stored.buffer com o endereço onde os dados são realmente deveria ser armazenado.When writing data from an address above 16Meg to a DMA-based peripheral,the data must be first copied from Ao gravar dados a partir de umendereço acima 16meg para um periférico baseado em DMA, os dados devemser copiados do primeirowhere it resides into a buffer located below 16Meg, and then the DMA cancopy the data from the buffer to the onde reside num tampão localizadoabaixo 16meg, e, em seguida, o DMA pode copiar os dados do buffer para ohardware. hardware. In FreeBSD, these reserved buffers are called“Bounce Buffers”. No FreeBSD, estes buffers reservados são chamados de"Buffers Bounce". In the MS-DOS world, they are No mundo do MS-DOS, elessãosometimes called “Smart Buffers”. às vezes chamado de "buffersinteligentes".*Note:* A new implementation of the 8237, called the 82374, allows 16bits of page register to be specified, allows *Nota:* A novaimplementação do 8237, chamado de 82374, permite 16 bits de registro dapágina a ser especificado, permiteaccess to the entire 32 bit address space, without the use of bouncebuffers. acesso a todo o espaço de endereço de 32 bits, sem a utilizaçãode tampões de rejeição.*10.1.3.* *10.1.3.* *DMA Operational Modes and Settings* *Modosoperacionais DMA e Configurações*The 8237 DMA can be operated in several modes. O DMA 8237 pode ser

Page 80: 139920579 Versao Traduzida de Book

operado em vários modos. The main ones are: Os principais são:Single ÚnicoA single byte (or word) is transferred. Um único byte (ou palavra) étransferida. The DMA must release and re-acquire the bus for eachadditional byte. O DMA deve liberar e voltar a adquirir o ônibus paracada byte adicional.This is commonly-used by devices that cannot transfer the entire blockof data immediately. Isto é vulgarmente utilizado por dispositivos quenão pode transferir todo o bloco de dados imediatamente. The peripheralwill O periférico serárequest the DMA each time it is ready for another transfer. solicitar oDMA de cada vez que é preparado para uma outra transferência.The standard PC-compatible floppy disk controller (NEC 765) only has aone-byte buffer, so it uses this mode. O controlador de disquete PCcompatível com a norma NEC (765) só tem um buffer de um byte, por issoele usa este modo.Block/Demand Bloco / DemandaOnce the DMA acquires the system bus, an entire block of data istransferred, up to a maximum of 64K. Uma vez que o DMA adquire o bus desistema, um bloco inteiro de dados são transferidos, até um máximo de 64k. If the Se operipheral needs additional time, it can assert the READY signal tosuspend the transfer briefly. periférica precisa de tempo adicional,pode-se afirmar o sinal READY de suspender a transferência por algunsinstantes. READY should READY deve/58/ /58/------------------------------------------------------------------------*Page 67* *Página 67*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/not be used excessively, and for slow peripheral transfers, the SingleTransfer Mode should be used instead. não pode ser usado em excesso, epara transferências de periféricos lentos, o Transfer Mode único deveser utilizado.The difference between Block and Demand is that once a Block transfer isstarted, it runs until the transfer A diferença entre o bloco ea demandaé que uma vez que a transferência do bloco é iniciado, ele vai até atransferênciacount reaches zero. contagem chega a zero. DRQ only needs to be asserteduntil -DACK is asserted. DRQ só precisa ser afirmado até-DACK éafirmado. Demand Mode will transfer one Modo de demanda irá transferir umamore bytes until DRQ is de-asserted, at which point the DMA suspends thetransfer and releases the bus back to mais bytes até DRQ é de-afirmado,altura em que o DMA suspende a transferência e libera o ônibus de voltaparathe CPU. a CPU. When DRQ is asserted later, the transfer resumes whereit was suspended. Quando DRQ é afirmado mais tarde, a transferênciacontinua de onde foi suspenso.Older hard disk controllers used Demand Mode until CPU speeds increasedto the point that it was more Controladores de disco rígido mais antigosutilizados Modo demanda até velocidades de CPU aumentou a tal ponto queera maisefficient to transfer the data using the CPU, particularly if the memorylocations used in the transfer were above eficaz para transferir osdados utilizando o processador, especialmente se as localizações dememória utilizados na transferência foram acimathe 16Meg mark. a marca 16meg.Cascade CascataThis mechanism allows a DMA channel to request the bus, but then theattached peripheral device is responsible Este mecanismo permite que um

Page 81: 139920579 Versao Traduzida de Book

canal DMA para solicitar o bus, mas, em seguida, o dispositivoperiférico anexado é responsávelfor placing the addressing information on the bus instead of the DMA.para colocar a informação de endereçamento no barramento em vez do DMA.This is also used to implement a Isto também é utilizado paraimplementar umatechnique known as “Bus Mastering”. técnica conhecida como "Bus Mastering".When a DMA channel in Cascade Mode receives control of the bus, the DMAdoes not place addresses and I/O Quando um canal DMA no modo Cascatarecebe o controle do ônibus, o DMA não colocar endereços e I / Ocontrol signals on the bus like the DMA normally does when it is active.sinais de controle no ônibus como o DMA normalmente faz quando estáativo. Instead, the DMA only asserts the Em vez disso, o DMA afirmaapenas o-DACK signal for the active DMA channel. -DACK sinal para o canal DMAativo.At this point it is up to the peripheral connected to that DMA channelto provide address and bus control Neste ponto, cabe ao periféricoconectado a esse canal de DMA para fornecer o endereço e controle de ônibussignals. sinais. The peripheral has complete control over the systembus, and can do reads and/or writes to any address O periférico temcompleto controle sobre o barramento do sistema, e pode fazê-lê e / ouescreve para qualquer endereçobelow 16Meg. abaixo 16meg. When the peripheral is finished with the bus,it de-asserts the DRQ line, and the DMA controller Quando o periférico éterminado com o ônibus, que de-ativa a linha de DRQ, eo controlador de DMAcan then return control to the CPU or to some other DMA channel. pode,então, retornar o controle para a CPU ou para algum outro canal de DMA.Cascade Mode can be used to chain multiple DMA controllers together, andthis is exactly what DMA Channel Modo cascata pode ser usado para cadeiavários controladores de DMA juntos, e isso é exatamente o DMA Canal4 is used for in the PC architecture. 4 é usado para a arquitetura PC.When a peripheral requests the bus on DMA channels 0, 1, 2 or 3, theslave Quando um pedido periféricas do autocarro em DMA canais 0, 1, 2 ou3, o escravoDMA controller asserts HLDREQ, but this wire is actually connected toDRQ4 on the primary DMA controller Controlador de DMA afirma HLDREQ, maseste fio é efectivamente ligado a DRQ4 no primário controlador DMAinstead of to the CPU. em vez de para a CPU. The primary DMA controller,thinking it has work to do on Channel 4, requests the bus O controladorde DMA principal, pensando que tem trabalho a fazer no Channel 4, ospedidos de ônibusfrom the CPU using HLDREQ signal. do processador de sinal usando HLDREQ.Once the CPU grants the bus to the primary DMA controller, -DACK4 is Umavez que a CPU concede o ônibus para o principal controlador de DMA, é-DACK4asserted, and that wire is actually connected to the HLDA signal on theslave DMA controller. afirmado, e esse fio é, na verdade, ligada aosinal HLDA sobre o controlador de DMA escravo. The slave DMA O escravo DMAcontroller then transfers data for the DMA channel that requested it (0,1, 2 or 3), or the slave DMA may grant controlador, em seguida,transfere os dados para o canal de DMA que o solicitou (0, 1, 2 ou 3),ou o escravo DMA pode concederthe bus to a peripheral that wants to perform its own bus-mastering,such as a SCSI controller. o ônibus para um periférico que quer executaro seu próprio ônibus-masterização, como um controlador SCSI.Because of this wiring arrangement, only DMA channels 0, 1, 2, 3, 5, 6and 7 are usable with peripherals on Devido a esta disposição de fiação,apenas canais de DMA 0, 1, 2, 3, 5, 6 e 7 são utilizáveis ��comperiféricos emPC/AT systems. PC / AT sistemas.

Page 82: 139920579 Versao Traduzida de Book

*Note:* DMA channel 0 was reserved for refresh operations in early IBMPC computers, but is generally *Nota:* DMA channel 0 foi reservado paraoperações de atualização em primeiros computadores IBM PC, mas geralmente éavailable for use by peripherals in modern systems. disponível para usopelos periféricos em sistemas modernos./59/ /59/------------------------------------------------------------------------*Page 68* *Página 68*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/When a peripheral is performing Bus Mastering, it is important that theperipheral transmit data to or from Quando um dispositivo periféricoestá realizando Barramento Mestre, é importante que os dados detransmissão para ou a partir periféricasmemory constantly while it holds the system bus. memória constantementeenquanto se mantiver o barramento do sistema. If the peripheral cannotdo this, it must release the bus Se o periférico não pode fazer isso,ele deve liberar o ônibusfrequently so that the system can perform refresh operations on mainmemory. com freqüência para que o sistema possa realizar operações deatualização em memória principal.The Dynamic RAM used in all PCs for main memory must be accessedfrequently to keep the bits stored in the A RAM dinâmica utilizada emtodos os PCs para a memória principal deve ser acessado com freqüênciapara manter os bits armazenados nocomponents “charged”. componentes "carregada". Dynamic RAM essentiallyconsists of millions of capacitors with each one holding one RAMdinâmica consiste essencialmente de milhões de capacitores com cada umsegurando umbit of data. bits de dados. These capacitors are charged with power torepresent a Estes capacitores são carregados com poderes para representar a1 1or drained to represent a ou drenado para representar um0 0. . Because all Porque todoscapacitors leak, power must be added at regular intervals to keep thecondensadores de vazamento, a energia deve ser adicionado em intervalosregulares para manter a1 1values intact. valores intactos. The RAM chips actually Os chips dememória RAM, na verdade,handle the task of pumping power back into all of the appropriatelocations in RAM, but they must be told when lidar com a tarefa debombear o poder de volta em todos os locais apropriados na RAM, mas elesdevem ser informados quandoto do it by the rest of the computer so that the refresh activity won'tinterfere with the computer wanting to ao fazê-lo, o resto docomputador, de modo que a actividade de actualização não irá interferircom o computador que desejamaccess RAM normally. acessar RAM normalmente. If the computer is unableto refresh memory, the contents of memory will become Se o computador écapaz de actualizar a memória, o conteúdo da memória serácorrupted in just a few milliseconds. corrompido em apenas algunsmilissegundos.Since memory read and write cycles “count” as refresh cycles (a dynamicRAM refresh cycle is actually an Como a memória de leitura e escritaciclos de "contar" como ciclos de refresh (um ciclo dinâmico RAMatualização é na verdade umincomplete memory read cycle), as long as the peripheral controllercontinues reading or writing data to ciclo de leitura da memória

Page 83: 139920579 Versao Traduzida de Book

incompleto), enquanto o controlador de periféricos continua a ler ougravar dadossequential memory locations, that action will refresh all of memory.posições de memória seqüenciais, essa ação irá atualizar toda a memória.Bus-mastering is found in some SCSI host interfaces and otherhigh-performance peripheral controllers. De barramento é encontrado emalgumas interfaces SCSI e outros controladores de periféricos de altodesempenho.Autoinitialize AutoinitializeThis mode causes the DMA to perform Byte, Block or Demand transfers, butwhen the DMA transfer counter Este modo faz com que o DMA para realizarByte, bloco ou Demanda transferências, mas quando o DMA transferência debalcãoreaches zero, the counter and address are set back to where they werewhen the DMA channel was originally chega a zero, o contador e endereçosão definidos de volta para onde eles estavam quando o canal de DMA foioriginalmenteprogrammed. programado. This means that as long as the peripheralrequests transfers, they will be granted. Isto significa que, enquantoas transferências dos pedidos periféricos, eles irão ser concedida. Itis up to the Cabe aoCPU to move new data into the fixed buffer ahead of where the DMA isabout to transfer it when doing output CPU para mover os novos dadospara a memória intermédia fixo à frente do que o DMA é de cerca detransferi-la quando se faz a produçãooperations, and read new data out of the buffer behind where the DMA iswriting when doing input operations. operações e os novos dados parafora do buffer de trás, onde o DMA está escrevendo ao fazer operações deentrada.This technique is frequently used on audio devices that have small or nohardware “sample” buffers. Esta técnica é freqüentemente usada emdispositivos de áudio que têm pouco ou nenhum hardware buffers"amostra". There is Temadditional CPU overhead to manage this “circular” buffer, but in somecases this may be the only way to sobrecarga adicional CPU paragerenciar este buffer "circular", mas em alguns casos isso pode ser aúnica maneira deeliminate the latency that occurs when the DMA counter reaches zero andthe DMA stops transfers until it is elimina a latência que ocorre quandoo contador chega a zero e DMA no DMA pára até que seja transferênciasreprogrammed. reprogramado.*10.1.4.* *10.1.4.* *Programming the DMA* *Programação do DMA*The DMA channel that is to be programmed should always be “masked”before loading any settings. O canal de DMA que está a ser programadodeve sempre ser "mascarada" antes de carregar as configurações. This isbecause Isto é porquethe hardware might unexpectedly assert the DRQ for that channel, and theDMA might respond, even though not all o hardware pode inesperadamenteafirmar a DRQ para esse canal, eo DMA pode responder, embora nem todosof the parameters have been loaded or updated. os parâmetros foramcarregados ou actualizado.Once masked, the host must specify the direction of the transfer(memory-to-I/O or I/O-to-memory), what mode of Uma vez mascarado, oanfitrião deve especificar a direção da transferência (memória para I /O ou para memória O I /), o modo deDMA operation is to be used for the transfer (Single, Block, Demand,Cascade, etc), and finally the address and Operação de DMA é para serusado para a transferência (standard, bloco, Demanda Cascade, etc), e,finalmente, o endereço elength of the transfer are loaded. comprimento da transferência são

Page 84: 139920579 Versao Traduzida de Book

carregados. The length that is loaded is one less than the amount youexpect the DMA to O comprimento que é carregado é um a menos do que aquantidade que você espera que o DMA para/60/ /60/------------------------------------------------------------------------*Page 69* *Page 69*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/transfer. transferir. The LSB and MSB of the address and length arewritten to the same 8-bit I/O port, so another port must be A LSB e MSBdo endereço eo comprimento são gravadas no mesmo 8-bit da porta I / O,para que outra porta deve serwritten to first to guarantee that the DMA accepts the first byte as theLSB and the second byte as the MSB of the escrita para a primeira agarantia de que o DMA aceita o primeiro byte como o LSB e o segundo bytecomo o MSB dolength and address. comprimento e endereço.Then, be sure to update the Page Register, which is external to the DMAand is accessed through a different set of Então, não se esqueça deatualizar a página de cadastro, o que é externo ao DMA e é acessadoatravés de um conjunto diferente deI/O ports. Portas I / O.Once all the settings are ready, the DMA channel can be un-masked. Umavez que todas as configurações estão prontas, o canal DMA pode serun-mascarado. That DMA channel is now considered to be Esse canal de DMAé agora considerado“armed”, and will respond when the DRQ line for that channel isasserted. "Armada", e irá responder quando a linha DRQ para esse canal éafirmado.Refer to a hardware data book for precise programming details for the8237. Consulte um livro de dados de hardware para obter mais detalhes deprogramação específicas para o 8237. You will also need to refer to theI/O Você também vai precisar para se referir ao I / Oport map for the PC system, which describes where the DMA and PageRegister ports are located. mapa da porta para o sistema PC, quedescreve onde as portas de Registro de DMA ea página estão localizados.A complete port Uma porta completamap table is located below. tabela mapa está localizado abaixo.*10.1.5.* *10.1.5.* *DMA Port Map* *DMA Porto Mapa*All systems based on the IBM-PC and PC/AT have the DMA hardware locatedat the same I/O ports. Todos os sistemas baseados no IBM-PC e PC / ATtêm o hardware DMA localizados nas mesmas portas de E / S. The completeO completolist is provided below. lista é fornecida abaixo. Ports assigned to DMAController #2 are undefined on non-AT designs. Portas atribuídas a DMAcontrolador � 2 são indefinidos sobre a não-AT projetos.*10.1.5.1.* *10.1.5.1.* *0x00–0x1f DMA Controller #1 (Channels 0, 1, 2and 3)* *0x00-0x1F controlador DMA # 1 (Canais 0, 1, 2 e 3)*DMA Address and Count Registers DMA Endereço de e Registradores Conde0x00 0x00write escreverChannel 0 starting address O canal 0 endereço de partida0x00 0x00read lerChannel 0 current address O canal 0 endereço atual0x01 0x01write escreverChannel 0 starting word count O canal 0 começando contagem de palavras0x01 0x01read ler

Page 85: 139920579 Versao Traduzida de Book

Channel 0 remaining word count O canal 0 contagem de palavras restantes0x02 0x02write escreverChannel 1 starting address Canal 1 endereço inicial0x02 0x02read lerChannel 1 current address Canal 1 endereço atual0x03 0x03write escreverChannel 1 starting word count Canal 1 partida de contagem de palavras0x03 0x03read lerChannel 1 remaining word count Canal 1 contagem de palavras restantes0x04 0x04write escreverChannel 2 starting address Canal 2 endereço inicial0x04 0x04read lerChannel 2 current address Canal 2 endereço atual0x05 0x05write escreverChannel 2 starting word count Canal 2 de iniciar contagem de palavras0x05 0x05read lerChannel 2 remaining word count Canal 2 contagem de palavras restantes0x06 0x06write escreverChannel 3 starting address Canal 3 endereço inicial0x06 0x06read lerChannel 3 current address Canal 3 endereço atual0x07 0x07write escreverChannel 3 starting word count Canal 3, a partir de contagem de palavras0x07 0x07read lerChannel 3 remaining word count Canal 3 contagem de palavras restantes/61/ /61/------------------------------------------------------------------------*Page 70* *Página 70*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/DMA Command Registers DMA comando registra0x08 0x08write escreverCommand Register Comando Register0x08 0x08read lerStatus Register Estado Register0x09 0x09write escreverRequest Register Pedir Registrar0x09 0x09read ler- -0x0a 0x0Awrite escreverSingle Mask Register Bit Única máscara Register Bit0x0a 0x0Aread ler

Page 86: 139920579 Versao Traduzida de Book

- -0x0b 0x0Bwrite escreverMode Register Modo de Registo0x0b 0x0Bread ler- -0x0c 0x0cwrite escreverClear LSB/MSB Flip-Flop Limpar LSB / MSB Flip-Flop0x0c 0x0cread ler- -0x0d 0x0dwrite escreverMaster Clear/Reset Master Clear / Reset0x0d 0x0dread lerTemporary Register (not available on Registro temporário (não disponível emnewer versions) versões mais recentes)0x0e 0x0ewrite escreverClear Mask Register Limpar registo de máscara0x0e 0x0eread ler- -0x0f 0x0Fwrite escreverWrite All Mask Register Bits Escrever todos os bits do registador demáscara0x0f 0x0Fread lerRead All Mask Register Bits (only in Leia todos os bits do registador demáscara (apenas emIntel 82374) Intel 82374)*10.1.5.2.* *10.1.5.2.* *0xc0–0xdf DMA Controller #2 (Channels 4, 5, 6and 7)* *0xc0-0xDF controlador DMA # 2 (canais 4, 5, 6 e 7)*DMA Address and Count Registers DMA Endereço de e Registradores Conde0xc0 0xc0write escreverChannel 4 starting address Channel 4 endereço inicial0xc0 0xc0read lerChannel 4 current address Channel 4 endereço atual0xc2 0xC2write escreverChannel 4 starting word count Channel 4 a partir de contagem de palavras0xc2 0xC2read lerChannel 4 remaining word count Channel 4 contagem de palavras restantes0xc4 0xC4write escreverChannel 5 starting address Canal 5 endereço inicial0xc4 0xC4read lerChannel 5 current address Canal 5 endereço atual0xc6 0xc6write escreverChannel 5 starting word count Canal 5 de iniciar contagem de palavras0xc6 0xc6

Page 87: 139920579 Versao Traduzida de Book

read lerChannel 5 remaining word count Canal 5 contagem de palavras restantes0xc8 0xC8write escreverChannel 6 starting address Canal 6 endereço inicial0xc8 0xC8read lerChannel 6 current address Canal 6 atual endereço/62/ /62/------------------------------------------------------------------------*Page 71* *Página 71*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/0xca 0xcawrite escreverChannel 6 starting word count Canal 6 partida contagem de palavras0xca 0xcaread lerChannel 6 remaining word count Canal 6 contagem de palavras restantes0xcc 0xCCwrite escreverChannel 7 starting address Canal 7 endereço inicial0xcc 0xCCread lerChannel 7 current address Canal 7 endereço atual0xce 0xCEwrite escreverChannel 7 starting word count Canal 7 iniciar contagem de palavras0xce 0xCEread lerChannel 7 remaining word count Canal 7 contagem de palavras restantesDMA Command Registers DMA comando registra0xd0 0xd0write escreverCommand Register Comando Register0xd0 0xd0read lerStatus Register Estado Register0xd2 0xD2write escreverRequest Register Pedir Registrar0xd2 0xD2read ler- -0xd4 0xd4write escreverSingle Mask Register Bit Única máscara Register Bit0xd4 0xd4read ler- -0xd6 0xD6write escreverMode Register Modo de Registo0xd6 0xD6read ler- -0xd8 0xd8write escreverClear LSB/MSB Flip-Flop Limpar LSB / MSB Flip-Flop0xd8 0xd8

Page 88: 139920579 Versao Traduzida de Book

read ler- -0xda 0xdawrite escreverMaster Clear/Reset Master Clear / Reset0xda 0xdaread lerTemporary Register (not present in Registro temporário (não presente emIntel 82374) Intel 82374)0xdc 0xdcwrite escreverClear Mask Register Limpar registo de máscara0xdc 0xdcread ler- -0xde 0xDEwrite escreverWrite All Mask Register Bits Escrever todos os bits do registador demáscara0xdf 0xDFread lerRead All Mask Register Bits (only in Leia todos os bits do registador demáscara (apenas emIntel 82374) Intel 82374)*10.1.5.3.* *10.1.5.3.* *0x80–0x9f DMA Page Registers* *0x80-0x9F DMAPágina Registra*0x87 0x87r/w r / wChannel 0 Low byte (23-16) page Canal 0 Low byte (23-16) páginaRegister Registrar0x83 0x83r/w r / wChannel 1 Low byte (23-16) page Canal 1 Low byte (23-16) páginaRegister Registrar/63/ /63/------------------------------------------------------------------------*Page 72* *Página 72*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/0x81 0x81r/w r / wChannel 2 Low byte (23-16) page Canal 2 Low byte (23-16) páginaRegister Registrar0x82 0x82r/w r / wChannel 3 Low byte (23-16) page Canal 3 Low byte (23-16) páginaRegister Registrar0x8b 0x8br/w r / wChannel 5 Low byte (23-16) page Canal 5 Low byte (23-16) páginaRegister Registrar0x89 0x89r/w r / wChannel 6 Low byte (23-16) page Canal 6 Low byte (23-16) páginaRegister Registrar0x8a 0x8ar/w r / wChannel 7 Low byte (23-16) page Canal 7 Low byte (23-16) páginaRegister Registrar0x8f 0x8F

Page 89: 139920579 Versao Traduzida de Book

r/w r / wLow byte page Refresh Low byte página de atualização*10.1.5.4.* *10.1.5.4.* *0x400–0x4ff 82374 Enhanced DMA Registers**0x400-0x4ff 82.374 aprimorada DMA Registra*The Intel 82374 EISA System Component (ESC) was introduced in early 1996and includes a DMA controller that O Intel 82374 EISA Componentes doSistema (ESC) foi introduzido no início de 1996 e inclui um controladorde DMA queprovides a superset of 8237 functionality as well as other PC-compatiblecore peripheral components in a single fornece um subconjunto de 8237 afuncionalidade, assim como outros componentes periféricos do núcleo dePC-compatíveis num únicopackage. pacote. This chip is targeted at both EISA and PCI platforms,and provides modern DMA features like Este chip é dirigido a ambos EISAe plataformas PCI, e fornece recursos modernos como DMAscatter-gather, ring buffers as well as direct access by the system DMAto all 32 bits of address space. scatter-gather, buffers de anel, bemcomo acesso direto pelo sistema DMA para todos os 32 bits de espaço deendereço.If these features are used, code should also be included to providesimilar functionality in the previous 16 years Se esses recursos sãoutilizados, o código também deve ser incluído para fornecerfuncionalidade semelhante nos 16 anos anterioresworth of PC-compatible computers. pena de computadores PC-compatíveis.For compatibility reasons, some of the 82374 registers must beprogrammed Por motivos de compatibilidade, alguns dos 82.374 registosdeve ser programado/after/ programming the traditional 8237 registers for each transfer./Depois de/ programar o tradicional 8.237 registros para cadatransferência. Writing to a traditional 8237 register forces theEscrevendo para um registo tradicional 8237 obriga ocontents of some of the 82374 enhanced registers to zero to providebackward software compatibility. conteúdo de alguns dos registrosaprimorados 82.374 para zero para fornecer compatibilidade de softwarepara trás.0x401 0x401r/w r / wChannel 0 High byte (bits 23-16) word O canal 0 alta byte (bits 23-16)palavracount contar0x403 0x403r/w r / wChannel 1 High byte (bits 23-16) word Canal 1 High byte (bits 23-16)palavracount contar0x405 0x405r/w r / wChannel 2 High byte (bits 23-16) word Canal 2 High byte (bits 23-16)palavracount contar0x407 0x407 É necessáriar/w r / wChannel 3 High byte (bits 23-16) word Canal 3 High byte (bits 23-16)palavracount contar0x4c6 0x4c6r/w r / wChannel 5 High byte (bits 23-16) word Canal 5 High byte (bits 23-16)palavracount contar

Page 90: 139920579 Versao Traduzida de Book

0x4ca 0x4car/w r / wChannel 6 High byte (bits 23-16) word Canal 6 High byte (bits 23-16)palavracount contar/64/ /64/------------------------------------------------------------------------*Page 73* *Página 73*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/0x4ce 0x4cer/w r / wChannel 7 High byte (bits 23-16) word Canal 7 High byte (bits 23-16)palavracount contar0x487 0x487r/w r / wChannel 0 High byte (bits 31-24) page O canal 0 alta byte (bits 31-24)páginaRegister Registrar0x483 0x483r/w r / wChannel 1 High byte (bits 31-24) page Canal 1 High byte (bits 31-24) páginaRegister Registrar0x481 0x481r/w r / wChannel 2 High byte (bits 31-24) page Canal 2 High byte (bits 31-24) páginaRegister Registrar0x482 0x482 Duasr/w r / wChannel 3 High byte (bits 31-24) page Canal 3 High byte (bits 31-24) páginaRegister Registrar0x48b 0x48br/w r / wChannel 5 High byte (bits 31-24) page Canal 5 High byte (bits 31-24) páginaRegister Registrar0x489 0x489r/w r / wChannel 6 High byte (bits 31-24) page Canal 6 High byte (bits 31-24) páginaRegister Registrar0x48a 0x48ar/w r / wChannel 6 High byte (bits 31-24) page Canal 6 High byte (bits 31-24) páginaRegister Registrar0x48f 0x48fr/w r / wHigh byte page Refresh Alta byte Atualizar página0x4e0 0x4e0r/w r / wChannel 0 Stop Register (bits 7-2) O canal 0 Parar Register (bits 7-2)0x4e1 0x4e1r/w r / wChannel 0 Stop Register (bits 15-8) O canal 0 Parar Register (bits 15-8)0x4e2 0x4e2r/w r / wChannel 0 Stop Register (bits 23-16) O canal 0 Parar Register (bits 23-16)0x4e4 0x4e4r/w r / wChannel 1 Stop Register (bits 7-2) Canal 1 Stop Register (bits 7-2)0x4e5 0x4e5

Page 91: 139920579 Versao Traduzida de Book

r/w r / wChannel 1 Stop Register (bits 15-8) Canal 1 Stop Register (bits 15-8)0x4e6 0x4e6r/w r / wChannel 1 Stop Register (bits 23-16) Canal 1 Stop Register (bits 23-16)0x4e8 0x4e8r/w r / wChannel 2 Stop Register (bits 7-2) Canal 2 Stop Register (bits 7-2)0x4e9 0x4e9r/w r / wChannel 2 Stop Register (bits 15-8) Canal 2 Stop Register (bits 15-8)0x4ea 0x4ear/w r / wChannel 2 Stop Register (bits 23-16) Canal 2 Stop Register (bits 23-16)0x4ec 0x4ecr/w r / wChannel 3 Stop Register (bits 7-2) Canal 3 Stop Register (bits 7-2)0x4ed 0x4edr/w r / wChannel 3 Stop Register (bits 15-8) Canal 3 Stop Register (bits 15-8)0x4ee 0x4eer/w r / wChannel 3 Stop Register (bits 23-16) Canal 3 Stop Register (bits 23-16)0x4f4 0x4f4r/w r / wChannel 5 Stop Register (bits 7-2) Canal 5 Stop Register (bits 7-2)0x4f5 0x4f5r/w r / wChannel 5 Stop Register (bits 15-8) Canal 5 Stop Register (bits 15-8)0x4f6 0x4f6r/w r / wChannel 5 Stop Register (bits 23-16) Canal 5 Stop Register (bits 23-16)0x4f8 0x4f8r/w r / wChannel 6 Stop Register (bits 7-2) Canal 6 Parar Register (bits 7-2)0x4f9 0x4f9r/w r / wChannel 6 Stop Register (bits 15-8) Canal 6 Parar Register (bits 15-8)0x4fa 0x4far/w r / wChannel 6 Stop Register (bits 23-16) Canal 6 Parar Register (bits 23-16)/65/ /65/------------------------------------------------------------------------*Page 74* *Página 74*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/0x4fc 0x4fcr/w r / wChannel 7 Stop Register (bits 7-2) Canal 7 Parar Register (bits 7-2)0x4fd 0x4fdr/w r / wChannel 7 Stop Register (bits 15-8) Canal 7 Parar Register (bits 15-8)0x4fe 0x4fer/w r / wChannel 7 Stop Register (bits 23-16) Canal 7 Parar Register (bits 23-16)0x40a 0x40awrite escreverChannels 0-3 Chaining Mode Register Canais 0-3 encadeamento Modo Registrar0x40a 0x40aread ler

Page 92: 139920579 Versao Traduzida de Book

Channel Interrupt Status Register Canal de interrupção Estado Registrar0x4d4 0x4d4write escreverChannels 4-7 Chaining Mode Register Canais 4-7 encadeamento Modo Registrar0x4d4 0x4d4read lerChaining Mode Status Encadeamento Modo Estado0x40c 0x40cread lerChain Buffer Expiration Control Cadeia de buffer de controle de validadeRegister Registrar0x410 0x410write escreverChannel 0 Scatter-Gather Command O canal 0 Scatter-Gather CommandRegister Registrar0x411 0x411write escreverChannel 1 Scatter-Gather Command Canal 1 Scatter-Gather CommandRegister Registrar0x412 0x412write escreverChannel 2 Scatter-Gather Command Canal 2 Scatter-Gather CommandRegister Registrar0x413 0x413write escreverChannel 3 Scatter-Gather Command Canal 3 Scatter-Gather CommandRegister Registrar0x415 0x415write escreverChannel 5 Scatter-Gather Command Canal 5 Scatter-Gather CommandRegister Registrar0x416 0x416write escreverChannel 6 Scatter-Gather Command Canal 6 Scatter-Gather CommandRegister Registrar0x417 0x417write escreverChannel 7 Scatter-Gather Command Canal 7 Scatter-Gather CommandRegister Registrar0x418 0x418read lerChannel 0 Scatter-Gather Status O canal 0 Scatter-Gather EstadoRegister Registrar0x419 0x419read lerChannel 1 Scatter-Gather Status Canal 1 Scatter-Gather EstadoRegister Registrar0x41a 0x41aread lerChannel 2 Scatter-Gather Status Canal 2 Scatter-Gather EstadoRegister Registrar0x41b 0x41bread lerChannel 3 Scatter-Gather Status Canal 3 Scatter-Gather EstadoRegister Registrar0x41d 0x41dread lerChannel 5 Scatter-Gather Status Canal 5 Scatter-Gather EstadoRegister Registrar0x41e 0x41e

Page 93: 139920579 Versao Traduzida de Book

read lerChannel 5 Scatter-Gather Status Canal 5 Scatter-Gather EstadoRegister Registrar/66/ /66/------------------------------------------------------------------------*Page 75* *Página 75*

/Chapter 10./ /Capítulo 10./ /DMA/ /DMA/0x41f 0x41fread lerChannel 7 Scatter-Gather Status Canal 7 Scatter-Gather EstadoRegister Registrar0x420-0x423 0x420, 0x423r/w r / wChannel 0 Scatter-Gather Descriptor O canal 0 Scatter-Gather DescriptorTable Pointer Register Tabela Pointer Register0x424-0x427 0x424, 0x427r/w r / wChannel 1 Scatter-Gather Descriptor Canal 1 Scatter-Gather DescriptorTable Pointer Register Tabela Pointer Register0x428-0x42b 0x428-0x42br/w r / wChannel 2 Scatter-Gather Descriptor Canal 2 Scatter-Gather DescriptorTable Pointer Register Tabela Pointer Register0x42c-0x42f 0x42c-0x42fr/w r / wChannel 3 Scatter-Gather Descriptor Canal 3 Scatter-Gather DescriptorTable Pointer Register Tabela Pointer Register0x434-0x437 0x434, 0x437r/w r / wChannel 5 Scatter-Gather Descriptor Canal 5 Scatter-Gather DescriptorTable Pointer Register Tabela Pointer Register0x438-0x43b 0x438-0x43br/w r / wChannel 6 Scatter-Gather Descriptor Canal 6 Scatter-Gather DescriptorTable Pointer Register Tabela Pointer Register0x43c-0x43f 0x43c-0x43fr/w r / wChannel 7 Scatter-Gather Descriptor Canal 7 Scatter-Gather DescriptorTable Pointer Register Tabela Pointer Register/67/ /67/------------------------------------------------------------------------*Page 76* *Página 76*

*V. I/O System* *V. Sistema de I / O*------------------------------------------------------------------------*Page 77* *Página 77*

*Chapter 11.* *Capítulo 11.* *UFS* *UFS*UFS, FFS, Ext2FS, JFS, inodes, buffer cache, labeling, locking,metadata, soft-updates, LFS, portalfs, procfs, UFS, FFS, Ext2FS, JFSinodes, buffer cache, rotulagem, fecho, metadados, soft-updates, LFS,portalfs, procfs,vnodes, memory sharing, memory objects, TLBs, caching vnodes,compartilhamento de memória, objetos de memória, TLBs, cache/69/ /69/------------------------------------------------------------------------*Page 78* *Página 78*

*VI.* *VI.* *Interprocess Communication* *Comunicação entre*

Page 94: 139920579 Versao Traduzida de Book

------------------------------------------------------------------------*Page 79* *Página 79*

*Chapter 12.* *Capítulo 12.* *Signals* *Sinais*Signals, pipes, semaphores, message queues, shared memory, ports,sockets, doors Sinais, tubos, semáforos, filas de mensagens, memóriacompartilhada, portas, tomadas, portas/71/ /71/------------------------------------------------------------------------*Page 80* *Página 80*

*VII.* *VII.* *Networking* *Networking*------------------------------------------------------------------------*Page 81* *Página 81*

*Chapter 13.* *Capítulo 13.* *Sockets* *Sockets*Sockets, bpf, IP, TCP, UDP, ICMP, OSI, bridging, firewalling, NAT,switching, etc Sockets, bpf, IP, TCP, UDP, ICMP, OSI, bridging,firewall, NAT, switching, etc/73/ /73/------------------------------------------------------------------------*Page 82* *Página 82*

*Chapter 14.* *Capítulo 14.* *IPv6 Internals* *Internals IPv6**14.1.* *14.1.* *IPv6/IPsec Implementation* *IPv6/IPsec Implementação*/Contributed by Yoshinobu Inoue </ /Contribuição de Yoshinobu Inoue <//[email protected]/ /[email protected]//>, 5 March 2000./ />, 5 de Março de 2000./This section should explain IPv6 and IPsec related implementationinternals. Esta seção deve explicar IPv6 e IPSec internos deimplementação. These functionalities are derived from Estasfuncionalidades são derivadasKAME project (http://www.kame.net) Projeto KAME (http://www.kame.net)*14.1.1.* *14.1.1.* *IPv6* *IPv6**14.1.1.1.* *14.1.1.1.* *Conformance* *Conformidade*The IPv6 related functions conforms, or tries to conform to the latestset of IPv6 specifications. As funções relacionadas com o IPv6 está emconformidade, ou tenta se conformar com o último conjunto deespecificações do IPv6. For future reference Para referência futurawe list some of the relevant documents below ( /NOTE/ : this is not acomplete list - this is too hard to maintain...). listamos alguns dosdocumentos abaixo /(NOTA:/ esta não é uma lista completa - isso é muitodifícil de manter ...).For details please refer to specific chapter in the document, RFCs,manpages, or comments in the source code. Para mais detalhes, consulte ocapítulo específico do documento, RFCs, manpages, ou comentários nocódigo-fonte.Conformance tests have been performed on the KAME STABLE kit at TAHIproject. Testes de conformidade têm sido realizados sobre o kit ESTÁVELKAME no projeto TAHI. Results can be viewed at Os resultados podem servistos emhttp://www.tahi.org/report/KAME/ (http://www.tahi.org/report/KAME/).http://www.tahi.org/report/KAME/ (http://www.tahi.org/report/KAME/). Wealso attended Univ. Também participaram Univ. of New Hampshire of NewHampshireIOL tests (http://www.iol.unh.edu/) in the past, with our pastsnapshots. Testes de LIO (http://www.iol.unh.edu/) no passado, com osnossos snapshots passadas.• •RFC1639: FTP Operation Over Big Address Records (FOOBAR) RFC1639: Mais

Page 95: 139920579 Versao Traduzida de Book

de FTP Operação Big Morada Records (FOOBAR)• •RFC2428 is preferred over RFC1639. RFC2428 é preferível a RFC1639. FTPclients will first try RFC2428, then RFC1639 if failed. Clientes FTPtentará primeiro RFC2428, RFC1639, em seguida, se falhou.• •RFC1886: DNS Extensions to support IPv6 RFC1886: Extensões de DNS parasuportar IPv6• •RFC1933: Transition Mechanisms for IPv6 Hosts and Routers RFC1933:Mecanismos de Transição para IPv6 Hosts e Routers• •IPv4 compatible address is not supported. Endereço IPv4 compatível não ésuportado.• •automatic tunneling (described in 4.3 of this RFC) is not supported.tunelamento automático (descrita no item 4.3 deste RFC) não é suportado.• •gif(4) interface implements IPv[46]-over-IPv[46] tunnel in a genericway, and it covers "configured tunnel" gif (4) interface implementa IPv[46]-over-IPv [46] túnel de uma forma genérica, e que abrange "túnelconfigurado"described in the spec. descrito na especificação. See 23.5.1.5 <#88> inthis document for details. Veja 23.5.1.5 <#88> neste documento paraobter detalhes.• •RFC1981: Path MTU Discovery for IPv6 RFC1981: Path MTU Discovery para IPv6• •RFC2080: RIPng for IPv6 RFC2080: RIPng para IPv6• •usr.sbin/route6d support this. usr.sbin/route6d suportar isto./74/ /74/------------------------------------------------------------------------*Page 83* *Página 83*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/ /Internals IPv6/• •RFC2292: Advanced Sockets API for IPv6 RFC2292: Avançado Sockets APIpara IPv6• •For supported library functions/kernel APIs, see Para as funções debiblioteca suportados / APIs do kernel, vejasys/netinet6/ADVAPI sys/netinet6/ADVAPI. .• •RFC2362: Protocol Independent Multicast-Sparse Mode (PIM-SM) RFC2362:Modo Multicast-Sparse Independent Protocol (PIM-SM)• •RFC2362 defines packet formats for PIM-SM. RFC2362 define formatos depacotes para o PIM-SM.draft-ietf-pim-ipv6-01.txt projecto-IETF-pim-ipv6-01.txtis written based on this. é escrito com base nesta.• •RFC2373: IPv6 Addressing Architecture RFC2373: Arquitetura deendereçamento IPv6• •supports node required addresses, and conforms to the scope requirement.suporta endereços necessários nó, e está em conformidade com a exigênciade escopo.• •

Page 96: 139920579 Versao Traduzida de Book

RFC2374: An IPv6 Aggregatable Global Unicast Address Format RFC2374: Umunicast global Formato de endereço IPv6 Aggregatable• •supports 64-bit length of Interface ID. suporta comprimento de ID deinterface de 64 bits.• •RFC2375: IPv6 Multicast Address Assignments RFC2375: atribuições deendereços Multicast IPv6• •Userland applications use the well-known addresses assigned in the RFC.Aplicações UserLand usar os endereços conhecidos atribuídos no RFC.• •RFC2428: FTP Extensions for IPv6 and NATs RFC2428: FTP Extensões paraIPv6 e NAT• •RFC2428 is preferred over RFC1639. RFC2428 é preferível a RFC1639. FTPclients will first try RFC2428, then RFC1639 if failed. Clientes FTPtentará primeiro RFC2428, RFC1639, em seguida, se falhou.• •RFC2460: IPv6 specification RFC2460: especificação do IPv6• •RFC2461: Neighbor discovery for IPv6 RFC2461: Neighbor Discovery para IPv6• •See 23.5.1.2 <#84> in this document for details. Veja 23.5.1.2 <#84>neste documento para obter detalhes.• •RFC2462: IPv6 Stateless Address Autoconfiguration RFC2462: apátridasendereço autoconfiguração do IPv6• •See 23.5.1.4 <#86> in this document for details. Veja 23.5.1.4 <#86>neste documento para obter detalhes.• •RFC2463: ICMPv6 for IPv6 specification RFC2463: ICMPv6 paraespecificação IPv6• •See 23.5.1.9 <#91> in this document for details. Veja 23.5.1.9 <#91>neste documento para obter detalhes./75/ /75/------------------------------------------------------------------------*Page 84* *Página 84*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/ /Internals IPv6/• •RFC2464: Transmission of IPv6 Packets over Ethernet Networks RFC2464:Transmissão de pacotes IPv6 em redes Ethernet• •RFC2465: MIB for IPv6: Textual Conventions and General Group RFC2465:MIB IPv6: Textual Convenções e grupo geral• •Necessary statistics are gathered by the kernel. Dados estatísticosnecessários são recolhidos pelo kernel. Actual IPv6 MIB support isprovided as a patchkit for ucd-snmp. Actual apoio MIB IPv6 é fornecidocomo um patchkit para UCD-SNMP.• •RFC2466: MIB for IPv6: ICMPv6 group RFC2466: MIB IPv6: ICMPv6 grupo• •Necessary statistics are gathered by the kernel. Dados estatísticosnecessários são recolhidos pelo kernel. Actual IPv6 MIB support isprovided as patchkit for ucd-snmp. Actual apoio MIB IPv6 é fornecidocomo patchkit para UCD-SNMP.

Page 97: 139920579 Versao Traduzida de Book

• •RFC2467: Transmission of IPv6 Packets over FDDI Networks RFC2467:Transmissão de pacotes IPv6 sobre FDDI Networks• •RFC2497: Transmission of IPv6 packet over ARCnet Networks RFC2497:Transmissão de pacotes IPv6 durante redes ARCnet• •RFC2553: Basic Socket Interface Extensions for IPv6 RFC2553: BasicSocket interface extensões para IPv6• •IPv4 mapped address (3.7) and special behavior of IPv6 wildcard bindsocket (3.8) are supported. Endereço IPv4 mapeado (3.7) e umcomportamento especial de tomada ligam curinga IPv6 (3.8) sãosuportados. See 23.5.1.12 <#92> Veja 23.5.1.12 <#92>in this document for details. neste documento para obter detalhes.• •RFC2675: IPv6 Jumbograms RFC2675: Jumbograms IPv6• •See 23.5.1.7 <#89> in this document for details. Veja 23.5.1.7 <#89>neste documento para obter detalhes.• •RFC2710: Multicast Listener Discovery for IPv6 RFC2710: MulticastListener Discovery para IPv6• •RFC2711: IPv6 router alert option RFC2711: opção de alerta de roteador IPv6• •draft-ietf-ipngwg-router-renum-08 projecto-IETF-ipngwg-router-renum-08: Router renumbering for IPv6 : Router renumeração para IPv6• •draft-ietf-ipngwg-icmp-namelookups-02projecto-IETF-ipngwg-icmp-namelookups-02: IPv6 Name Lookups Through ICMP : Pesquisas Nome IPv6 através de ICMP• •draft-ietf-ipngwg-icmp-name-lookups-03projecto-IETF-ipngwg-icmp-nome-pesquisas-03: IPv6 Name Lookups Through ICMP : Pesquisas Nome IPv6 através de ICMP• •draft-ietf-pim-ipv6-01.txt projecto-IETF-pim-ipv6-01.txt: PIM for IPv6 : PIM para IPv6• •pim6dd(8) implements dense mode. pim6dd (8) implementa modo denso.pim6sd(8) implements sparse mode. pim6sd (8) implementa modo esparso.• •draft-itojun-ipv6-tcp-to-anycast-00 projecto-itojun-ipv6-tcp-to-anycast-00: Disconnecting TCP connection toward IPv6 anycast address : Desligarconexão TCP para o endereço IPv6 anycast• •draft-yamamoto-wideipv6-comm-model-00projecto-yamamoto-wideipv6-comm-model-00• •See 23.5.1.6 <#88> in this document for details. Veja 23.5.1.6 <#88>neste documento para obter detalhes.• •draft-ietf-ipngwg-scopedaddr-format-00.txtprojecto-IETF-ipngwg-scopedaddr-format-00.txt: An Extension of Format for IPv6 Scoped Addresses : Uma extensão deFormato para alcance endereços IPv6/76/ /76/------------------------------------------------------------------------*Page 85* *Página 85*

Page 98: 139920579 Versao Traduzida de Book

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/ /Internals IPv6/*14.1.1.2.* *14.1.1.2.* *Neighbor Discovery* *Neighbor Discovery*Neighbor Discovery is fairly stable. Neighbor Discovery é bastanteestável. Currently Address Resolution, Duplicated Address Detection, andNeighbor Atualmente Address Resolution, duplicado Morada Detecção eNeighborUnreachability Detection are supported. Detecção Unreachability sãosuportados. In the near future we will be adding Proxy NeighborAdvertisement support Num futuro próximo, estaremos adicionando suporteNeighbor Advertisement Proxyin the kernel and Unsolicited Neighbor Advertisement transmissioncommand as admin tool. no kernel e comando transmissão NeighborAdvertisement Unsolicited como ferramenta de administração.If DAD fails, the address will be marked "duplicated" and message willbe generated to syslog (and usually to Se o pai não, o endereço serámarcado "duplicado" ea mensagem será gerada para syslog (e, geralmente, aconsole). Console). The "duplicated" mark can be checked withifconfig(8). A marca "duplicado" pode ser verificado com o ifconfig (8).It is administrators' responsibility to check for and É deresponsabilidade dos administradores para verificar erecover from DAD failures. recuperação de falhas pai. The behaviorshould be improved in the near future. O comportamento deve sermelhorado no futuro próximo.Some of the network driver loops multicast packets back to itself, evenif instructed not to do so (especially in Alguns dos driver de redelaços pacotes multicast de volta para si mesma, mesmo instruídos a nãofazê-lo (especialmente empromiscuous mode). modo promíscuo). In such cases DAD may fail, becauseDAD engine sees inbound NS packet (actually from the Nesse DAD casospode falhar, porque o motor de DAD vê a entrada de pacotes NS (naverdade, a partir donode itself) and considers it as a sign of duplicate. nó em si) econsidera isso como um sinal de duplicata. You may want to look at #ifcondition marked "heuristics" in Você pode querer olhar para # ifcondição marcada "heurística" emsys/netinet6/nd6_nbr.c:nd6_dad_timer() as workaround (note that the codefragment in "heuristics" section is not sys/netinet6/nd6_nbr.c:nd6_dad_timer () como solução (note que o fragmento de código seção"heurística" in não éspec conformant). especificação conformant).Neighbor Discovery specification (RFC2461) does not talk about neighborcache handling in the following cases: Neighbor Discovery especificação(RFC2461) não fala sobre a manipulação de cache vizinho nos seguintescasos:1. 1. when there was no neighbor cache entry, node received unsolicitedRS/NS/NA/redirect packet without link-layer quando não havia nenhumaentrada de cache vizinho, o nó não solicitadas recebidas RS / NS / NA /redirecionamento de pacotes, sem camada de enlaceaddress endereço2. 2. neighbor cache handling on medium without link-layer address (weneed a neighbor cache entry for IsRouter bit) cache vizinha manipulaçãoem meio sem endereço da camada de enlace (precisamos de uma entrada decache vizinho para bit IsRouter)For first case, we implemented workaround based on discussions on IETFipngwg mailing list. Para o primeiro caso, foi implementado solução combase em discussões sobre IETF ipngwg mailing list. For more details, seePara mais detalhes, consultethe comments in the source code and email thread started from (IPng7155), dated Feb 6 1999. os comentários no código-fonte e fio de e-mail

Page 99: 139920579 Versao Traduzida de Book

começou a partir de (IPng 7155), datado de 6 de fevereiro de 1999.IPv6 on-link determination rule (RFC2461) is quite different fromassumptions in BSD network code. IPv6 sobre-link regra de determinação(RFC2461) é bem diferente de pressupostos código de rede BSD. At this Nestemoment, no on-link determination rule is supported where default routerlist is empty (RFC2461, section 5.2, last momento, nenhuma regradeterminação em-link é suportado em lista roteador padrão está vazia(RFC2461, seção 5.2, últimasentence in 2nd paragraph - note that the spec misuse the word "host"and "node" in several places in the section). sentença no parágrafo 2 �- note que a especificação mau uso da palavra "host" e "nó" em várioslugares na seção).To avoid possible DoS attacks and infinite loops, only 10 options on NDpacket is accepted now. Para evitar possíveis ataques de negação deserviço e loops infinitos, apenas 10 opções de pacotes ND é aceitoagora. Therefore, if you Portanto, se vocêhave 20 prefix options attached to RA, only the first 10 prefixes willbe recognized. ter 20 opções de prefixo anexado ao RA, apenas osprimeiros 10 prefixos será reconhecido. If this troubles you, please askit Se isso o incomoda, por favor, pergunte-loon FREEBSD-CURRENT mailing list and/or modify nd6_maxndopt in NoFreeBSD-CURRENT lista de discussão e / ou modificar nd6_maxndopt emsys/netinet6/nd6.c sys/netinet6/nd6.c. . If there are high Se houver altademands we may provide sysctl knob for the variable. exige podemosfornecer botão sysctl para a variável.*14.1.1.3.* *14.1.1.3.* *Scope Index* *Índice Scope*IPv6 uses scoped addresses. IPv6 utiliza endereços de escopo. Therefore,it is very important to specify scope index (interface index forlink-local Portanto, é muito importante especificar índice alcance(índice de interface para ligação localaddress, or site index for site-local address) with an IPv6 address.endereço ou local de índice para endereço do site local) com um endereçoIPv6. Without scope index, scoped IPv6 address is Sem índice alcance,endereço IPv6 escopo éambiguous to the kernel, and kernel will not be able to determine theoutbound interface for a packet. ambíguo para o núcleo, e do grão nãoserá capaz de determinar a interface de saída para um pacote.Ordinary userland applications should use advanced API (RFC2292) tospecify scope index, or interface index. Aplicações userlândia comunsdevem usar avançado API (RFC2292) para especificar índice escopo, ouíndice de interface. For Parasimilar purpose, sin6_scope_id member in sockaddr_in6 structure isdefined in RFC2553. finalidade semelhante, um membro em sin6_scope_idsockaddr_in6 estrutura é definida em RFC2553. However, the semantics Noentanto, a semânticafor sin6_scope_id is rather vague. para sin6_scope_id é bastante vago.If you care about portability of your application, we suggest you to useadvanced Se você se preocupa com a portabilidade da sua aplicação,sugerimos que você use avançadaAPI rather than sin6_scope_id. API em vez de sin6_scope_id./77/ /77/------------------------------------------------------------------------*Page 86* *Página 86*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/ /Internals IPv6/In the kernel, an interface index for link-local scoped address isembedded into 2nd 16bit-word (3rd and 4th byte) in No kernel, um índiceinterface para endereço link-local escopo é incorporado 2 16bit-palavra(3 � e 4 byte) em

Page 100: 139920579 Versao Traduzida de Book

IPv6 address. Endereço IPv6. For example, you may see something like:Por exemplo, você pode ver algo como:fe80:1::200:f8ff:fe01:6317 fe80: 1 :: 200: f8ff: FE01: 6317in the routing table and interface address structure (structin6_ifaddr). na tabela e interface de estrutura de endereço deroteamento (struct in6_ifaddr). The address above is a link-localunicast O endereço acima é um unicast link-localaddress which belongs to a network interface whose interface identifieris 1. endereço que pertence a uma interface de rede, cuja interfaceidentificador é 1. The embedded index enables us to O índice incorporadopermite-nosidentify IPv6 link local addresses over multiple interfaces effectivelyand with only a little code change. identificar endereços locais de linkIPv6 sobre múltiplas interfaces de forma eficaz e com apenas uma pequenamudança de código.Routing daemons and configuration programs, like route6d(8) andifconfig(8), will need to manipulate the Routing daemon e programas deconfiguração, como route6d (8) e ifconfig (8), será necessário manipular o"embedded" scope index. "Embedded" índice de escopo. These programs userouting sockets and ioctls (like SIOCGIFADDR_IN6) and the kernel Essesprogramas usam soquetes de roteamento e IOCTLS (como SIOCGIFADDR_IN6) eokernelAPI will return IPv6 addresses with 2nd 16bit-word filled in. The APIsare for manipulating kernel internal structure. API retornará endereçosIPv6 com 2 16bit palavra preenchidos As APIs são para manipular aestrutura interna do kernel.Programs that use these APIs have to be prepared about differences inkernels anyway. Programas que usam essas APIs tem que estar preparadosobre as diferenças de kernels de qualquer maneira.When you specify scoped address to the command line, NEVER write theembedded form (such as ff02:1::1 or Quando você especificar o endereçoescopo da linha de comando, NUNCA escrever o formulário incorporado(como FF02: 1 :: 1 oufe80:2::fedc). fe80: 2 :: FEDC). This is not supposed to work. Isto nãoé suposto para trabalhar. Always use standard form, like ff02::1 orfe80::fedc, with command line Sempre usar o formulário padrão, como FF02:: 1 ou fe80 :: FEDC, com linha de comandooption for specifying interface (like opção para interface deespecificação (comoping6 -I ne0 ff02::1 ping6-I ne0 FF02 :: 1). ). In general, if a command does not have command Em geral, se umcomando não tem comandoline option to specify outgoing interface, that command is not ready toaccept scoped address. opção de linha para especificar interface desaída, esse comando não está pronto para aceitar o endereço escopo. Thismay seem to be Isso pode pareceropposite from IPv6's premise to support "dentist office" situation.oposto a premissa de IPv6 para apoiar "dentista escritório" a situação.We believe that specifications need some Acreditamos que asespecificações precisar de algumimprovements for this. melhorias para isso.Some of the userland tools support extended numeric IPv6 syntax, asdocumented in Algumas das ferramentas userlândia apoiar sintaxe IPv6numérico estendido, conforme documentado nodraft-ietf-ipngwg-scopedaddr-format-00.txtprojecto-IETF-ipngwg-scopedaddr-format-00.txt. . You can specify outgoing link, by using name of the Você podeespecificar link de saída, usando o nome dooutgoing interface like "fe80::1%ne0". interface de saída como "fe80 ::1% ne0". This way you will be able to specify link-local scoped address

Page 101: 139920579 Versao Traduzida de Book

without much Desta forma, você será capaz de especificar endereçolink-local escopo sem muitotrouble. problemas.To use this extension in your program, you'll need to usegetaddrinfo(3), and getnameinfo(3) with Para usar esta extensão em seuprograma, você vai precisar usar getaddrinfo (3), e getnameinfo (3) comNI_WITHSCOPEID. NI_WITHSCOPEID. The implementation currently assumes1-to-1 relationship between a link and an interface, A aplicação assumeactualmente uma-a-uma relação entre uma ligação e uma interface,which is stronger than what specs say. que é mais forte do queespecificações dizem.*14.1.1.4.* *14.1.1.4.* *Plug and Play* *Plug and Play*Most of the IPv6 stateless address autoconfiguration is implemented inthe kernel. A maioria dos apátridas endereço autoconfiguração do IPv6 éimplementado no kernel. Neighbor Discovery functions are FunçõesNeighbor Discovery sãoimplemented in the kernel as a whole. implementado no núcleo como umtodo. Router Advertisement (RA) input for hosts is implemented in thekernel. Entrada Router Advertisement (RA) para os anfitriões éimplementado no kernel.Router Solicitation (RS) output for endhosts, RS input for routers, andRA output for routers are implemented in the Solicitação Router (RS)saída para endhosts, entrada RS para roteadores e saída de RA pararoteadores são implementados nouserland. userland.*14.1.1.4.1.* *14.1.1.4.1.* *Assignment of link-local, and specialaddresses* *Atribuição de endereços link-local, e especial*IPv6 link-local address is generated from IEEE802 address (ethernet MACaddress). Endereço IPv6 link-local é gerado a partir IEEE802 endereço(endereço Ethernet MAC). Each of interface is assigned an Cada umainterface é atribuído umIPv6 link-local address automatically, when the interface becomes up(IFF_UP). Endereço IPv6 link-local automaticamente, quando a interfacetorna-se up (IFF_UP). Also, direct route for the link-local Além disso,a rota direta para o link-localaddress is added to routing table. endereço é adicionado à tabela deroteamento./78/ /78/------------------------------------------------------------------------*Page 87* *Página 87*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/ /Internals IPv6/Here is an output of netstat command: Aqui é uma saída do comando netstat:Internet6: Internet6:Destination DestinoGateway Porta de entradaFlags BandeirasNetif Expire Netif vencimentofe80:1::%ed0/64 fe80: 1 ::% ed0/64link#1 link # 1UC UCed0 ed0fe80:2::%ep0/64 fe80: 2 ::% ep0/64link#2 link # 2UC UCep0 ep0Interfaces that has no IEEE802 address (pseudo interfaces like tunnelinterfaces, or ppp interfaces) will borrow Interfaces que não temendereço IEEE802 (interfaces de pseudo, como interfaces de túnel, ouinterfaces PPP) vai emprestar

Page 102: 139920579 Versao Traduzida de Book

IEEE802 address from other interfaces, such as ethernet interfaces,whenever possible. IEEE802 endereço de outras interfaces, como asinterfaces Ethernet, sempre que possível. If there is no IEEE802 Se nãohouver nenhuma IEEE802hardware attached, last-resort pseudorandom value, which is fromMD5(hostname), will be used as source of hardware anexo, valor pseudoúltimo recurso, que é de MD5 (hostname), será utilizado como fonte delink-local address. link-local address. If it is not suitable for yourusage, you will need to configure the link-local address manually. Senão é adequado para o seu uso, você precisará configurar o endereçolink-local manualmente.If an interface is not capable of handling IPv6 (such as lack ofmulticast support), link-local address will not be Se uma interface nãoé capaz de lidar com IPv6 (como a falta de suporte a multicast), oendereço link-local não seráassigned to that interface. atribuído a essa interface. See section 2for details. Ver secção 2 para mais detalhes.Each interface joins the solicited multicast address and the link-localall-nodes multicast addresses (eg Cada interface junta-se ao endereço demulticast solicitados e os locais de ligação de todos os nós demulticast endereços (egfe80::1:ff01:6317 and ff02::1, respectively, on the link the interfaceis attached). fe80 :: 1: FF01: 6317 e FF02 :: 1, respectivamente, nolink a interface está em anexo). In addition to a link-local address,Além de um endereço link-local,the loopback address (::1) will be assigned to the loopback interface. oendereço de loopback (:: 1) será atribuído à interface loopback. Also,::1/128 and ff01::/32 are automatically Além disso, :: 1/128 e FF01 :: /32 são automaticamenteadded to routing table, and loopback interface joins node-localmulticast group ff01::1. adicionados à tabela de roteamento, e interfaceloopback se junta a grupo multicast node-local FF01 :: 1.*14.1.1.4.2.* *14.1.1.4.2.* *Stateless address autoconfiguration onhosts* *Apátridas endereço autoconfiguração em hosts*In IPv6 specification, nodes are separated into two categories:/routers/ and /hosts/ . Na especificação IPv6, os nós são divididos emduas categorias: /os roteadores/ e /hosts./ Routers forward packetsaddressed Roteadores encaminhem pacotes endereçadosto others, hosts does not forward the packets. para os outros, osanfitriões não encaminhar os pacotes. net.inet6.ip6.forwarding defineswhether this node is router or host net.inet6.ip6.forwarding define seeste nó é roteador ou host(router if it is 1, host if it is 0). (Router se é um, anfitrião se for 0).When a host hears Router Advertisement from the router, a host mayautoconfigure itself by stateless address Quando um host ouve RouterAdvertisement do roteador, um host pode-se autoconfigure por apátridasendereçoautoconfiguration. autoconfiguração. This behavior can be controlled bynet.inet6.ip6.accept_rtadv (host autoconfigures itself if it is set Estecomportamento pode ser controlado por net.inet6.ip6.accept_rtadv (hostautoconfigura si se estiver definidoto 1). a 1). By autoconfiguration, network address prefix for thereceiving interface (usually global address prefix) is Porautoconfiguração, rede prefixo de endereço para a interface de recepção(prefixo de endereço normalmente global) éadded. adicionado. Default route is also configured. Rota padrão tambémestá configurado. Routers periodically generate Router Advertisementpackets. Routers gerar periodicamente pacotes Router Advertisement. Torequest an Para solicitar umadjacent router to generate RA packet, a host can transmit Router

Page 103: 139920579 Versao Traduzida de Book

Solicitation. roteador adjacente para gerar RA pacote, um host podetransmitir Solicitação Router. To generate a RS packet at any time, Paragerar um pacote de RS, em qualquer momento,use the /rtsol/ command. use o comando /rtsol./ rtsold(8) daemon is alsoavailable. rtsold (8) daemon também está disponível. rtsold(8) generatesRouter Solicitation whenever rtsold (8) gera Solicitação Router semprenecessary, and it works great for nomadic usage (notebooks/laptops).necessário, e ele funciona muito bem para o uso nômade (notebooks /laptops). If one wishes to ignore Router Advertisements, Se alguémdeseja ignorar anúncios roteador,use sysctl to set net.inet6.ip6.accept_rtadv to 0. usar sysctl paradefinir net.inet6.ip6.accept_rtadv a 0.To generate Router Advertisement from a router, use the rtadvd(8)daemon. Para gerar Router Advertisement de um roteador, use o rtadvd (8)daemon.Note that, IPv6 specification assumes the following items, andnonconforming cases are left unspecified:• •Only hosts will listen to router advertisements• •Hosts have single network interface (except loopback)Therefore, this is unwise to enable net.inet6.ip6.accept_rtadv onrouters, or multi-interface host. A misconfigurednode can behave strange (nonconforming configuration allowed for thosewho would like to do some experiments)./79/ /79/------------------------------------------------------------------------*Page 88* *Página 88*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/To summarize the sysctl knob:accept_rtadv forwarding role of the node--- --- ---0 0 host (to be manually configured)0 1 router1 0 autoconfigured host(spec assumes that host has singleinterface only, autoconfigured hostwith multiple interface isout-of-scope)1 1 invalid, or experimental(out-of-scope of spec)RFC2462 has validation rule against incoming RA prefix informationoption, in 5.5.3 (e). This is to protect hostsfrom malicious (or misconfigured) routers that advertise very shortprefix lifetime. There was an update from JimBound to ipngwg mailing list (look for "(ipng 6712)" in the archive) andit is implemented Jim's update.See 23.5.1.2 <#84> in the document for relationship between DAD andautoconfiguration.*14.1.1.5. Generic tunnel interface*GIF (Generic InterFace) is a pseudo interface for configured tunnel.Details are described in gif(4). Currently Atualmente• •v6 in v6• •v6 in v4• •v4 in v6• •

Page 104: 139920579 Versao Traduzida de Book

v4 in v4are available. estão disponíveis. Use gifconfig(8) to assign physical(outer) source and destination address to gif interfaces.Configuration that uses same address family for inner and outer IPheader (v4 in v4, or v6 in v6) is dangerous. It is Évery easy to configure interfaces and routing tables to perform infinitelevel of tunneling. /Please be warned/ .gif can be configured to be ECN-friendly. See 2 3.5.4.5 <#100> forECN-friendliness of tunnels, and gif(4) for how toconfigure.If you would like to configure an IPv4-in-IPv6 tunnel with gifinterface, read gif(4) carefully. You will need to Você vai precisar deremove IPv6 link-local address automatically assigned to the gif interface./80/ /80/------------------------------------------------------------------------*Page 89* *Página 89*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/*14.1.1.6. Source Address Selection*Current source selection rule is scope oriented (there are someexceptions - see below). For a given destination, asource IPv6 address is selected by the following rule:1. 1. If the source address is explicitly specified by the user (eg viathe advanced API), the specified address is used.2. 2. If there is an address assigned to the outgoing interface (whichis usually determined by looking up the routingtable) that has the same scope as the destination address, the addressis used.This is the most typical case.3. 3. If there is no address that satisfies the above condition, choosea global address assigned to one of the interfaceson the sending node.4. 4. If there is no address that satisfies the above condition, anddestination address is site local scope, choose a sitelocal address assigned to one of the interfaces on the sending node.5. 5. If there is no address that satisfies the above condition, choosethe address associated with the routing table entryfor the destination. This is the last resort, which may cause scopeviolation.For instance, ::1 is selected for ff01::1, fe80:1::200:f8ff:fe01:6317for fe80:1::2a0:24ff:feab:839b (note thatembedded interface index - described in 23.5.1.3 <#85> - helps us choosethe right source address. Those embedded indiceswill not be on the wire). If the outgoing interface has multiple addressfor the scope, a source is selected longestmatch basis (rule 3). Suppose 3ffe:501:808:1:200:f8ff:fe01:6317 and3ffe:2001:9:124:200:f8ff:fe01:6317 are given tothe outgoing interface. 3ffe:501:808:1:200:f8ff:fe01:6317 is chosen asthe source for the destination 3ffe:501:800::1.Note that the above rule is not documented in the IPv6 spec. It isconsidered "up to implementation" item. There are Temsome cases where we do not use the above rule. One example is connectedTCP session, and we use the address keptin tcb as the source. Another example is source address for NeighborAdvertisement. Under the spec (RFC24617.2.2) NA's source should be the target address of the correspondingNS's target. In this case we follow the specrather than the above longest-match rule.For new connections (when rule 1 does not apply), deprecated addresses(addresses with preferred lifetime = 0) will

Page 105: 139920579 Versao Traduzida de Book

not be chosen as source address if other choices are available. If noother choices are available, deprecated addresswill be used as a last resort. If there are multiple choice ofdeprecated addresses, the above scope rule will be used tochoose from those deprecated addresses. If you would like to prohibitthe use of deprecated address for some reason,configure net.inet6.ip6.use_deprecated to 0. The issue related todeprecated address is described in RFC2462 5.5.4(NOTE: there is some debate underway in IETF ipngwg on how to use"deprecated" address).*14.1.1.7. Jumbo Payload*The Jumbo Payload hop-by-hop option is implemented and can be used tosend IPv6 packets with payloads longerthan 65,535 octets. But currently no physical interface whose MTU ismore than 65,535 is supported, so such/81/ /81/------------------------------------------------------------------------*Page 90* *Página 90*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/payloads can be seen only on the loopback interface (ie lo0).If you want to try jumbo payloads, you first have to reconfigure thekernel so that the MTU of the loopback interfaceis more than 65,535 bytes; add the following to the kernel configurationfile:options "LARGE_LOMTU" #To test jumbo payloadand recompile the new kernel.Then you can test jumbo payloads by the ping6(8) command with -b and -soptions. The -b option must be specifiedto enlarge the size of the socket buffer and the -s option specifies thelength of the packet, which should be more than65,535. For example, type as follows:*% ping6 -b 70000 -s 68000 ::1*The IPv6 specification requires that the Jumbo Payload option must notbe used in a packet that carries a fragmentheader. cabeçalho. If this condition is broken, an ICMPv6 ParameterProblem message must be sent to the sender. specification especificaçãois followed, but you cannot usually see an ICMPv6 error caused by thisrequirement.When an IPv6 packet is received, the frame length is checked andcompared to the length specified in the payloadlength field of the IPv6 header or in the value of the Jumbo Payloadoption, if any. If the former is shorter than thelatter, the packet is discarded and statistics are incremented. You cansee the statistics as output of netstat(8)command with '-s -p ip6' option:% netstat -s -p ip6ip6:(snip)1 with data size < data lengthSo, kernel does not send an ICMPv6 error unless the erroneous packet isan actual Jumbo Payload, that is, its packetsize is more than 65,535 bytes. As described above, currently nophysical interface with such a huge MTU issupported, so it rarely returns an ICMPv6 error.TCP/UDP over jumbogram is not supported at this moment. This is becausewe have no medium (other thanloopback) to test this. Contact us if you need this.IPsec does not work on jumbograms. This is due to some specificationtwists in supporting AH with jumbograms

Page 106: 139920579 Versao Traduzida de Book

(AH header size influences payload length, and this makes it real hardto authenticate inbound packet with jumbopayload option as well as AH).There are fundamental issues in *BSD support for jumbograms. We wouldlike to address those, but we need moretime to finalize these. To name a few:• •mbuf pkthdr.len field is typed as "int" in 4.4BSD, so it will not holdjumbogram with len > 2G on 32bitarchitecture CPUs. If we would like to support jumbogram properly, thefield must be expanded to hold 4G + IPv6header + link-layer header. Therefore, it must be expanded to at leastint64_t (u_int32_t is NOT enough)./82/ /82/------------------------------------------------------------------------*Page 91* *Página 91*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/• •We mistakingly use "int" to hold packet length in many places. We needto convert them into larger integral type.It needs a great care, as we may experience overflow during packetlength computation.• •We mistakingly check for ip6_plen field of IPv6 header for packetpayload length in various places. We should bechecking mbuf pkthdr.len instead. ip6_input() will perform sanity checkon jumbo payload option on input, andwe can safely use mbuf pkthdr.len afterwards.• •TCP code needs a careful update in bunch of places, of course.*14.1.1.8. Loop prevention in header processing*IPv6 specification allows arbitrary number of extension headers to beplaced onto packets. If we implement IPv6packet processing code in the way BSD IPv4 code is implemented, kernelstack may overflow due to long functioncall chain. sys/netinet6 code is carefully designed to avoid kernelstack overflow. Because of this, sys/netinet6 codedefines its own protocol switch structure, as "struct ip6protosw" (seenetinet6/ip6protosw.h). ). There is no suchupdate to IPv4 part (sys/netinet) for compatibility, but small change isadded to its pr_input() prototype. So "structipprotosw" is also defined. Because of this, if you receiveIPsec-over-IPv4 packet with massive number of IPsecheaders, kernel stack may blow up. IPsec-over-IPv6 is okay. (Off-course,for those all IPsec headers to be processed,each such IPsec header must pass each IPsec check. So an anonymousattacker won't be able to do such an attack.)*14.1.1.9. ICMPv6*After RFC2463 was published, IETF ipngwg has decided to disallow ICMPv6error packet against ICMPv6 redirect,to prevent ICMPv6 storm on a network medium. This is already implementedinto the kernel.*14.1.1.10.* *Applications* *Aplicações*For userland programming, we support IPv6 socket API as specified inRFC2553, RFC2292 and upcoming internetdrafts. Rascunhos.TCP/UDP over IPv6 is available and quite stable. You can enjoytelnet(1), ftp(1), rlogin(1), rsh(1), ssh(1), etc. These

Page 107: 139920579 Versao Traduzida de Book

applications are protocol independent. That is, they automaticallychooses IPv4 or IPv6 according to DNS.*14.1.1.11. Kernel Internals*While ip_forward() calls ip_output(), ip6_forward() directly callsif_output() since routers must not divide IPv6packets into fragments./83/ /83/------------------------------------------------------------------------*Page 92* *Página 92*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/ICMPv6 should contain the original packet as long as possible up to1280. UDP6/IP6 port unreach, for instance,should contain all extension headers and the *unchanged* UDP6 and IP6headers. So, all IP6 functions except TCPnever convert network byte order into host byte order, to save theoriginal packet.tcp_input(), udp6_input() and icmp6_input() can't assume that IP6 headeris preceding the transport headers due toextension headers. So, in6_cksum() was implemented to handle packetswhose IP6 header and transport header is notcontinuous. TCP/IP6 nor UDP6/IP6 header structure don't exist forchecksum calculation.To process IP6 header, extension headers and transport headers easily,network drivers are now required to storepackets in one internal mbuf or one or more external mbufs. A typicalold driver prepares two internal mbufs for 96 -204 bytes data, however, now such packet data is stored in one externalmbuf.netstat -s -p ip6tells you whether or not your driver conforms such requirement. In thefollowing example,"cce0" violates the requirement. (For more information, refer to Section2.)Mbuf statistics:317 one mbuftwo or more mbuf::lo0 = 8cce0 = 103282 one ext mbuf0 two or more ext mbufEach input function calls IP6_EXTHDR_CHECK in the beginning to check ifthe region between IP6 and its headeris continuous. IP6_EXTHDR_CHECK calls m_pullup() only if the mbuf hasM_LOOP flag, that is, the packetcomes from the loopback interface. m_pullup() is never called forpackets coming from physical network interfaces.Both IP and IP6 reassemble functions never call m_pullup().*14.1.1.12. IPv4 mapped address and IPv6 wildcard socket*RFC2553 describes IPv4 mapped address (3.7) and special behavior of IPv6wildcard bind socket (3.8). The specallows you to:• •Accept IPv4 connections by AF_INET6 wildcard bind socket.• •Transmit IPv4 packet over AF_INET6 socket by using special form of theaddress like ::ffff:10.1.1.1.but the spec itself is very complicated and does not specify how thesocket layer should behave. Here we call theformer one "listening side" and the latter one "initiating side", for

Page 108: 139920579 Versao Traduzida de Book

reference purposes.You can perform wildcard bind on both of the address families, on thesame port.The following table show the behavior of FreeBSD 4.x./84/ /84/------------------------------------------------------------------------*Page 93* *Página 93*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/listening sideinitiating side(AF_INET6 wildcard(connection to ::ffff:10.1.1.1)socket gets IPv4 conn.)--- ------ ---FreeBSD 4.xconfigurablesupported suportadodefault: enabledThe following sections will give you more details, and how you canconfigure the behavior.Comments on listening side:It looks that RFC2553 talks too little on wildcard bind issue,especially on the port space issue, failure mode andrelationship between AF_INET/INET6 wildcard bind. There can be severalseparate interpretation for this RFCwhich conform to it but behaves differently. So, to implement portableapplication you should assume nothing aboutthe behavior in the kernel. Using getaddrinfo(3) is the safest way. Portnumber space and wildcard bind issues werediscussed in detail on ipv6imp mailing list, in mid March 1999 and itlooks that there's no concrete consensus(means, up to implementers). You may want to check the mailing listarchives.If a server application would like to accept IPv4 and IPv6 connections,there will be two alternatives.One is using AF_INET and AF_INET6 socket (you'll need two sockets). Usegetaddrinfo(3) with AI_PASSIVE intoai_flags, and socket(2) and bind(2) to all the addresses returned. Byopening multiple sockets, you can acceptconnections onto the socket with proper address family. IPv4 connectionswill be accepted by AF_INET socket, andIPv6 connections will be accepted by AF_INET6 socket.Another way is using one AF_INET6 wildcard bind socket. Usegetaddrinfo(3) with AI_PASSIVE into ai_flags andwith AF_INET6 into ai_family, and set the 1st argument hostname to NULL.And socket(2) and bind(2) to theaddress returned. (should be IPv6 unspecified addr). You can accepteither of IPv4 and IPv6 packet via this onesocket. socket.To support only IPv6 traffic on AF_INET6 wildcard binded socketportably, always check the peer address when aconnection is made toward AF_INET6 listening socket. If the address isIPv4 mapped address, you may want toreject the connection. You can check the condition by usingIN6_IS_ADDR_V4MAPPED() macro.To resolve this issue more easily, there is system dependentsetsockopt(2) option, IPV6_BINDV6ONLY, used likebelow. abaixo.

Page 109: 139920579 Versao Traduzida de Book

int on;setsockopt(s, IPPROTO_IPV6, IPV6_BINDV6ONLY,(char *)&on, sizeof (on)) < 0));When this call succeed, then this socket only receive IPv6 packets.Comments on initiating side:/85/ /85/------------------------------------------------------------------------*Page 94* *Página 94*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/Advise to application implementers: to implement a portable IPv6application (which works on multiple IPv6kernels), we believe that the following is the key to the success:• •NEVER hardcode AF_INET nor AF_INET6.• •Use getaddrinfo(3) and getnameinfo(3) throughout the system. Never usegethostby*(), getaddrby*(), inet_*() orgetipnodeby*(). (To update existing applications to be IPv6 awareeasily, sometime getipnodeby*() will be useful.But if possible, try to rewrite the code to use getaddrinfo(3) andgetnameinfo(3).)• •If you would like to connect to destination, use getaddrinfo(3) and tryall the destination returned, like telnet(1)does.• •Some of the IPv6 stack is shipped with buggy getaddrinfo(3). Ship aminimal working version with yourapplication and use that as last resort.If you would like to use AF_INET6 socket for both IPv4 and IPv6 outgoingconnection, you will need to usegetipnodebyname(3). When you would like to update your existingapplication to be IPv6 aware with minimal effort,this approach might be chosen. But please note that it is a temporalsolution, because getipnodebyname(3) itself isnot recommended as it does not handle scoped IPv6 addresses at all. ForIPv6 name resolution, getaddrinfo(3) is thepreferred API. So you should rewrite your application to usegetaddrinfo(3), when you get the time to do it.When writing applications that make outgoing connections, story goesmuch simpler if you treat AF_INET andAF_INET6 as totally separate address family. {set,get}sockopt issue goessimpler, DNS issue will be made simpler.We do not recommend you to rely upon IPv4 mapped address.*14.1.1.12.1. unified tcp and inpcb code*FreeBSD 4.x uses shared tcp code between IPv4 and IPv6 (fromsys/netinet/tcp*) and separate udp4/6 code. It usesunified inpcb structure.The platform can be configured to support IPv4 mapped address. Kernelconfiguration is summarized as follows:• •By default, AF_INET6 socket will grab IPv4 connections in certaincondition, and can initiate connection to IPv4destination embedded in IPv4 mapped IPv6 address.• •You can disable it on entire system with sysctl like below.sysctl -w net.inet6.ip6.mapped_addr=0/14.1.1.12.1.1. listening side/Each socket can be configured to support special AF_INET6 wildcard bind

Page 110: 139920579 Versao Traduzida de Book

(enabled by default). You can disable iton each socket basis with setsockopt(2) like below./86/ /86/------------------------------------------------------------------------*Page 95* *Página 95*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/int on;setsockopt(s, IPPROTO_IPV6, IPV6_BINDV6ONLY,(char *)&on, sizeof (on)) < 0));Wildcard AF_INET6 socket grabs IPv4 connection if and only if thefollowing conditions are satisfied:• •there's no AF_INET socket that matches the IPv4 connection• •the AF_INET6 socket is configured to accept IPv4 traffic, iegetsockopt(IPV6_BINDV6ONLY) returns 0.There's no problem with open/close ordering./14.1.1.12.1.2. initiating side/FreeBSD 4.x supports outgoing connection to IPv4 mapped address(::ffff:10.1.1.1), if the node is configured tosupport IPv4 mapped address.*14.1.1.13. sockaddr_storage*When RFC2553 was about to be finalized, there was discussion on howstruct sockaddr_storage members are named.One proposal is to prepend "__" to the members (like "__ss_len") as theyshould not be touched. The other proposalwas that don't prepend it (like "ss_len") as we need to touch thosemembers directly. There was no clear consensuson it. nele.As a result, RFC2553 defines struct sockaddr_storage as follows:struct sockaddr_storage {u_char __ss_len; /* address length */u_char __ss_family; /* address family *//* and bunch of padding */}; };On the contrary, XNET draft defines as follows:struct sockaddr_storage {u_char ss_len; /* address length */u_char ss_family; /* address family *//* and bunch of padding */}; };/87/ /87/------------------------------------------------------------------------*Page 96* *Página 96*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/In December 1999, it was agreed that RFC2553bis should pick the latter(XNET) definition.Current implementation conforms to XNET definition, based on RFC2553bisdiscussion.If you look at multiple IPv6 implementations, you will be able to seeboth definitions. As an userland programmer,the most portable way of dealing with it is to:1. 1. ensure ss_family and/or ss_len are available on the platform, byusing GNU autoconf,2. 2. have -Dss_family=__ss_family to unify all occurrences (includingheader file) into __ss_family, or3. 3. never touch __ss_family. cast to sockaddr * and use sa_family like:struct sockaddr_storage ss;

Page 111: 139920579 Versao Traduzida de Book

family = ((struct sockaddr *)&ss)->sa_family*14.1.2. Network Drivers*Now following two items are required to be supported by standard drivers:1. 1. mbuf clustering requirement. In this stable release, we changedMINCLSIZE into MHLEN+1 for all theoperating systems in order to make all the drivers behave as we expect.2. 2. multicast. multicast. If ifmcstat(8) yields no multicast group fora interface, that interface has to be patched.If any of the driver don't support the requirements, then the drivercan't be used for IPv6 and/or IPseccommunication. comunicação. If you find any problem with your card usingIPv6/IPsec, then, please report it to< <[email protected]>. >.(NOTE: In the past we required all PCMCIA drivers to have a call toin6_ifattach(). We have no such requirementany more)*14.1.3.* *Translator* *Tradutor*We categorize IPv4/IPv6 translator into 4 types:• •/Translator A/ --- It is used in the early stage of transition to makeit possible to establish a connection from an IPv6host in an IPv6 island to an IPv4 host in the IPv4 ocean./88/ /88/------------------------------------------------------------------------*Page 97* *Página 97*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/• •/Translator B/ --- It is used in the early stage of transition to makeit possible to establish a connection from an IPv4host in the IPv4 ocean to an IPv6 host in an IPv6 island.• •/Translator C/ --- It is used in the late stage of transition to make itpossible to establish a connection from an IPv4host in an IPv4 island to an IPv6 host in the IPv6 ocean.• •/Translator D/ --- It is used in the late stage of transition to make itpossible to establish a connection from an IPv6host in the IPv6 ocean to an IPv4 host in an IPv4 island.TCP relay translator for category A is supported. This is called"FAITH". We also provide IP header translator forcategory A. (The latter is not yet put into FreeBSD 4.x yet.)*14.1.3.1. FAITH TCP relay translator*FAITH system uses TCP relay daemon called faithd(8) helped by thekernel. FAITH will reserve an IPv6 addressprefix, and relay TCP connection toward that prefix to IPv4 destination.For example, if the reserved IPv6 prefix is 3ffe:0501:0200:ffff::, andthe IPv6 destination for TCP connection is3ffe:0501:0200:ffff::163.221.202.12, the connection will be relayedtoward IPv4 destination 163.221.202.12.destination IPv4 node (163.221.202.12)^ ^| IPv4 tcp toward 163.221.202.12FAITH-relay dual stack node^ ^| IPv6 TCP toward 3ffe:0501:0200:ffff::163.221.202.12source IPv6 nodefaithd(8) must be invoked on FAITH-relay dual stack node.

Page 112: 139920579 Versao Traduzida de Book

For more details, consultsrc/usr.sbin/faithd/README*14.1.4. IPsec*IPsec is mainly organized by three components.1. 1. Policy Management2. 2. Key Management Key Management3. 3. AH and ESP handling/89/ /89/------------------------------------------------------------------------*Page 98* *Página 98*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/*14.1.4.1. Policy Management*The kernel implements experimental policy management code. There are twoway to manage security policy. One is Uma éto configure per-socket policy using setsockopt(2). In this cases,policy configuration is described inipsec_set_policy(3). The other is to configure kernel packetfilter-based policy using PF_KEY interface, viasetkey(8).The policy entry is not re-ordered with its indexes, so the order ofentry when you add is very significant.*14.1.4.2.* *Key Management* *Key Management*The key management code implemented in this kit (sys/netkey) is ahome-brew PFKEY v2 implementation. This Esteconforms to RFC2367.The home-brew IKE daemon, "racoon" is included in the kit(kame/kame/racoon). Basically you'll need to runracoon as daemon, then setup a policy to require keys (likeping -P 'out ipsec esp/transport//use'). ). The Okernel will contact racoon daemon as necessary to exchange keys.*14.1.4.3. AH and ESP handling*IPsec module is implemented as "hooks" to the standard IPv4/IPv6processing. When sending a packet,ip{,6}_output() checks if ESP/AH processing is required by checking if amatching SPD (Security Policy Database)is found. é encontrado. If ESP/AH is needed, {esp,ah}{4,6}_output() willbe called and mbuf will be updated accordingly. When a Quando umpacket is received, {esp,ah}4_input() will be called based on protocolnumber, ie (*inetsw[proto])().{esp,ah}4_input() will decrypt/check authenticity of the packet, andstrips off daisy-chained header and padding forESP/AH. It is safe to strip off the ESP/AH header on packet reception,since we will never use the received packet in"as is" form.By using ESP/AH, TCP4/6 effective data segment size will be affected byextra daisy-chained headers inserted byESP/AH. Our code takes care of the case.Basic crypto functions can be found in directory "sys/crypto". ESP/AHtransform are listed in {esp,ah}_core.c withwrapper functions. If you wish to add some algorithm, add wrapperfunction in {esp,ah}_core.c, and add your cryptoalgorithm code into sys/crypto.Tunnel mode is partially supported in this release, with the followingrestrictions:• •IPsec tunnel is not combined with GIF generic tunneling interface. Itneeds a great care because we may create aninfinite loop between ip_output() and tunnelifp->if_output(). Opinion

Page 113: 139920579 Versao Traduzida de Book

varies if it is better to unify them, or not.• •MTU and Don't Fragment bit (IPv4) considerations need more checking, butbasically works fine.• •Authentication model for AH tunnel must be revisited. We'll need toimprove the policy management engine,eventually. eventualmente./90/ /90/------------------------------------------------------------------------*Page 99* *Página 99*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/*14.1.4.4. Conformance to RFCs and IDs*The IPsec code in the kernel conforms (or, tries to conform) to thefollowing standards:"old IPsec" specification documented inrfc182[5-9].txt"new IPsec" specification documented inrfc240[1-6].txt, ,rfc241[01].txt, ,rfc2451.txtand edraft-mcdonald-simple-ipsec-api-01.txt(draft expired, but you can take fromftp://ftp.kame.net/pub/internet-drafts/(ftp://ftp.kame.net/pub/internet-drafts/)). (NOTE: IKE specifications,rfc241[7-9].txtare implemented in userland, as "racoon" IKE daemon)Currently supported algorithms are:• •old IPsec AH• •null crypto checksum (no document, just for debugging)• •keyed MD5 with 128bit crypto checksum (rfc1828.txt) )• •keyed SHA1 with 128bit crypto checksum (no document)• •HMAC MD5 with 128bit crypto checksum (rfc2085.txt) )• •HMAC SHA1 with 128bit crypto checksum (no document)• •old IPsec ESP• •null encryption (no document, similar torfc2410.txt) )• •DES-CBC mode (rfc1829.txt) )• •new IPsec AH

Page 114: 139920579 Versao Traduzida de Book

• •null crypto checksum (no document, just for debugging)• •keyed MD5 with 96bit crypto checksum (no document)• •keyed SHA1 with 96bit crypto checksum (no document)• •HMAC MD5 with 96bit crypto checksum (rfc2403.txt) )• •HMAC SHA1 with 96bit crypto checksum (rfc2404.txt) )• •new IPsec ESP• •null encryption (rfc2410.txt) )• •DES-CBC with derived IV (draft-ietf-ipsec-ciph-des-derived-01.txt, draft expired)• •DES-CBC with explicit IV (rfc2405.txt) )/91/ /91/------------------------------------------------------------------------*Page 100* *Página 100*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/• •3DES-CBC with explicit IV (rfc2451.txt) )• •BLOWFISH CBC (rfc2451.txt) )• •CAST128 CBC (rfc2451.txt) )• •RC5 CBC (rfc2451.txt) )• •each of the above can be combined with:• •ESP authentication with HMAC-MD5(96bit)• •ESP authentication with HMAC-SHA1(96bit)The following algorithms are NOT supported:• •old IPsec AH• •HMAC MD5 with 128bit crypto checksum + 64bit replay prevention (

Page 115: 139920579 Versao Traduzida de Book

rfc2085.txt) )• •keyed SHA1 with 160bit crypto checksum + 32bit padding (rfc1852.txt) )IPsec (in kernel) and IKE (in userland as "racoon") has been tested atseveral interoperability test events, and it isknown to interoperate with many other implementations well. Also,current IPsec implementation as quite widecoverage for IPsec crypto algorithms documented in RFC (we coveralgorithms without intellectual property issuesonly). apenas).*14.1.4.5. ECN consideration on IPsec tunnels*ECN-friendly IPsec tunnel is supported as described indraft-ipsec-ecn-00.txt. .Normal IPsec tunnel is described in RFC2401. On encapsulation, IPv4 TOSfield (or, IPv6 traffic class field) will becopied from inner IP header to outer IP header. On decapsulation outerIP header will be simply dropped. The Odecapsulation rule is not compatible with ECN, since ECN bit on theouter IP TOS/traffic class field will be lost.To make IPsec tunnel ECN-friendly, we should modify encapsulation anddecapsulation procedure. This is describedin http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt(http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt), chapter 3.IPsec tunnel implementation can give you three behaviors, by settingnet.inet.ipsec.ecn (or net.inet6.ipsec6.ecn) tosome value:• •RFC2401: no consideration for ECN (sysctl value -1)/92/ /92/------------------------------------------------------------------------*Page 101* *Página 101*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/• •ECN forbidden (sysctl value 0)• •ECN allowed (sysctl value 1)Note that the behavior is configurable in per-node manner, not per-SAmanner (draft-ipsec-ecn-00 wants per-SAconfiguration, but it looks too much for me).The behavior is summarized as follows (see source code for more detail):encapsulatedecapsulate--- ------ ---RFC2401copy all TOS bitsdrop TOS bits on outerfrom inner to outer.(use inner TOS bits as is)ECN forbiddencopy TOS bits except for ECNdrop TOS bits on outer(masked with 0xfc) from inner(use inner TOS bits as is)to outer. set ECN bits to 0.

Page 116: 139920579 Versao Traduzida de Book

ECN allowedcopy TOS bits except for ECNuse inner TOS bits with someCE (masked with 0xfe) fromchange. mudar. if outer ECN CE bitinner to outer.is 1, enable ECN CE bit onset ECN CE bit to 0.the inner.General strategy for configuration is as follows:• •if both IPsec tunnel endpoint are capable of ECN-friendly behavior,you'd better configure both end to "ECNallowed" (sysctl value 1).• •if the other end is very strict about TOS bit, use "RFC2401" (sysctlvalue -1).• •in other cases, use "ECN forbidden" (sysctl value 0).The default behavior is "ECN forbidden" (sysctl value 0).For more information, please refer to: Para mais informações, consulte:http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt(http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt),RFC2481 (Explicit Congestion Notification),src/sys/netinet6/{ah,esp}_input.c(Thanks goes to Kenjiro Cho <[email protected]> for detailed analysis)/93/ /93/------------------------------------------------------------------------*Page 102* *Página 102*

/Chapter 14./ /Capítulo 14./ /IPv6 Internals/*14.1.4.6.* *Interoperability* *Interoperability*Here are (some of) platforms that KAME code have tested IPsec/IKEinteroperability in the past. Note that both endsmay have modified their implementation, so use the following list justfor reference purposes.Altiga, Ashley-laurent (vpcom.com), Data Fellows (F-Secure), EricssonACC, FreeS/WAN, HITACHI, IBM AIX,IIJ, Intel, Microsoft WinNT, NIST (linux IPsec + plutoplus), Netscreen,OpenBSD, RedCreek, Routerware, SSH,Secure Computing, Soliton, Toshiba, VPNet, Yamaha RT100i/94/ /94/------------------------------------------------------------------------*Page 103* *Página 103*

*VIII.* *VIII.* *Network Filesystems*------------------------------------------------------------------------*Page 104* *Página 104*

*Chapter 15.* *Capítulo 15.* *AFS* *AFS*AFS, NFS, SANs etc]/96/ /96/------------------------------------------------------------------------*Page 105* *Página 105*

*IX.* *IX.* *Terminal Handling*------------------------------------------------------------------------*Page 106* *Página 106*

Page 117: 139920579 Versao Traduzida de Book

*Chapter 16. Syscons*Syscons, tty, PCVT, serial console, screen savers, etc/98/ /98/------------------------------------------------------------------------*Page 107* *Página 107*

*X. Sound*------------------------------------------------------------------------*Page 108* *Página 108*

*Chapter 17. OSS*OSS, waveforms, etc/100/ /100/------------------------------------------------------------------------*Page 109* *Página 109*

*XI.* *XI.* *Device Drivers*------------------------------------------------------------------------*Page 110* *Página 110*

*Chapter 18. Writing FreeBSD Device Drivers*This chapter was written by Murray Stokely <[email protected]> with selections from a variety of sourcesincluding the intro(4) man page by Jörg Wunsch <[email protected]>. >.*18.1.* *Introduction* *Introdução*This chapter provides a brief introduction to writing device drivers forFreeBSD. A device in this context is a termused mostly for hardware-related stuff that belongs to the system, likedisks, printers, or a graphics display with itskeyboard. teclado. A device driver is the software component of theoperating system that controls a specific device. There Láare also so-called pseudo-devices where a device driver emulates thebehaviour of a device in software without anyparticular underlying hardware. Device drivers can be compiled into thesystem statically or loaded on demandthrough the dynamic kernel linker facility 'kld'.Most devices in a Unix-like operating system are accessed throughdevice-nodes, sometimes also called special files.These files are usually located under the directory/devin the file system hierarchy. Until devfs is fully integratedinto FreeBSD, each device node must be created statically andindependent of the existence of the associated devicedriver. motorista. Most device nodes on the system are created by runningMAKEDEV. .Device drivers can roughly be broken down into two categories; characterand network device drivers.*18.2.* *18.2.* *Dynamic Kernel Linker Facility - KLD*The kld interface allows system administrators to dynamically add andremove functionality from a running system.This allows device driver writers to load their new changes into arunning kernel without constantly rebooting to testchanges. mudanças.The kld interface is used through the following administrator commands :• •

Page 118: 139920579 Versao Traduzida de Book

kldload- loads a new kernel module• •kldunload- unloads a kernel module• •kldstat- lists the currently loadded modulesSkeleton Layout of a kernel module/* / ** KLD Skeleton* Inspired by Andrew Reiter's Daemonnews article/102/ /102/------------------------------------------------------------------------*Page 111* *Página 111*

/Chapter 18. Writing FreeBSD Device Drivers/*/ * /#include < sys/types.h >#include < sys/module.h >#include < sys/systm.h > /* uprintf */#include < sys/errno.h >#include < sys/param.h > /* defines used in kernel.h */#include < sys/kernel.h > /* types used in module initialization *//* / ** Load handler that deals with the loading and unloading of a KLD.*/ * /static int static intskel_loader(struct module *m, int what, void *arg){ {int err = 0;switch (what) {case MOD_LOAD:/* kldload */uprintf("Skeleton KLD loaded.\n");break; quebrar;case MOD_UNLOAD:uprintf("Skeleton KLD unloaded.\n");break; quebrar;default: default:err = EINVAL;break; quebrar;} }return(err);} }/* Declare this module to the rest of the kernel */DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);*18.2.1. Makefile*FreeBSD provides a makefile include that you can use to quickly compileyour kernel addition.SRCS=skeleton.cKMOD=skeleton.include < bsd.kmod.mk >/103/ /103/------------------------------------------------------------------------*Page 112* *Página 112*

/Chapter 18. Writing FreeBSD Device Drivers/Simply runningmake fazer

Page 119: 139920579 Versao Traduzida de Book

with this makefile will create a fileskeleton.kothat can be loaded into your system bytyping :# #kldload -v ./skeleton.ko*18.3. Accessing a device driver*Unix provides a common set of system calls for user applications to use.The upper layers of the kernel dispatchthese calls to the corresponding device driver when a user accesses adevice node. The O/dev/MAKEDEVscript makesmost of the device nodes for your system but if you are doing your owndriver development it may be necessary tocreate your own device nodes withmknod*18.3.1. Creating static device nodes*The Omknodcommand requires four arguments to create a device node. You mustspecify the name of this devicenode, the type of device, the major number of the device, and the minornumber of the device.*18.3.2. Dynamic device nodes*The device filesystem, or devfs, provides access to the kernel's devicenamespace in the global filesystemnamespace. This eliminates the problems of potentially having a devicedriver without a static device node, or adevice node without an installed device driver. Devfs is still a work inprogress, but it is already working quite nice.*18.4. Character Devices*A character device driver is one that transfers data directly to andfrom a user process. This is the most common typeof device driver and there are plenty of simple examples in the sourcetree.This simple example pseudo-device remembers whatever values you write toit and can then supply them back to youwhen you read from it./* / ** Simple 'echo' pseudo-device KLD* */104/ /104/------------------------------------------------------------------------*Page 113* *Página 113*

/Chapter 18. Writing FreeBSD Device Drivers/* Murray Stokely*/ * /#define MIN(a,b) (((a) < (b)) ? (a) : (b))#include < sys/types.h >#include < sys/module.h >#include < sys/systm.h > /* uprintf */#include < sys/errno.h >#include < sys/param.h > /* defines used in kernel.h */#include < sys/kernel.h > /* types used in module initialization */#include < sys/conf.h >/* cdevsw struct */#include < sys/uio.h >/* uio struct */

Page 120: 139920579 Versao Traduzida de Book

#include < sys/malloc.h >#define BUFFERSIZE 256/* Function prototypes */d_open_techo_open;d_close_techo_close;d_read_techo_read;d_write_techo_write;/* Character device entry points */static struct cdevsw echo_cdevsw = {echo_open,echo_close,echo_read,echo_write,noioctl,nopoll,nommap,nostrategy,"echo",33, 33,/* reserved for lkms - /usr/src/sys/conf/majors */nodump,nopsize,D_TTY,-1 -1}; };typedef struct s_echo {char msg[BUFFERSIZE];int len;} t_echo;/105/ /105/------------------------------------------------------------------------*Page 114* *Página 114*

/Chapter 18. Writing FreeBSD Device Drivers//* vars */static dev_t sdev;static int len;static int count;static t_echo *echomsg;MALLOC_DECLARE(M_ECHOBUF);MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");/* / ** This function acts is called by the kld[un]load(2) system calls to* determine what actions to take when a module is loaded or unloaded.*/ * /static int static intecho_loader(struct module *m, int what, void *arg){ {int err = 0;switch (what) {case MOD_LOAD:/* kldload */sdev = make_dev(& &echo_cdevsw,0, 0,

Page 121: 139920579 Versao Traduzida de Book

UID_ROOT,GID_WHEEL,0600,"echo");/* kmalloc memory for use by this driver *//* / *malloc(256,M_ECHOBUF,M_WAITOK); */MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);printf("Echo device loaded.\n");break; quebrar;case MOD_UNLOAD:destroy_dev(sdev);FREE(echomsg,M_ECHOBUF);printf("Echo device unloaded.\n");break; quebrar;default: default:err = EINVAL;break; quebrar;} }return(err);} }/106/ /106/------------------------------------------------------------------------*Page 115* *Página 115*

/Chapter 18. Writing FreeBSD Device Drivers/int intecho_open(dev_t dev, int oflags, int devtype, struct proc *p){ {int err = 0;uprintf("Opened device \"echo\" successfully.\n");return(err);} }int intecho_close(dev_t dev, int fflag, int devtype, struct proc *p){ {uprintf("Closing device \"echo.\"\n");return(0);} }/* / ** The read function just takes the buf that was saved via* echo_write() and returns it to userland for accessing.* uio(9)*/ * /int intecho_read(dev_t dev, struct uio *uio, int ioflag){ {int err = 0;int amt;/* How big is this read operation? Either as big as the user wants,or as big as the remaining data */amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ?echomsg->len - uio->uio_offset : 0);if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {uprintf("uiomove failed!\n");} }return err;} }/* / *

Page 122: 139920579 Versao Traduzida de Book

* echo_write takes in a character string and saves it* to buf for later accessing.*/ * /int int/107/ /107/------------------------------------------------------------------------*Page 116* *Página 116*

/Chapter 18. Writing FreeBSD Device Drivers/echo_write(dev_t dev, struct uio *uio, int ioflag){ {int err = 0;/* Copy the string in from user memory to kernel memory */err = copyin(uio->uio_iov->iov_base, echomsg->msg,MIN(uio->uio_iov->iov_len,BUFFERSIZE));/* Now we need to null terminate */*(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;/* Record the length */echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);if (err != 0) {uprintf("Write failed: bad address!\n");} }count++; contar + +;return(err);} }DEV_MODULE(echo,echo_loader,NULL);To install this driver you will first need to make a node on yourfilesystem with a command such as :# #mknod /dev/echo c 33 0With this driver loaded you should now be able to type something like :# #echo -n "Test Data" > /dev/echo# #cat /dev/echoTest DataReal hardware devices in the next chapter..Additional Resources Recursos adicionais• •Dynamic Kernel Linker (KLD) Facility Programming Tutorial(http://www.daemonnews.org/200010/blueprints.html) - Daemonnews(http://www.daemonnews.org) October2000 2000• •How to Write Kernel Drivers with NEWBUS(http://www.daemonnews.org/200007/newbus-intro.html) -Daemonnews (http://www.daemonnews.org) July 2000/108/ /108/------------------------------------------------------------------------*Page 117* *Página 117*

/Chapter 18. Writing FreeBSD Device Drivers/*18.5. Network Drivers*Drivers for network devices do not use device nodes in order to beaccessed. Their selection is based on otherdecisions made inside the kernel and instead of calling open(), use of anetwork device is generally introduced byusing the system call socket(2).man ifnet(), loopback device, Bill Paul's drivers, etc../109/ /109/

Page 123: 139920579 Versao Traduzida de Book

------------------------------------------------------------------------*Page 118* *Página 118*

*Chapter 19.* *Capítulo 19.* *ISA device drivers*/This chapter was written by Sergey Babkin <//[email protected]//> Modifications for the handbook made by//Murray Stokely <//[email protected]//>, Wylie Stilwell <//[email protected]//>, and Valentino Vaschetto//</ /<//[email protected]//>./ />./*19.1.* *19.1.* *Synopsis* *Sinopse*This chapter introduces the issues relevant to writing a driver for anISA device. The pseudo-code presented here israther detailed and reminiscent of the real code but is still onlypseudo-code. It avoids the details irrelevant to thesubject of the discussion. The real-life examples can be found in thesource code of real drivers. In particular thedrivers "ep" and "aha" are good sources of information.*19.2.* *Basic information* *Informação básica*A typical ISA driver would need the following include files:#include < sys/module.h >#include < sys/bus.h >#include < machine/bus.h >#include < machine/resource.h >#include < sys/rman.h >#include < isa/isavar.h >#include < isa/pnpvar.h >They describe the things specific to the ISA and generic bus subsystem.The bus subsystem is implemented in an object-oriented fashion, its mainstructures are accessed by associatedmethod functions.The list of bus methods implemented by an ISA driver is like one for anyother bus. For a hypothetical driver named"xxx" they would be:• •static void xxx_isa_identify (driver_t *, device_t);Normally used for bus drivers, not devicedrivers. But for ISA devices this method may have special use: if thedevice provides some device-specific(non-PnP) way to auto-detect devices this routine may implement it.• •static int xxx_isa_probe (device_t dev);Probe for a device at a known (or PnP) location. This Esteroutine can also accommodate device-specific auto-detection ofparameters for partially configured devices./110/ /110/------------------------------------------------------------------------*Page 119* *Página 119*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •static int xxx_isa_attach (device_t dev);Attach and initialize device.• •static int xxx_isa_detach (device_t dev);

Page 124: 139920579 Versao Traduzida de Book

Detach device before unloading the driver module.• •static int xxx_isa_shutdown (device_t dev);Execute shutdown of the device before systemshutdown.• •static int xxx_isa_suspend (device_t dev);Suspend the device before the system goes to thepower-save state. May also abort transition to the power-save state.• •static int xxx_isa_resume (device_t dev);Resume the device activity after return from power-savestate. Estado.xxx_isa_probe()and exxx_isa_attach()are mandatory, the rest of the routines are optional, depending on thedevice's needs.The driver is linked to the system with the following set of descriptions./* table of supported bus methods */static device_method_t xxx_isa_methods[] = {/* list all the bus method functions supported by the driver *//* omit the unsupported methods */DEVMETHOD(device_identify, xxx_isa_identify),DEVMETHOD(device_probe,xxx_isa_probe),DEVMETHOD(device_attach,xxx_isa_attach),DEVMETHOD(device_detach,xxx_isa_detach),DEVMETHOD(device_shutdown, xxx_isa_shutdown),DEVMETHOD(device_suspend,xxx_isa_suspend),DEVMETHOD(device_resume,xxx_isa_resume),{ 0, 0 }}; };static driver_t xxx_isa_driver = {"xxx",xxx_isa_methods,sizeof(struct xxx_softc),}; };static devclass_t xxx_devclass;DRIVER_MODULE(xxx, isa, xxx_isa_driver, xxx_devclass,load_function, load_argument);Here struct xxx_softc is a device-specific structure that containsprivate driver data and descriptors for the driver’sresources. recursos. The bus code automatically allocates one softcdescriptor per device as needed./111/ /111/------------------------------------------------------------------------*Page 120* *Página 120*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/If the driver is implemented as a loadable module thenload_function()is called to do driver-specificinitialization or clean-up when the driver is loaded or unloaded andload_argument is passed as one of its arguments.If the driver does not support dynamic loading (in other words it must

Page 125: 139920579 Versao Traduzida de Book

always be linked into kernel) then these valuesshould be set to 0 and the last definition would look like:DRIVER_MODULE(xxx, isa, xxx_isa_driver,xxx_devclass, 0, 0);If the driver is for a device which supports PnP then a table ofsupported PnP IDs must be defined. The table consistsof a list of PnP IDs supported by this driver and human-readabledescriptions of the hardware types and modelshaving these IDs. It looks like:static struct isa_pnp_id xxx_pnp_ids[] = {/* a line for each supported PnP ID */{ 0x12345678,"Our device model 1234A" },{ 0x12345679,"Our device model 1234B" },{ 0,NULL }, /* end of table */}; };If the driver does not support PnP devices it still needs an empty PnPID table, like:static struct isa_pnp_id xxx_pnp_ids[] = {{ 0,NULL }, /* end of table */}; };*19.3. Device_t pointer*Device_t is the pointer type for the device structure. Here we consideronly the methods interesting from the devicedriver writer's standpoint. The methods to manipulate values in thedevice structure are:• •device_t device_get_parent(dev)Get the parent bus of a device.• •driver_t device_get_driver(dev)Get pointer to its driver structure.• •char *device_get_name(dev)Get the driver name, such as "xxx" for our example.• •int device_get_unit(dev)Get the unit number (units are numbered from 0 for the devicesassociated witheach driver).• •char *device_get_nameunit(dev)Get the device name including the unit number, such as "xxx0" , "xxx1"and so on. e assim por diante.• •char *device_get_desc(dev)Get the device description. Normally it describes the exact model ofdevice inhuman-readable form./112/ /112/------------------------------------------------------------------------*Page 121* *Página 121*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •device_set_desc(dev, desc)Set the description. This makes the device description point to the

Page 126: 139920579 Versao Traduzida de Book

string descwhich may not be deallocated or changed after that.• •device_set_desc_copy(dev, desc)Set the description. The description is copied into an internaldynamically allocated buffer, so the string desc may be changedafterwards without adverse effects.• •void *device_get_softc(dev)Get pointer to the device descriptor (struct xxx_softc) associated withthisdevice. dispositivo.• •u_int32_t device_get_flags(dev)Get the flags specified for the device in the configuration file.A convenience functiondevice_printf(dev, fmt, ...)may be used to print the messages from the devicedriver. motorista. It automatically prepends the unitname and colon tothe message.The device_t methods are implemented in the file kern/bus_subr.c.*19.4.* *19,4.* *Config file and the order of identifying and probing**during auto-configuration*The ISA devices are described in the kernel config file like:device xxx0 at isa? port 0x300 irq 10 drq 5iomem 0xd0000 flags 0x1 sensitiveThe values of port, IRQ and so on are converted to the resource valuesassociated with the device. They are optional,depending on the device needs and abilities for auto-configuration. Forexample, some devices don't need DRQ at alland some allow the driver to read the IRQ setting from the deviceconfiguration ports. If a machine has multiple ISAbuses the exact bus may be specified in the configuration line, like"isa0" or "isa1", otherwise the device would besearched for on all the ISA buses."sensitive" is a resource requesting that this device must be probedbefore all non-sensitive devices. It is supportedbut does not seem to be used in any current driver.For legacy ISA devices in many cases the drivers are still able todetect the configuration parameters. But each deviceto be configured in the system must have a config line. If two devicesof some type are installed in the system butthere is only one configuration line for the corresponding driver, ie:device xxx0 at isa?then only one device will be configured.But for the devices supporting automatic identification by the means ofPlug-n-Play or some proprietary protocol oneconfiguration line is enough to configure all the devices in the system,like the one above or just simply:device xxx at isa?/113/ /113/------------------------------------------------------------------------*Page 122* *Página 122*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/If a driver supports both auto-identified and legacy devices and bothkinds are installed at once in one machine thenit's enough to describe in the config file the legacy devices only. Theauto-identified devices will be addedautomatically. automaticamente.

Page 127: 139920579 Versao Traduzida de Book

When an ISA bus is auto-configured the events happen as follows:All the drivers' identify routines (including the PnP identify routinewhich identifies all the PnP devices) are called inrandom order. As they identify the devices they add them to the list onthe ISA bus. Normally the drivers' identifyroutines associate their drivers with the new devices. The PnP identifyroutine does not know about the other driversyet so it does not associate any with the new devices it adds.The PnP devices are put to sleep using the PnP protocol to prevent themfrom being probed as legacy devices.The probe routines of non-PnP devices marked as "sensitive" are called.If probe for a device went successfully, theattach routine is called for it.The probe and attach routines of all non-PNP devices are called likewise.The PnP devices are brought back from the sleep state and assigned theresources they request: I/O and memoryaddress ranges, IRQs and DRQs, all of them not conflicting with theattached legacy devices.Then for each PnP device the probe routines of all the present ISAdrivers are called. The first one that claims thedevice gets attached. It is possible that multiple drivers would claimthe device with different priority, thehighest-priority driver wins. The probe routines must callISA_PNP_PROBE()to compare the actual PnP ID with thelist of the IDs supported by the driver and if the ID is not in thetable return failure. That means that absolutely everydriver, even the ones not supporting any PnP devices must callISA_PNP_PROBE(), at least with an empty PnP IDtable to return failure on unknown PnP devices.The probe routine returns a positive value (the error code) on error,zero or negative value on success.The negative return values are used when a PnP device supports multipleinterfaces. For example, an oldercompatibility interface and a newer advanced interface which aresupported by different drivers. Then both driverswould detect the device. The driver which returns a higher value in theprobe routine takes precedence (in otherwords, the driver returning 0 has highest precedence, returning -1 isnext, returning -2 is after it and so on). In resultthe devices which support only the old interface will be handled by theold driver (which should return -1 from theprobe routine) while the devices supporting the new interface as wellwill be handled by the new driver (whichshould return 0 from the probe routine). If multiple drivers return thesame value then the one called first wins. So ifa driver returns value 0 it may be sure that it won the priorityarbitration.The device-specific identify routines can also assign not a driver but aclass of drivers to the device. Then all thedrivers in the class are probed for this device, like the case with PnP.This feature is not implemented in any existingdriver and is not considered further in this document.Because the PnP devices are disabled when probing the legacy devicesthey will not be attached twice (once aslegacy and once as PnP). But in case of device-dependent identifyroutines it's the responsibility of the driver tomake sure that the same device won't be attached by the driver twice:once as legacy user-configured and once as

Page 128: 139920579 Versao Traduzida de Book

auto-identified./114/ /114/------------------------------------------------------------------------*Page 123* *Página 123*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/Another practical consequence for the auto-identified devices (both PnPand device-specific) is that the flags can notbe passed to them from the kernel configuration file. So they musteither not use the flags at all or use the flags fromthe device unit 0 for all the auto-identified devices or use the sysctlinterface instead of flags.Other unusual configurations may be accommodated by accessing theconfiguration resources directly with functionsof familiesresource_query_*()and eresource_*_value(). . Their implementations are located inkern/subr_bus.h. The old IDE disk driver i386/isa/wd.c contains examplesof such use. But the standard means ofconfiguration must always be preferred. Leave parsing the configurationresources to the bus configuration code.*19.5.* *Resources* *Recursos*The information that a user enters into the kernel configuration file isprocessed and passed to the kernel asconfiguration resources. This information is parsed by the busconfiguration code and transformed into a value ofstructure device_t and the bus resources associated with it. The driversmay access the configuration resourcesdirectly using functions resource_* for more complex cases ofconfiguration. But generally it's not needed norrecommended, so this issue is not discussed further.The bus resources are associated with each device. They are identifiedby type and number within the type. For the PelaISA bus the following types are defined:• •/SYS_RES_IRQ/ - interrupt number• •/SYS_RES_DRQ/ - ISA DMA channel number• •/SYS_RES_MEMORY/ - range of device memory mapped into the system memoryspace• •/SYS_RES_IOPORT/ - range of device I/O registersThe enumeration within types starts from 0, so if a device has twomemory regions if would have resources of typeSYS_RES_MEMORY numbered 0 and 1. The resource type has nothing to dowith the C language type, all theresource values have the C language type "unsigned long" and must becast as necessary. The resource numbers don'thave to be contiguous although for ISA they normally would be. Thepermitted resource numbers for ISA devicesare: são os seguintes:IRQ: 0-1DRQ: 0-1MEMORY: 0-3IOPORT: 0-7All the resources are represented as ranges, with a start value andcount. For IRQ and DRQ resources the count

Page 129: 139920579 Versao Traduzida de Book

would be normally equal to 1. The values for memory refer to thephysical addresses.Three types of activities can be performed on resources:/115/ /115/------------------------------------------------------------------------*Page 124* *Página 124*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •set/get• •allocate/release• •activate/deactivateSetting sets the range used by the resource. Allocation reserves therequested range that no other driver would be ableto reserve it (and checking that no other driver reserved this rangealready). Activation makes the resource accessibleto the driver doing whatever is necessary for that (for example, formemory it would be mapping into the kernelvirtual address space).The functions to manipulate resources are:• •int bus_set_resource(device_t dev, int type, int rid, u_long start,u_long count)Set a range for a resource. Returns 0 if successful, error codeotherwise. Normally the only reason this functionwould return an error is value of type, rid, start or count out ofpermitted range.• •dev - driver's device• •type - type of resource, SYS_RES_*• •rid - resource number (ID) within type• •start, count - resource range• •int bus_get_resource(device_t dev, int type, int rid, u_long *startp,u_long*countp)Get the range of resource. Returns 0 if successful, error code if theresource is not defined yet.• •u_long bus_get_resource_start(device_t dev, int type, int rid) u_longbus_get_resource_count (device_t dev, int type, int rid)Convenience functions to get only the start or count. Return 0 in caseof error, so if the resource start has 0 amongthe legitimate values it would be impossible to tell if the value is 0or an error occurred. Luckily, no ISA resourcesfor add-on drivers may have a start value equal 0.• •void bus_delete_resource(device_t dev, int type, int rid)Delete a resource, make it undefined.• •struct resource * bus_alloc_resource(device_t dev, int type, int *rid,u_long start,u_long end, u_long count, u_int flags)/116/ /116/------------------------------------------------------------------------

Page 130: 139920579 Versao Traduzida de Book

*Page 125* *Página 125*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/Allocate a resource as a range of count values not allocated by anyoneelse, somewhere between start and end.Alas, alignment is not supported. If the resource was not set yet it'sautomatically created. The special values ofstart 0 and end0 (all ones) means that the fixed values previously set bybus_set_resource()must be usedinstead: start and count as themselves and end=(start+count), in thiscase if the resource was not defined beforethen an error is returned. Although rid is passed by reference it's notset anywhere by the resource allocation codeof the ISA bus. (The other buses may use a different approach and modifyit).Flags are a bitmap, the flags interesting for the caller are:• •/RF_ACTIVE/ - causes the resource to be automatically activated afterallocation.• •/RF_SHAREABLE/ - resource may be shared at the same time by multipledrivers.• •/RF_TIMESHARE/ - resource may be time-shared by multiple drivers, ieallocated at the same time by many butactivated only by one at any given moment of time.• •Returns 0 on error. The allocated values may be obtained from thereturned handle using methodsrhand_*(). .• •int bus_release_resource(device_t dev, int type, int rid, structresource *r)• •Release the resource, r is the handle returned bybus_alloc_resource(). . Returns 0 on success, error codeotherwise.• •int bus_activate_resource(device_t dev, int type, int rid, structresource *r) intbus_deactivate_resource(device_t dev, int type, int rid, struct resource*r)• •Activate or deactivate resource. Return 0 on success, error codeotherwise. If the resource is time-shared andcurrently activated by another driver then EBUSY is returned.• •int bus_setup_intr(device_t dev, struct resource *r, int flags,driver_intr_t*handler, void *arg, void **cookiep) int bus_teardown_intr(device_t dev,structresource *r, void *cookie)• •Associate or de-associate the interrupt handler with a device. Return 0on success, error code otherwise.• •r - the activated resource handler describing the IRQ

Page 131: 139920579 Versao Traduzida de Book

flags - the interrupt priority level, one of:• •INTR_TYPE_TTY- terminals and other likewise character-type devices. To mask them usespltty(). .• •(INTR_TYPE_TTY | INTR_TYPE_FAST)- terminal type devices with small input buffer, critical to the dataloss on input (such as the old-fashioned serial ports). To mask them usespltty(). .• •INTR_TYPE_BIO- block-type devices, except those on the CAM controllers. To mask them usesplbio(). .• •INTR_TYPE_CAM- CAM (Common Access Method) bus controllers. To mask them usesplcam(). .• •INTR_TYPE_NET- network interface controllers. To mask them usesplimp(). ./117/ /117/------------------------------------------------------------------------*Page 126* *Página 126*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •INTR_TYPE_MISC- miscellaneous devices. There is no other way to mask them than bysplhigh()which quemasks all interrupts.When an interrupt handler executes all the other interrupts matching itspriority level will be masked. The only A únicaexception is the MISC level for which no other interrupts are masked andwhich is not masked by any other interrupt.• •/handler/ - pointer to the handler function, the type driver_intr_t isdefined as "void driver_intr_t(void *)"• •/arg/ - the argument passed to the handler to identify this particulardevice. It is cast from void* to any real type bythe handler. The old convention for the ISA interrupt handlers was touse the unit number as argument, the new(recommended) convention is using a pointer to the device softc structure.• •/cookie[p]/ - the value received fromsetup()is used to identify the handler when passed toteardown()A number of methods is defined to operate on the resource handlers(struct resource *). Those of interest to thedevice driver writers are:• •

Page 132: 139920579 Versao Traduzida de Book

u_long rman_get_start(r) u_long rman_get_end(r)Get the start and end of allocated resource range.• •void *rman_get_virtual(r)Get the virtual address of activated memory resource.*19.6. Bus memory mapping*In many cases data is exchanged between the driver and the devicethrough the memory. Two variants are possible:(a) memory is located on the device card(b) memory is the main memory of computerIn the case (a) the driver always copies the data back and forth betweenthe on-card memory and the main memory asnecessary. necessário. To map the on-card memory into the kernel virtualaddress space the physical address and length of theon-card memory must be defined as a SYS_RES_MEMORY resource. Thatresource can then be allocated andactivated, and its virtual address obtained usingrman_get_virtual(). . The older drivers used the functionpmap_mapdev()for this purpose, which should not be used directly any more. Now it'sone of the internal steps ofresource activation.Most of the ISA cards will have their memory configured for physicallocation somewhere in range 640KB-1MB.Some of the ISA cards require larger memory ranges which should beplaced somewhere under 16MB (because ofthe 24-bit address limitation on the ISA bus). In that case if themachine has more memory than the start address ofthe device memory (in other words, they overlap) a memory hole must beconfigured at the address range used bydevices. dispositivos. Many BIOSes allow to configure a memory hole of1MB starting at 14MB or 15MB. FreeBSD can handlethe memory holes properly if the BIOS reports them properly (old BIOSesmay have this feature broken)./118/ /118/------------------------------------------------------------------------*Page 127* *Página 127*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/In the case (b) just the address of the data is sent to the device, andthe device uses DMA to actually access the datain the main memory. Two limitations are present: First, ISA cards canonly access memory below 16MB. Second, the Em segundo lugar, ocontiguous pages in virtual address space may not be contiguous inphysical address space, so the device may have todo scatter/gather operations. The bus subsystem provides ready solutionsfor some of these problems, the rest has tobe done by the drivers themselves.Two structures are used for DMA memory allocation, bus_dma_tag_t andbus_dmamap_t. Tag describes theproperties required for the DMA memory. Map represents a memory blockallocated according to these properties.Multiple maps may be associated with the same tag.Tags are organized into a tree-like hierarchy with inheritance of theproperties. A child tag inherits all therequirements of its parent tag or may make them more strict but nevermore loose.Normally one top-level tag (with no parent) is created for each deviceunit. If multiple memory areas with different

Page 133: 139920579 Versao Traduzida de Book

requirements are needed for each device then a tag for each of them maybe created as a child of the parent tag.The tags can be used to create a map in two ways.First, a chunk of contiguous memory conformant with the tag requirementsmay be allocated (and later may befreed). This is normally used to allocate relatively long-living areasof memory for communication with the device.Loading of such memory into a map is trivial: it's always considered asone chunk in the appropriate physicalmemory range.Second, an arbitrary area of virtual memory may be loaded into a map.Each page of this memory will be checked forconformance to the map requirement. If it conforms then it's left atit's original location. If it is not then a freshconformant "bounce page" is allocated and used as intermediate storage.When writing the data from thenon-conformant original pages they will be copied to their bounce pagesfirst and then transferred from the bouncepages to the device. When reading the data would go from the device tothe bounce pages and then copied to theirnon-conformant original pages. The process of copying between theoriginal and bounce pages is calledsynchronization. sincronização. This is normally used on per-transferbasis: buffer for each transfer would be loaded, transfer doneand buffer unloaded.The functions working on the DMA memory are:• •int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,bus_size_tboundary, bus_addr_t lowaddr, bus_addr_t highaddr, bus_dma_filter_t*filter, void*filterarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, intflags,bus_dma_tag_t *dmat)Create a new tag. Returns 0 on success, the error code otherwise.• •/parent/ - parent tag, or NULL to create a top-level tag /alignment/ -required physical alignment of the memoryarea to be allocated for this tag. Use value 1 for "no specificalignment". Applies only to the futurebus_dmamem_alloc()but not mas nãobus_dmamap_create()calls. /boundary/ - physical address boundary thatmust not be crossed when allocating the memory. Use value 0 for "noboundary". Applies only to the future/119/ /119/------------------------------------------------------------------------*Page 128* *Página 128*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/bus_dmamem_alloc()but not mas nãobus_dmamap_create()calls. chamadas. Must be power of 2. If the memory is plannedto be used in non-cascaded DMA mode (ie the DMA addresses will besupplied not by the device itself but bythe ISA DMA controller) then the boundary must be no larger than 64KB(64*1024) due to the limitations ofthe DMA hardware.

Page 134: 139920579 Versao Traduzida de Book

• •/lowaddr, highaddr/ - the names are slighlty misleading; these valuesare used to limit the permitted range ofphysical addresses used to allocate the memory. The exact meaning variesdepending on the planned future use:• •For Parabus_dmamem_alloc()all the addresses from 0 to lowaddr-1 are considered permitted, thehigher onesare forbidden.• •For Parabus_dmamap_create()all the addresses outside the inclusive range [lowaddr; highaddr] areconsideredaccessible. acessível. The addresses of pages inside the range arepassed to the filter function which decides if they areaccessible. acessível. If no filter function is supplied then all therange is considered unaccessible.• •For the ISA devices the normal values (with no filter function) are:lowaddr = BUS_SPACE_MAXADDR_24BIThighaddr = BUS_SPACE_MAXADDR• •/filter, filterarg/ - the filter function and its argument. If NULL ispassed for filter then the whole range [lowaddr,highaddr] is considered unaccessible when doingbus_dmamap_create(). . Otherwise the physical address ofeach attempted page in range [lowaddr; highaddr] is passed to the filterfunction which decides if it isaccessible. acessível. The prototype of the filter function is:int filterfunc(void *arg, bus_addr_t paddr)It Elemust return 0 if the page is accessible, non-zero otherwise.• •/maxsize/ - the maximal size of memory (in bytes) that may be allocatedthrough this tag. In case it's difficult toestimate or could be arbitrarily big, the value for ISA devices would beBUS_SPACE_MAXSIZE_24BIT.• •/nsegments/ - maximal number of scatter-gather segments supported by thedevice. If unrestricted then the valueBUS_SPACE_UNRESTRICTED should be used. This value is recommended for theparent tags, the actualrestrictions would then be specified for the descendant tags. Tags withnsegments equal toBUS_SPACE_UNRESTRICTED may not be used to actually load maps, they maybe used only as parent tags.The practical limit for nsegments seems to be about 250-300, highervalues will cause kernel stack overflow.But anyway the hardware normally can't support that many scatter-gatherbuffers.• •/maxsegsz/ - maximal size of a scatter-gather segment supported by thedevice. The maximal value for ISA devicewould be BUS_SPACE_MAXSIZE_24BIT.• •/flags/ - a bitmap of flags. The only interesting flags are:

Page 135: 139920579 Versao Traduzida de Book

• •/BUS_DMA_ALLOCNOW/ - requests to allocate all the potentially neededbounce pages when creating the tag/120/ /120/------------------------------------------------------------------------*Page 129* *Página 129*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •/BUS_DMA_ISA/ - mysterious flag used only on Alpha machines. It is notdefined for the i386 machines.Probably it should be used by all the ISA drivers for Alpha machines butit looks like there are no suchdrivers yet.• •/dmat/ - pointer to the storage for the new tag to be returned• •int bus_dma_tag_destroy(bus_dma_tag_t dmat)Destroy a tag. Returns 0 on success, the error code otherwise.dmat - the tag to be destroyed• •int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,bus_dmamap_t*mapp)Allocate an area of contiguous memory described by the tag. The size ofmemory to be allocated is tag's maxsize.Returns 0 on success, the error code otherwise. The result still has tobe loaded bybus_dmamap_load()before antesused to get the physical address of the memory.• •/dmat/ - the tag• •/vaddr/ - pointer to the storage for the kernel virtual address of theallocated area to be returned.• •flags - a bitmap of flags. The only interesting flag is:• •/BUS_DMA_NOWAIT/ - if the memory is not immediately available return theerror. If this flag is not set thenthe routine is allowed to sleep waiting until the memory will becomeavailable.• •/mapp/ - pointer to the storage for the new map to be returned• •void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)Free the memory allocated bybus_dmamem_alloc(). . As of now freeing of the memory allocated with ISArestrictions is not implemented. Because of this the recommended modelof use is to keep and re-use the allocatedareas for as long as possible. Do not lightly free some area and thenshortly allocate it again. That does not meanthat quebus_dmamem_free()should not be used at all: hopefully it will be properly implemented soon.• •/dmat/ - the tag• •

Page 136: 139920579 Versao Traduzida de Book

/vaddr/ - the kernel virtual address of the memory• •/map/ - the map of the memory (as returned frombus_dmamem_alloc()) )/121/ /121/------------------------------------------------------------------------*Page 130* *Página 130*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)Create a map for the tag, to be used inbus_dmamap_load()later. mais tarde. Returns 0 on success, the error code otherwise.• •/dmat/ - the tag• •/flags/ - theoretically, a bit map of flags. But no flags are definedyet, so as of now it will be always 0.• •/mapp/ - pointer to the storage for the new map to be returned• •int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)Destroy a map. Returns 0 on success, the error code otherwise.• •dmat - the tag to which the map is associated• •map - the map to be destroyed• •int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,bus_size_tbuflen, bus_dmamap_callback_t *callback, void *callback_arg, int flags)Load a buffer into the map (the map must be previously created bybus_dmamap_create()or oubus_dmamem_alloc()). ). All the pages of the buffer are checked for conformance to the tagrequirements and forthose not conformant the bounce pages are allocated. An array ofphysical segment descriptors is built and passedto the callback routine. This callback routine is then expected tohandle it in some way. The number of bouncebuffers in the system is limited, so if the bounce buffers are neededbut not immediately available the request willbe queued and the callback will be called when the bounce buffers willbecome available. Returns 0 if the callbackwas executed immediately or EINPROGRESS if the request was queued forfuture execution. In the latter case thesynchronization with queued callback routine is the responsibility ofthe driver.• •/dmat/ - the tag• •/map/ - the map• •/buf/ - kernel virtual address of the buffer• •/buflen/ - length of the buffer• •

Page 137: 139920579 Versao Traduzida de Book

/callback/ ,callback_arg- the callback function and its argumentThe prototype of callback function is:void callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)/122/ /122/------------------------------------------------------------------------*Page 131* *Página 131*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •/arg/ - the same as callback_arg passed tobus_dmamap_load()• •/seg/ - array of the segment descriptors• •/nseg/ - number of descriptors in array• •/error/ - indication of the segment number overflow: if it's set toEFBIG then the buffer did not fit into themaximal number of segments permitted by the tag. In this case only thepermitted number of descriptors will bein the array. Handling of this situation is up to the driver: dependingon the desired semantics it can eitherconsider this an error or split the buffer in two and handle the secondpart separatelyEach entry in the segments array contains the fields:• •/ds_addr/ - physical bus address of the segment• •/ds_len/ - length of the segment• •void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)unload the map.• •/dmat/ - tag• •/map/ - loaded map• •void bus_dmamap_sync (bus_dma_tag_t dmat, bus_dmamap_t map,bus_dmasync_op_t op)Synchronise a loaded buffer with its bounce pages before and afterphysical transfer to or from device. This is the Este é ofunction that does all the necessary copying of data between theoriginal buffer and its mapped version. The Obuffers must be synchronized both before and after doing the transfer.• •/dmat/ - tag• •/map/ - loaded map• •/op/ - type of synchronization operation to perform:• •BUS_DMASYNC_PREREAD- before reading from device into buffer• •BUS_DMASYNC_POSTREAD- after reading from device into buffer• •BUS_DMASYNC_PREWRITE

Page 138: 139920579 Versao Traduzida de Book

- before writing the buffer to device• •BUS_DMASYNC_POSTWRITE- after writing the buffer to device/123/ /123/------------------------------------------------------------------------*Page 132* *Página 132*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/As of now PREREAD and POSTWRITE are null operations but that may changein the future, so they must not beignored in the driver. Synchronization is not needed for the memoryobtained frombus_dmamem_alloc(). .Before calling the callback function frombus_dmamap_load()the segment array is stored in the stack. And it getspre-allocated for the maximal number of segments allowed by the tag.Because of this the practical limit for thenumber of segments on i386 architecture is about 250-300 (the kernelstack is 4KB minus the size of the userstructure, size of a segment array entry is 8 bytes, and some space mustbe left). Because the array is allocated basedon the maximal number this value must not be set higher than reallyneeded. Fortunately, for most of hardware themaximal supported number of segments is much lower. But if the driverwants to handle buffers with a very largenumber of scatter-gather segments it should do that in portions: loadpart of the buffer, transfer it to the device, loadnext part of the buffer, and so on.Another practical consequence is that the number of segments may limitthe size of the buffer. If all the pages in thebuffer happen to be physically non-contiguous then the maximal supportedbuffer size for that fragmented casewould be (nsegments * page_size). For example, if a maximal number of 10segments is supported then on i386maximal guaranteed supported buffer size would be 40K. If a higher sizeis desired then special tricks should be usedin the driver.If the hardware does not support scatter-gather at all or the driverwants to support some buffer size even if it’sheavily fragmented then the solution is to allocate a contiguous bufferin the driver and use it as intermediate storageif the original buffer does not fit.Below are the typical call sequences when using a map depend on the useof the map. The characters -> are used toshow the flow of time.For a buffer which stays practically fixed during all the time betweenattachment and detachment of a device:bus_dmamem_alloc -> bus_dmamap_load -> ...use buffer... -> ->bus_dmamap_unload -> bus_dmamem_freeFor a buffer that changes frequently and is passed from outside the driver:bus_dmamap_create ->-> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->-> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->... ...-> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->-> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->-> bus_dmamap_destroy

Page 139: 139920579 Versao Traduzida de Book

When loading a map created bybus_dmamem_alloc()the passed address and size of the buffer must be the sameas used inbus_dmamem_alloc(). . In this case it is guaranteed that the whole buffer will be mappedas one segment(so the callback may be based on this assumption) and the request willbe executed immediately (EINPROGRESSwill never be returned). All the callback needs to do in this case is tosave the physical address.A typical example would be:/124/ /124/------------------------------------------------------------------------*Page 133* *Página 133*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/static void static voidalloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error){ {*(bus_addr_t *)arg = seg[0].ds_addr;} }... ...int error; int erro;struct somedata {.... ....}; };struct somedata *vsomedata; /* virtual address */bus_addr_t psomedata; /* physical bus-relative address */bus_dma_tag_t tag_somedata;bus_dmamap_t map_somedata;... ...error=bus_dma_tag_create(parent_tag, alignment,boundary, lowaddr, highaddr, /*filter*/ NULL, /*filterarg*/ NULL,/*maxsize*/ sizeof(struct somedata), /*nsegments*/ 1,/*maxsegsz*/ sizeof(struct somedata), /*flags*/ 0,&tag_somedata);if(error)return error;error = bus_dmamem_alloc(tag_somedata, &vsomedata, /* flags*/ 0,&map_somedata);if(error)return error;bus_dmamap_load(tag_somedata, map_somedata, (void *)vsomedata,sizeof (struct somedata), alloc_callback,(void *) &psomedata, /*flags*/0);Looks a bit long and complicated but that's the way to do it. Thepractical consequence is: if multiple memory areasare allocated always together it would be a really good idea to combinethem all into one structure and allocate asone (if the alignment and boundary limitations permit).When loading an arbitrary buffer into the map created bybus_dmamap_create()special measures must be takento synchronize with the callback in case it would be delayed. The codewould look like:{ {int s;int error; int erro;/125/ /125/

Page 140: 139920579 Versao Traduzida de Book

------------------------------------------------------------------------*Page 134* *Página 134*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/s = splsoftvm();error = bus_dmamap_load(dmat,dmamap,buffer_ptr,buffer_len,callback,/*callback_arg*/ buffer_descriptor,/*flags*/0);if (error == EINPROGRESS) {/* / ** Do whatever is needed to ensure synchronization* with callback. Callback is guaranteed not to be started* until we do splx() or tsleep().*/ * /} }splx(s);} }Two possible approaches for the processing of requests are:1. 1. If requests are completed by marking them explicitly as done (suchas the CAM requests) then it would be simplerto put all the further processing into the callback driver which wouldmark the request when it's done. Then not muchextra synchronization is needed. For the flow control reasons it may bea good idea to freeze the request queue untilthis request gets completed.2. 2. If requests are completed when the function returns (such asclassic read or write requests on character devices)then a synchronization flag should be set in the buffer descriptor andtsleep()called. chamado. Later when the callback getscalled it will do it's processing and check this synchronization flag.If it's set then the callback should issue awakeup. In this approach the callback function could either do all theneeded processing (just like the previous case)or simply save the segments array in the buffer descriptor. Then aftercallback completes the calling function coulduse this saved segments array and do all the processing.*19.7.* *DMA* *DMA*The Direct Memory Access (DMA) is implemented in the ISA bus through theDMA controller (actually, two ofthem but that's an irrelevant detail). To make the early ISA devicessimple and cheap the logic of the bus control andaddress generation was concentrated in the DMA controller. Fortunately,FreeBSD provides a set of functions thatmostly hide the annoying details of the DMA controller from the devicedrivers.The simplest case is for the fairly intelligent devices. Like the busmaster devices on PCI they can generate the buscycles and memory addresses all by themselves. The only thing theyreally need from the DMA controller is busarbitration. arbitragem. So for this purpose they pretend to be cascadedslave DMA controllers. And the only thing needed from/126/ /126/------------------------------------------------------------------------*Page 135* *Página 135*

Page 141: 139920579 Versao Traduzida de Book

/Chapter 19./ /Capítulo 19./ /ISA device drivers/the system DMA controller is to enable the cascaded mode on a DMAchannel by calling the following functionwhen attaching the driver:void isa_dmacascade(int channel_number)All the further activity is done by programming the device. Whendetaching the driver no DMA-related functionsneed to be called.For the simpler devices things get more complicated. The functions usedare:• •int isa_dma_acquire(int chanel_number)Reserve a DMA channel. Returns 0 on success or EBUSY if the channel wasalready reserved by this or a differentdriver. motorista. Most of the ISA devices are not able to share DMAchannels anyway, so normally this function is calledwhen attaching a device. This reservation was made redundant by themodern interface of bus resources but stillmust be used in addition to the latter. If not used then later, otherDMA routines will panic.• •int isa_dma_release(int chanel_number)Release a previously reserved DMA channel. No transfers must be inprogress when the channel is released (aswell as the device must not try to initiate transfer after the channelis released).• •void isa_dmainit(int chan, u_int bouncebufsize)Allocate a bounce buffer for use with the specified channel. Therequested size of the buffer can't exceed 64KB.This bounce buffer will be automatically used later if a transfer bufferhappens to be not physically contiguous oroutside of the memory accessible by the ISA bus or crossing the 64KBboundary. If the transfers will be alwaysdone from buffers which conform to these conditions (such as thoseallocated bybus_dmamem_alloc()with comproper limitations) thenisa_dmainit()does not have to be called. But it's quite convenient to transfer arbitrarydata using the DMA controller. The bounce buffer will automatically careof the scatter-gather issues.• •/chan/ - channel number• •/bouncebufsize/ - size of the bounce buffer in bytes• •void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)Prepare to start a DMA transfer. This function must be called to set upthe DMA controller before actually startingtransfer on the device. It checks that the buffer is contiguous andfalls into the ISA memory range, if not then thebounce buffer is automatically used. If bounce buffer is required butnot set up byisa_dmainit()or too smallfor the requested transfer size then the system will panic. In case of awrite request with bounce buffer the data

Page 142: 139920579 Versao Traduzida de Book

will be automatically copied to the bounce buffer./127/ /127/------------------------------------------------------------------------*Page 136* *Página 136*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/• •flags - a bitmask determining the type of operation to be done. Thedirection bits B_READ and B_WRITE aremutually exclusive.• •B_READ - read from the ISA bus into memory• •B_WRITE - write from the memory to the ISA bus• •B_RAW - if set then the DMA controller will remember the buffer andafter the end of transfer willautomatically re-initialize itself to repeat transfer of the same bufferagain (of course, the driver may change thedata in the buffer before initiating another transfer in the device). Ifnot set then the parameters will work onlyfor one transfer, andisa_dmastart()will have to be called again before initiating the next transfer. UsingUtilizaçãoB_RAW makes sense only if the bounce buffer is not used.• •addr - virtual address of the buffer• •nbytes - length of the buffer. Must be less or equal to 64KB. Length of0 is not allowed: the DMA controller willunderstand it as 64KB while the kernel code will understand it as 0 andthat would cause unpredictable effects. For Parachannels number 4 and higher the length must be even because thesechannels transfer 2 bytes at a time. In case of Em caso dean odd length the last byte will not be transferred.• •chan - channel number• •void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)Synchronize the memory after device reports that transfer is done. Ifthat was a read operation with a bouncebuffer then the data will be copied from the bounce buffer to theoriginal buffer. Arguments are the same as forisa_dmastart(). . Flag B_RAW is permitted but it does not affectisa_dmadone()in any way.• •int isa_dmastatus(int channel_number)Returns the number of bytes left in the current transfer to betransferred. In case the flag B_READ was set inisa_dmastart()the number returned will never be equal to zero. At the end of transferit will be automaticallyreset back to the length of buffer. The normal use is to check thenumber of bytes left after the device signals thatthe transfer is completed. If the number of bytes is not 0 then probablysomething went wrong with that transfer.• •

Page 143: 139920579 Versao Traduzida de Book

int isa_dmastop(int channel_number)Aborts the current transfer and returns the number of bytes leftuntransferred./128/ /128/------------------------------------------------------------------------*Page 137* *Página 137*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/*19.8. xxx_isa_probe*This function probes if a device is present. If the driver supportsauto-detection of some part of device configuration(such as interrupt vector or memory address) this auto-detection must bedone in this routine.As for any other bus, if the device can not be detected or is detectedbut failed the self-test or some other problemhappened then it returns a positive value of error. The value ENXIO mustbe returned if the device is not present.Other error values may mean other conditions. Zero or negative valuesmean success. Most of the drivers return zeroas success.The negative return values are used when a PnP device supports multipleinterfaces. For example, an oldercompatibility interface and a newer advanced interface which aresupported by different drivers. Then both driverswould detect the device. The driver which returns a higher value in theprobe routine takes precedence (in otherwords, the driver returning 0 has highest precedence, one returning -1is next, one returning -2 is after it and so on).In result the devices which support only the old interface will behandled by the old driver (which should return -1from the probe routine) while the devices supporting the new interfaceas well will be handled by the new driver(which should return 0 from the probe routine).The device descriptor struct xxx_softc is allocated by the system beforecalling the probe routine. If the probe routinereturns an error the descriptor will be automatically deallocated by thesystem. So if a probing error occurs the drivermust make sure that all the resources it used during probe aredeallocated and that nothing keeps the descriptor frombeing safely deallocated. If the probe completes successfully thedescriptor will be preserved by the system and laterpassed to the routinexxx_isa_attach(). . If a driver returns a negative value it can't be sure that it willhave thehighest priority and its attach routine will be called. So in this caseit also must release all the resources beforereturning and if necessary allocate them again in the attach routine.When Quandoxxx_isa_probe()returns 0 releasing theresources before returning is also a good idea, a well-behaved drivershould do so. But in case if there is someproblem with releasing the resources the driver is allowed to keepresources between returning 0 from the proberoutine and execution of the attach routine.A typical probe routine starts with getting the device descriptor and unit:struct xxx_softc *sc = device_get_softc(dev);int unit = device_get_unit(dev);int pnperror;

Page 144: 139920579 Versao Traduzida de Book

int error = 0;sc->dev = dev; /* link it back */sc->unit = unit;Then check for the PnP devices. The check is carried out by a tablecontaining the list of PnP IDs supported by thisdriver and human-readable descriptions of the device modelscorresponding to these IDs.pnperror=ISA_PNP_PROBE(device_get_parent(dev), dev,xxx_pnp_ids); if(pnperror == ENXIO) return ENXIO;/129/ /129/------------------------------------------------------------------------*Page 138* *Página 138*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/The logic of ISA_PNP_PROBE is the following: If this card (device unit)was not detected as PnP then ENOENTwill be returned. If it was detected as PnP but its detected ID does notmatch any of the IDs in the table then ENXIOis returned. Finally, if it has PnP support and it matches on of the IDsin the table, 0 is returned and the appropriatedescription from the table is set bydevice_set_desc(). .If a driver supports only PnP devices then the condition would look like:if(pnperror != 0)return pnperror;No special treatment is required for the drivers which don't support PnPbecause they pass an empty PnP ID tableand will always get ENXIO if called on a PnP card.The probe routine normally needs at least some minimal set of resources,such as I/O port number to find the cardand probe it. Depending on the hardware the driver may be able todiscover the other necessary resourcesautomatically. automaticamente. The PnP devices have all the resourcespre-set by the PnP subsystem, so the driver does not need todiscover them by itself.Typically the minimal information required to get access to the deviceis the I/O port number. Then some devicesallow to get the rest of information from the device configurationregisters (though not all devices do that). So firstwe try to get the port start value:sc->port0 = bus_get_resource_start(dev,SYS_RES_IOPORT, 0 /*rid*/); if(sc->port0 == 0) return ENXIO;The base port address is saved in the structure softc for future use. Ifit will be used very often then calling theresource function each time would be prohibitively slow. If we don't geta port we just return an error. Some devicedrivers can instead be clever and try to probe all the possible ports,like this:/* table of all possible base I/O port addresses for this device */static struct xxx_allports {u_short port; /* port address */short used; /* flag: if this port is already used by some unit */} xxx_allports = {{ 0x300, 0 },{ 0x320, 0 },{ 0x340, 0 },{ 0, 0 } /* end of table */}; };... ...

Page 145: 139920579 Versao Traduzida de Book

int port, i;... .../130/ /130/------------------------------------------------------------------------*Page 139* *Page 139*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0 /*rid*/);if(port !=0 ) {for(i=0; xxx_allports[i].port!=0; i++) {if(xxx_allports[i].used || xxx_allports[i].port != port)continue;/* found it */xxx_allports[i].used = 1;/* do probe on a known port */return xxx_really_probe(dev, port);} }return ENXIO; /* port is unknown or already used */} }/* we get here only if we need to guess the port */for(i=0; xxx_allports[i].port!=0; i++) {if(xxx_allports[i].used)continue;/* mark as used - even if we find nothing at this port* at least we won't probe it in future*/ * /xxx_allports[i].used = 1;error = xxx_really_probe(dev, xxx_allports[i].port);if(error == 0) /* found a device at that port */return 0; retornar 0;} }/* probed all possible addresses, none worked */return ENXIO;Of course, normally the driver’sidentify()routine should be used for such things. But there may be one validreason why it may be better to be done inprobe(): if this probe would drive some other sensitive device crazy. The Oprobe routines are ordered with consideration of the "sensitive" flag:the sensitive devices get probed first and the restof devices later. But the Mas oidentify()routines are called before any probes, so they show no respect to thesensitivedevices and may upset them.Now, after we got the starting port we need to set the port count(except for PnP devices) because the kernel does nothave this information in the configuration file.if(pnperror /* only for non-PnP devices */&& bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port0,XXX_PORT_COUNT) < 0)/131/ /131/------------------------------------------------------------------------*Page 140* *Página 140*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/return ENXIO;Finally allocate and activate a piece of port address space (specialvalues of start and end mean "use those we set by

Page 146: 139920579 Versao Traduzida de Book

bus_set_resource()"):sc->port0_rid = 0;sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,&sc->port0_rid,/*start*/ 0, /*end*/0, /*count*/ 0, RF_ACTIVE);if(sc->port0_r == NULL)return ENXIO;Now having access to the port-mapped registers we can poke the device insome way and check if it reacts like it isexpected to. If it does not then there is probably some other device orno device at all at this address.Normally drivers don't set up the interrupt handlers until the attachroutine. Instead they do probes in the pollingmode using the usando o modoDELAY()function for timeout. The probe routine must never hang forever, all thewaits for thedevice must be done with timeouts. If the device does not respond withinthe time it's probably broken ormisconfigured and the driver must return error. When determining thetimeout interval give the device some extratime to be on the safe side: althoughDELAY()is supposed to delay for the same amount of time on any machine ithas some margin of error, depending on the exact CPU.If the probe routine really wants to check that the interrupts reallywork it may configure and probe the interrupts too.But that's not recommended./* implemented in some very device-specific way */if(error = xxx_probe_ports(sc))goto bad; /* will deallocate the resources before returning */The fucntionxxx_probe_ports()may also set the device description depending on the exact model ofdevice itdiscovers. But if there is only one supported device model this can beas well done in a hardcoded way. Of course, Claro que,for the PnP devices the PnP support sets the description from the tableautomatically.if(pnperror)device_set_desc(dev, "Our device model 1234");Then the probe routine should either discover the ranges of all theresources by reading the device configurationregisters or make sure that they were set explicitly by the user. Wewill consider it with an example of on-boardmemory. memória. The probe routine should be as non-intrusive aspossible, so allocation and check of functionality of the restof resources (besides the ports) would be better left to the attachroutine./132/ /132/------------------------------------------------------------------------*Page 141* *Página 141*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/The memory address may be specified in the kernel configuration file oron some devices it may be pre-configured innon-volatile configuration registers. If both sources are available anddifferent, which one should be used? Probably Provavelmenteif the user bothered to set the address explicitly in the kernel

Page 147: 139920579 Versao Traduzida de Book

configuration file they know what they're doing and thisone should take precedence. An example of implementation could be:/* try to find out the config address first */sc->mem0_p = bus_get_resource_start(dev, SYS_RES_MEMORY, 0 /*rid*/);if(sc->mem0_p == 0) { /* nope, not specified by user */sc->mem0_p = xxx_read_mem0_from_device_config(sc);if(sc->mem0_p == 0)/* can't get it from device config registers either */goto bad;} else { } Else {if(xxx_set_mem0_address_on_device(sc) < 0)goto bad; /* device does not support that address */} }/* just like the port, set the memory size,* for some devices the memory size would not be constant* but should be read from the device configuration registers instead* to accommodate different models of devices. Another option would* be to let the user set the memory size as "msize" configuration* resource which will be automatically handled by the ISA bus.*/ * /if(pnperror) { /* only for non-PnP devices */sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);if(sc->mem0_size == 0) /* not specified by user */sc->mem0_size = xxx_read_mem0_size_from_device_config(sc);if(sc->mem0_size == 0) {/* suppose this is a very old model of device without* auto-configuration features and the user gave no preference,* so assume the minimalistic case* (of course, the real value will vary with the driver)*/ * /sc->mem0_size = 8*1024;} }if(xxx_set_mem0_size_on_device(sc) < 0)goto bad; /* device does not support that size */if(bus_set_resource(dev, SYS_RES_MEMORY, /*rid*/0,/133/ /133/------------------------------------------------------------------------*Page 142* *Página 142*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/sc->mem0_p, sc->mem0_size) < 0)goto bad;} else { } Else {sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);} }Resources for IRQ and DRQ are easy to check by analogy.If all went well then release all the resources and return success.xxx_free_resources(sc);return 0; retornar 0;Finally, handle the troublesome situations. All the resources should bedeallocated before returning. We make use ofthe fact that before the structure softc is passed to us it gets zeroedout, so we can find out if some resource wasallocated: then its descriptor is non-zero.bad:xxx_free_resources(sc);if(error)return error;else /* exact error is unknown */return ENXIO;

Page 148: 139920579 Versao Traduzida de Book

That would be all for the probe routine. Freeing of resources is donefrom multiple places, so it's moved to a functionwhich may look like:static void static voidxxx_free_resources(sc)struct xxx_softc *sc;{ {/* check every resource and free if not zero *//* interrupt handler */if(sc->intr_r) {bus_teardown_intr(sc->dev, sc->intr_r, sc->intr_cookie);bus_release_resource(sc->dev, SYS_RES_IRQ, sc->intr_rid,sc->intr_r);sc->intr_r = 0;} }/* all kinds of memory maps we could have allocated */if(sc->data_p) {bus_dmamap_unload(sc->data_tag, sc->data_map);/134/ /134/------------------------------------------------------------------------*Page 143* *Página 143*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/sc->data_p = 0;} }if(sc->data) { /* sc->data_map may be legitimately equal to 0 *//* the map will also be freed */bus_dmamem_free(sc->data_tag, sc->data, sc->data_map);sc->data = 0;} }if(sc->data_tag) {bus_dma_tag_destroy(sc->data_tag);sc->data_tag = 0;} }... ... free other maps and tags if we have them ...if(sc->parent_tag) {bus_dma_tag_destroy(sc->parent_tag);sc->parent_tag = 0;} }/* release all the bus resources */if(sc->mem0_r) {bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->mem0_rid,sc->mem0_r);sc->mem0_r = 0;} }... ...if(sc->port0_r) {bus_release_resource(sc->dev, SYS_RES_IOPORT, sc->port0_rid,sc->port0_r);sc->port0_r = 0;} }} }*19.9. xxx_isa_attach*The attach routine actually connects the driver to the system if theprobe routine returned success and the system hadchosen to attach that driver. If the probe routine returned 0 then theattach routine may expect to receive the devicestructure softc intact, as it was set by the probe routine. Also if theprobe routine returns 0 it may expect that theattach routine for this device shall be called at some point in the

Page 149: 139920579 Versao Traduzida de Book

future. If the probe routine returns a negative valuethen the driver may make none of these assumptions.The attach routine returns 0 if it completed successfully or error codeotherwise./135/ /135/------------------------------------------------------------------------*Page 144* *Página 144*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/The attach routine starts just like the probe routine, with getting somefrequently used data into more accessiblevariables. variáveis.struct xxx_softc *sc = device_get_softc(dev);int unit = device_get_unit(dev);int error = 0;Then allocate and activate all the necessary resources. Because normallythe port range will be released beforereturning from probe, it has to be allocated again. We expect that theprobe routine had properly set all the resourceranges, as well as saved them in the structure softc. If the proberoutine had left some resource allocated then it doesnot need to be allocated again (which would be considered an error).sc->port0_rid = 0;sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port0_rid,/*start*/ 0, /*end*/0, /*count*/ 0, RF_ACTIVE);if(sc->port0_r == NULL)return ENXIO;/* on-board memory */sc->mem0_rid = 0;sc->mem0_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem0_rid,/*start*/ 0, /*end*/0, /*count*/ 0, RF_ACTIVE);if(sc->mem0_r == NULL)goto bad;/* get its virtual address */sc->mem0_v = rman_get_virtual(sc->mem0_r);The DMA request channel (DRQ) is allocated likewise. To initialize ituse functions of theisa_dma*()family. família. For Paraexample: exemplo:isa_dmacascade(sc->drq0);The interrupt request line (IRQ) is a bit special. Besides allocationthe driver's interrupt handler should be associatedwith it. Historically in the old ISA drivers the argument passed by thesystem to the interrupt handler was the deviceunit number. But in modern drivers the convention suggests passing thepointer to structure softc. The important O importantereason is that when the structures softc are allocated dynamically thengetting the unit number from softc is easywhile getting softc from unit number is difficult. Also this conventionmakes the drivers for different buses look moreuniform and allows them to share the code: each bus gets its own probe,attach, detach and other bus-specific routineswhile the bulk of the driver code may be shared among them.sc->intr_rid = 0;sc->intr_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->intr_rid,/136/ /136/------------------------------------------------------------------------*Page 145*

Page 150: 139920579 Versao Traduzida de Book

/Chapter 19./ /Capítulo 19./ /ISA device drivers//*start*/ 0, /*end*/0, /*count*/ 0, RF_ACTIVE);if(sc->intr_r == NULL)goto bad;/* / ** XXX_INTR_TYPE is supposed to be defined depending on the type of* the driver, for example as INTR_TYPE_CAM for a CAM driver*/ * /error = bus_setup_intr(dev, sc->intr_r, XXX_INTR_TYPE,(driver_intr_t *) xxx_intr, (void *) sc, &sc->intr_cookie);if(error)goto bad;If the device needs to make DMA to the main memory then this memoryshould be allocated like described before:error=bus_dma_tag_create(NULL, /*alignment*/ 4,/*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_24BIT,/*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL,/*maxsize*/ BUS_SPACE_MAXSIZE_24BIT,/*nsegments*/ BUS_SPACE_UNRESTRICTED,/*maxsegsz*/ BUS_SPACE_MAXSIZE_24BIT, /*flags*/ 0,&sc->parent_tag);if(error)goto bad;/* many things get inherited from the parent tag* sc->data is supposed to point to the structure with the shared data,* for example for a ring buffer it could be:* struct {* *u_short rd_pos;* *u_short wr_pos;* *char carbonizarbf[XXX_RING_BUFFER_SIZE]* } *data;*/ * /error=bus_dma_tag_create(sc->parent_tag, 1,0, BUS_SPACE_MAXADDR, 0, /*filter*/ NULL, /*filterarg*/ NULL,/*maxsize*/ sizeof(* sc->data), /*nsegments*/ 1,/*maxsegsz*/ sizeof(* sc->data), /*flags*/ 0,&sc->data_tag);if(error)goto bad;/137/ /137/------------------------------------------------------------------------*Page 146* *Página 146*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/error = bus_dmamem_alloc(sc->data_tag, &sc->data, /* flags*/ 0,&sc->data_map);if(error)goto bad;/* xxx_alloc_callback() just saves the physical address at* the pointer passed as its argument, in this case &sc->data_p.* See details in the section on bus memory mapping.* It can be implemented like:* ** static void* xxx_alloc_callback(void *arg, bus_dma_segment_t *seg,* *

Page 151: 139920579 Versao Traduzida de Book

int nseg, int error)* {* **(bus_addr_t *)arg = seg[0].ds_addr;* }*/ * /bus_dmamap_load(sc->data_tag, sc->data_map, (void *)sc->data,sizeof (* sc->data), xxx_alloc_callback, (void *) &sc->data_p,/*flags*/0);After all the necessary resources are allocated the device should beinitialized. The initialization may include testingthat all the expected features are functional.if(xxx_initialize(sc) < 0)goto bad;The bus subsystem will automatically print on the console the devicedescription set by probe. But if the driver wantsto print some extra information about the device it may do so, for example:device_printf(dev, "has on-card FIFO buffer of %d bytes\n", sc->fifosize);If the initialization routine experiences any problems then printingmessages about them before returning error is alsorecommended. recomendado.The final step of the attach routine is attaching the device to itsfunctional subsystem in the kernel. The exact way todo it depends on the type of the driver: a character device, a blockdevice, a network device, a CAM SCSI bus deviceand so on. e assim por diante.If all went well then return success.error = xxx_attach_subsystem(sc);if(error)goto bad;/138/ /138/------------------------------------------------------------------------*Page 147* *Página 147*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/return 0; retornar 0;Finally, handle the troublesome situations. All the resources should bedeallocated before returning an error. We Nósmake use of the fact that before the structure softc is passed to us itgets zeroed out, so we can find out if someresource was allocated: then its descriptor is non-zero.bad:xxx_free_resources(sc);if(error)return error;else /* exact error is unknown */return ENXIO;That would be all for the attach routine.*19.10. xxx_isa_detach*If this function is present in the driver and the driver is compiled asa loadable module then the driver gets the abilityto be unloaded. This is an important feature if the hardware supportshot plug. But the ISA bus does not support hotplug, so this feature is not particularly important for the ISA devices.The ability to unload a driver may be usefulwhen debugging it, but in many cases installation of the new version ofthe driver would be required only after theold version somehow wedges the system and reboot will be needed anyway,so the efforts spent on writing the detachroutine may not be worth it. Another argument is that unloading would

Page 152: 139920579 Versao Traduzida de Book

allow upgrading the drivers on a productionmachine seems to be mostly theoretical. Installing a new version of adriver is a dangerous operation which shouldnever be performed on a production machine (and which is not permittedwhen the system is running in securemode). mode). Still the detach routine may be provided for the sake ofcompleteness.The detach routine returns 0 if the driver was successfully detached orthe error code otherwise.The logic of detach is a mirror of the attach. The first thing to do isto detach the driver from its kernel subsystem. If Sethe device is currently open then the driver has two choices: refuse tobe detached or forcibly close and proceed withdetach. The choice used depends on the ability of the particular kernelsubsystem to do a forced close and on thepreferences of the driver's author. Generally the forced close seems tobe the preferred alternative.struct xxx_softc *sc = device_get_softc(dev);int error; int erro;error = xxx_detach_subsystem(sc);if(error)return error;/139/ /139/------------------------------------------------------------------------*Page 148* *Página 148*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/Next the driver may want to reset the hardware to some consistent state.That includes stopping any ongoingtransfers, disabling the DMA channels and interrupts to avoid memorycorruption by the device. For most of thedrivers this is exactly what the shutdown routine does, so if it isincluded in the driver we can as well just call it.xxx_isa_shutdown(dev);And finally release all the resources and return success.xxx_free_resources(sc);return 0; retornar 0;*19.11. xxx_isa_shutdown*This routine is called when the system is about to be shut down. It isexpected to bring the hardware to someconsistent state. For most of the ISA devices no special action isrequired, so the function is not really necessarybecause the device will be re-initialized on reboot anyway. But somedevices have to be shut down with a specialprocedure, to make sure that they will be properly detected after softreboot (this is especially true for many deviceswith proprietary identification protocols). In any case disabling DMAand interrupts in the device registers andstopping any ongoing transfers is a good idea. The exact action dependson the hardware, so we don't consider it herein any details.xxx_intrThe interrupt handler is called when an interrupt is received which maybe from this particular device. The ISA busdoes not support interrupt sharing (except some special cases) so inpractice if the interrupt handler is called then theinterrupt almost for sure came from its device. Still the interrupthandler must poll the device registers and make surethat the interrupt was generated by its device. If not it should justreturn.

Page 153: 139920579 Versao Traduzida de Book

The old convention for the ISA drivers was getting the device unitnumber as an argument. It is obsolete, and the newdrivers receive whatever argument was specified for them in the attachroutine when callingbus_setup_intr(). .By the new convention it should be the pointer to the structure softc.So the interrupt handler commonly starts as:static void static voidxxx_intr(struct xxx_softc *sc){ {It runs at the interrupt priority level specified by the interrupt typeparameter ofbus_setup_intr(). . That means Isso significathat all the other interrupts of the same type as well as all thesoftware interrupts are disabled./140/ /140/------------------------------------------------------------------------*Page 149* *Página 149*

/Chapter 19./ /Capítulo 19./ /ISA device drivers/To avoid races it is commonly written as a loop:while(xxx_interrupt_pending(sc)) {xxx_process_interrupt(sc);xxx_acknowledge_interrupt(sc);} }The interrupt handler has to acknowledge interrupt to the device onlybut not to the interrupt controller, the systemtakes care of the latter./141/ /141/------------------------------------------------------------------------*Page 150* *Página 150*

*Chapter 20. PCI Devices*This chapter will talk about the FreeBSD mechanisms for writing a devicedriver for a device on a PCI bus.*20.1. Probe and Attach*Information here about how the PCI bus code iterates through theunattached devices and see if a newly loaded kldwill attach to any of them./* / ** Simple KLD to play with the PCI functions.* ** Murray Stokely*/ * /#define MIN(a,b) (((a) < (b)) ? (a) : (b))#include < sys/types.h >#include < sys/module.h >#include < sys/systm.h > /* uprintf */#include < sys/errno.h >#include < sys/param.h > /* defines used in kernel.h */#include < sys/kernel.h > /* types used in module initialization */#include < sys/conf.h >/* cdevsw struct */#include < sys/uio.h >/* uio struct */#include < sys/malloc.h >#include < sys/bus.h > /* structs, prototypes for pci bus stuff */#include < pci/pcivar.h > /* For get_pci macros! */ * /

Page 154: 139920579 Versao Traduzida de Book

/* Function prototypes */d_open_tmypci_open;d_close_tmypci_close;d_read_tmypci_read;d_write_tmypci_write;/* Character device entry points */static struct cdevsw mypci_cdevsw = {mypci_open,mypci_close,mypci_read,/142/ /142/------------------------------------------------------------------------*Page 151* *Página 151*

/Chapter 20. PCI Devices/mypci_write,noioctl,nopoll,nommap,nostrategy,"mypci",36, 36,/* reserved for lkms - /usr/src/sys/conf/majors */nodump,nopsize,D_TTY,-1 -1}; };/* vars */static dev_t sdev;/* We're more interested in probe/attach than withopen/close/read/write at this point */int intmypci_open(dev_t dev, int oflags, int devtype, struct proc *p){ {int err = 0;uprintf("Opened device \"mypci\" successfully.\n");return(err);} }int intmypci_close(dev_t dev, int fflag, int devtype, struct proc *p){ {int err=0;uprintf("Closing device \"mypci.\"\n");return(err);} }int intmypci_read(dev_t dev, struct uio *uio, int ioflag){ {int err = 0;uprintf("mypci read!\n");return err;} }/143/ /143/------------------------------------------------------------------------*Page 152* *Página 152*

Page 155: 139920579 Versao Traduzida de Book

/Chapter 20. PCI Devices/int intmypci_write(dev_t dev, struct uio *uio, int ioflag){ {int err = 0;uprintf("mypci write!\n");return(err);} }/* PCI Support Functions *//* / ** Return identification string if this is device is ours.*/ * /static int static intmypci_probe(device_t dev){ {uprintf("MyPCI Probe\n""Vendor ID : 0x%x\n""Device ID : 0x%x\n",pci_get_vendor(dev),pci_get_device(dev));if (pci_get_vendor(dev) == 0x11c1) {uprintf("We've got the Winmodem, probe successful!\n");return 0; retornar 0;} }return ENXIO;} }/* Attach function is only called if the probe is successful */static int static intmypci_attach(device_t dev){ {uprintf("MyPCI Attach for : deviceID : 0x%x\n",pci_get_vendor(dev));sdev = make_dev(& &mypci_cdevsw,0, 0,UID_ROOT,GID_WHEEL,0600,"mypci");uprintf("Mypci device loaded.\n");return ENXIO;} }/144/ /144/------------------------------------------------------------------------*Page 153* *Página 153*

/Chapter 20./ /PCI Devices/ /PCI Devices//* Detach device. */ * /static int static intmypci_detach(device_t dev){ {uprintf("Mypci detach!\n");return 0; retornar 0;} }/* Called during system shutdown after sync. */ * /static int static intmypci_shutdown(device_t dev){ {uprintf("Mypci shutdown!\n");return 0; retornar 0;} }

Page 156: 139920579 Versao Traduzida de Book

/* / ** Device suspend routine.*/ * /static int static intmypci_suspend(device_t dev){ {uprintf("Mypci suspend!\n");return 0; retornar 0;} }/* / ** Device resume routine.*/ * /static int static intmypci_resume(device_t dev){ {uprintf("Mypci resume!\n");return 0; retornar 0;} }static device_method_t mypci_methods[] = {/* Device interface */DEVMETHOD(device_probe, mypci_probe),DEVMETHOD(device_attach, mypci_attach),DEVMETHOD(device_detach, mypci_detach),/145/ /145/------------------------------------------------------------------------*Page 154* *Página 154*

/Chapter 20./ /PCI Devices/ /PCI Devices/DEVMETHOD(device_shutdown, mypci_shutdown),DEVMETHOD(device_suspend, mypci_suspend),DEVMETHOD(device_resume, mypci_resume),{ 0, 0 }}; };static driver_t mypci_driver = {"mypci",mypci_methods,0, 0,/* sizeof(struct mypci_softc), */}; };static devclass_t mypci_devclass;DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);Additional Resources Recursos adicionais• •PCI Special Interest Group (http://www.pcisig.org)• •PCI System Architecture, Fourth Edition by Tom Shanley, et al.*20.2. Bus Resources*FreeBSD provides an object-oriented mechanism for requesting resourcesfrom a parent bus. Almost all devices willbe a child member of some sort of bus (PCI, ISA, USB, SCSI, etc) andthese devices need to acquire resources fromtheir parent bus (such as memory segments, interrupt lines, or DMAchannels).*20.2.1. Base Address Registers*To do anything particularly useful with a PCI device you will need toobtain the /Base Address Registers/ (BARs) fromthe PCI Configuration space. The PCI-specific details of obtaining theBAR is abstracted in thebus_alloc_resource()function. função.

Page 157: 139920579 Versao Traduzida de Book

For example, a typical driver might have something similar to this in theattach() attach ()function. função. : :sc->bar0id = 0x10;/146/ /146/------------------------------------------------------------------------*Page 155* *Página 155*

/Chapter 20./ /PCI Devices/ /PCI Devices/sc->bar0res = bus_alloc_resource(dev, SYS_RES_MEMORY, &(sc->bar0id),0,0, 1, RF_ACTIVE);if (sc->bar0res == NULL) {uprintf("Memory allocation of PCI base register 0 failed!\n");error = ENXIO;goto fail1;} }sc->bar1id = 0x14;sc->bar1res = bus_alloc_resource(dev, SYS_RES_MEMORY, &(sc->bar1id),0,0, 1, RF_ACTIVE);if (sc->bar1res == NULL) {uprintf("Memory allocation of PCI base register 1 failed!\n");error = ENXIO;goto fail2;} }sc->bar0_bt = rman_get_bustag(sc->bar0res);sc->bar0_bh = rman_get_bushandle(sc->bar0res);sc->bar1_bt = rman_get_bustag(sc->bar1res);sc->bar1_bh = rman_get_bushandle(sc->bar1res);Handles for each base address register are kept in the softc structureso that they can be used to write to the devicelater. mais tarde.These handles can then be used to read or write from the deviceregisters with thebus_space_*functions. For Paraexample, a driver might contain a shorthand function to read from aboard specific register like this :uint16_tboard_read(struct ni_softc *sc, uint16_t address) {return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);} }Similarly, one could write to the registers with :void invalidarboard_write(struct ni_softc *sc, uint16_t address, uint16_t value) {bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);} }These functions exist in 8bit, 16bit, and 32bit versions and you should usebus_space_{read|write}_{1|2|4}accordingly. em conformidade./147/ /147/------------------------------------------------------------------------*Page 156* *Página 156*

/Chapter 20./ /PCI Devices/ /PCI Devices/*20.2.2.* *Interrupts* *Interrupções*Interrupts are allocated from the object-oriented bus code in a waysimilar to the memory resources. First an IRQresource must be allocated from the parent bus, and then the interrupthandler must be setup to deal with this IRQ.Again, a sample from a device

Page 158: 139920579 Versao Traduzida de Book

attach() attach ()function says more than words./* Get the IRQ resource */sc->irqid = 0x0;sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &(sc->irqid),0,0, 1, RF_SHAREABLE | RF_ACTIVE);if (sc->irqres == NULL) {uprintf("IRQ allocation failed!\n");error = ENXIO;goto fail3;} }/* Now we should setup the interrupt handler */error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_MISC,my_handler, sc, &(sc->handler));if (error) {printf("Couldn't set up irq\n");goto fail4;} }sc->irq_bt = rman_get_bustag(sc->irqres);sc->irq_bh = rman_get_bushandle(sc->irqres);*20.2.3.* *DMA* *DMA*On the PC, peripherals that want to do bus-mastering DMA must deal withphysical addresses. This is a problemsince FreeBSD uses virtual memory and deals almost exclusively withvirtual addresses. Fortunately, there is afunction, função,vtophys()to help. para ajudar.#include < vm/vm.h >#include < vm/pmap.h >#define vtophys(virtual_address) (...)The solution is a bit different on the alpha however, and what we reallywant is a function calledvtobus(). .#if defined(__alpha__)/148/ /148/------------------------------------------------------------------------*Page 157* *Página 157*

/Chapter 20./ /PCI Devices/ /PCI Devices/#define vtobus(va)alpha_XXX_dmamap((vm_offset_t)va)#else # Else#define vtobus(va)vtophys(va)#endif # Endif*20.2.4. Deallocating Resources*It's very important to deallocate all of the resources that wereallocated duringattach() attach (). . Care must be taken todeallocate the correct stuff even on a failure condition so that thesystem will remain useable while your driver dies./149/ /149/------------------------------------------------------------------------*Page 158* *Página 158*

*Chapter 21.* *Capítulo 21.* *Common Access Method SCSI**Controllers*

Page 159: 139920579 Versao Traduzida de Book

/This chapter was written by Sergey Babkin <//[email protected]//> Modifications for the handbook made by//Murray Stokely <//[email protected]//>./ />./*21.1.* *Synopsis* *Sinopse*This document assumes that the reader has a general understanding ofdevice drivers in FreeBSD and of the SCSIprotocol. protocolo. Much of the information in this document wasextracted from the drivers :• •ncr (/sys/pci/ncr.c) by Wolfgang Stanglmeier and Stefan Esser• •sym (/sys/pci/sym.c) by Gerard Roudier• •aic7xxx (/sys/dev/aic7xxx/aic7xxx.c) by Justin T. Gibbsand from the CAM code itself (by Justing T. Gibbs, see/sys/cam/*). ). When some solution looked the most logicaland was essentially verbatim extracted from the code by Justin Gibbs, Imarked it as "recommended".The document is illustrated with examples in pseudo-code. Althoughsometimes the examples have many details andlook like real code, it's still pseudo-code. It was written todemonstrate the concepts in an understandable way. For a Para umreal driver other approaches may be more modular and efficient. It alsoabstracts from the hardware details, as well asissues that would cloud the demonstrated concepts or that are supposedto be described in the other chapters of thedevelopers handbook. Such details are commonly shown as calls tofunctions with descriptive names, comments orpseudo-statements. Fortunately real life full-size examples with all thedetails can be found in the real drivers.*21.2.* *21.2.* *General architecture*CAM stands for Common Access Method. It's a generic way to address theI/O buses in a SCSI-like way. This Esteallows a separation of the generic device drivers from the driverscontrolling the I/O bus: for example the disk driverbecomes able to control disks on both SCSI, IDE, and/or any other bus sothe disk driver portion does not have to berewritten (or copied and modified) for every new I/O bus. Thus the twomost important active entities are:• •/Peripheral Modules/ - a driver for peripheral devices (disk, tape,CDROM, etc.)• •/SCSI Interface Modules/ (SIM) - a Host Bus Adapter drivers forconnecting to an I/O bus such as SCSI or IDE./150/ /150/------------------------------------------------------------------------*Page 159* *Página 159*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/

Page 160: 139920579 Versao Traduzida de Book

A peripheral driver receives requests from the OS, converts them to asequence of SCSI commands and passes theseSCSI commands to a SCSI Interface Module. The SCSI Interface Module isresponsible for passing these commandsto the actual hardware (or if the actual hardware is not SCSI but, forexample, IDE then also converting the SCSIcommands to the native commands of the hardware).Because we are interested in writing a SCSI adapter driver here, fromthis point on we will consider everything fromthe SIM standpoint.A typical SIM driver needs to include the following CAM-related headerfiles:#include < cam/cam.h >#include < cam/cam_ccb.h >#include < cam/cam_sim.h >#include < cam/cam_xpt_sim.h >#include < cam/cam_debug.h >#include < cam/scsi/scsi_all.h >The first thing each SIM driver must do is register itself with the CAMsubsystem. This is done during the driver’sxxx_attach()function (here and further xxx_ is used to denote the unique driver nameprefix). The Oxxx_attach()function itself is called by the system bus auto-configuration codewhich we don't describe here.This is achieved in multiple steps: first it's necessary to allocate thequeue of requests associated with this SIM:struct cam_devq *devq;if(( devq = cam_simq_alloc(SIZE) )==NULL) {error; /* some code to handle the error */} }Here SIZE is the size of the queue to be allocated, maximal number ofrequests it could contain. It's the number ofrequests that the SIM driver can handle in parallel on one SCSI card.Commonly it can be calculated as:SIZE = NUMBER_OF_SUPPORTED_TARGETS * MAX_SIMULTANEOUS_COMMANDS_PER_TARGETNext we create a descriptor of our SIM:struct cam_sim *sim;if(( sim = cam_sim_alloc(action_func, poll_func, driver_name,softc, unit, max_dev_transactions,max_tagged_dev_transactions, devq) )==NULL) {cam_simq_free(devq);error; /* some code to handle the error */} }/151/ /151/------------------------------------------------------------------------*Page 160* *Página 160*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/Note that if we are not able to create a SIM descriptor we free the devqalso because we can do nothing else with itand we want to conserve memory.If a SCSI card has multiple SCSI buses on it then each bus requires itsown cam_sim structure.An interesting question is what to do if a SCSI card has more than oneSCSI bus, do we need one devq structure percard or per SCSI bus? The answer given in the comments to the CAM codeis: either way, as the driver's authorprefers.

Page 161: 139920579 Versao Traduzida de Book

The arguments are :• •action_func- pointer to the driver’sxxx_actionfunction. função.static void *xxx_action* ( /struct cam_sim *sim/ , /union ccb *ccb/ );• •poll_func- pointer to the driver’sxxx_poll()static void *xxx_poll* ( /struct cam_sim *sim/ );• •driver_name - the name of the actual driver, such as "ncr" or "wds"• •softc - pointer to the driver's internal descriptor for this SCSI card.This pointer will be used by the driver in futureto get private data.• •unit - the controller unit number, for example for controller "wds0"this number will be 0• •max_dev_transactions - maximal number of simultaneous transactions perSCSI target in the non-tagged mode.This value will be almost universally equal to 1, with possibleexceptions only for the non-SCSI cards. Also the Além disso, odrivers that hope to take advantage by preparing one transaction whileanother one is executed may set it to 2 butthis does not seem to be worth the complexity.• •max_tagged_dev_transactions - the same thing, but in the tagged mode.Tags are the SCSI way to initiate multipletransactions on a device: each transaction is assigned a unique tag andthe transaction is sent to the device. When Quandothe device completes some transaction it sends back the result togetherwith the tag so that the SCSI adapter (andthe driver) can tell which transaction was completed. This argument isalso known as the maximal tag depth. It Eledepends on the abilities of the SCSI adapter.Finally we register the SCSI buses associated with our SCSI adapter:if(xpt_bus_register(sim, bus_number) != CAM_SUCCESS) {cam_sim_free(sim, /*free_devq*/ TRUE);error; /* some code to handle the error *//152/ /152/------------------------------------------------------------------------*Page 161* *Página 161*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/} }If there is one devq structure per SCSI bus (ie we consider a card withmultiple buses as multiple cards with one buseach) then the bus number will always be 0, otherwise each bus on theSCSI card should be get a distinct number.Each bus needs its own separate structure cam_sim.After that our controller is completely hooked to the CAM system. Thevalue of devq can be discarded now: sim willbe passed as an argument in all further calls from CAM and devq can bederived from it.CAM provides the framework for such asynchronous events. Some eventsoriginate from the lower levels (the SIM

Page 162: 139920579 Versao Traduzida de Book

drivers), some events originate from the peripheral drivers, some eventsoriginate from the CAM subsystem itself.Any driver can register callbacks for some types of the asynchronousevents, so that it would be notified if theseevents occur. os eventos ocorrem.A typical example of such an event is a device reset. Each transactionand event identifies the devices to which itapplies by the means of "path". The target-specific events normallyoccur during a transaction with this device. So Assimthe path from that transaction may be re-used to report this event (thisis safe because the event path is copied in theevent reporting routine but not deallocated nor passed anywherefurther). Also it's safe to allocate paths dynamicallyat any time including the interrupt routines, although that incurscertain overhead, and a possible problem with thisapproach is that there may be no free memory at that time. For a busreset event we need to define a wildcard pathincluding all devices on the bus. So we can create the path for thefuture bus reset events in advance and avoidproblems with the future memory shortage:struct cam_path *path;if(xpt_create_path(&path, /*periph*/NULL,cam_sim_path(sim), CAM_TARGET_WILDCARD,CAM_LUN_WILDCARD) != CAM_REQ_CMP) {xpt_bus_deregister(cam_sim_path(sim));cam_sim_free(sim, /*free_devq*/TRUE);error; /* some code to handle the error */} }softc->wpath = path;softc->sim = sim;As you can see the path includes:• •ID of the peripheral driver (NULL here because we have none)• •ID of the SIM driver (cam_sim_path(sim)) )• •SCSI target number of the device (CAM_TARGET_WILDCARD means "all devices")• •SCSI LUN number of the subdevice (CAM_LUN_WILDCARD means "all LUNs")/153/ /153/------------------------------------------------------------------------*Page 162* *Página 162*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/If the driver can't allocate this path it won't be able to worknormally, so in that case we dismantle that SCSI bus.And we save the path pointer in the softc structure for future use.After that we save the value of sim (or we can alsodiscard it on the exit fromxxx_probe()if we wish).That's all for a minimalistic initialization. To do things right thereis one more issue left.For a SIM driver there is one particularly interesting event: when atarget device is considered lost. In this case Neste casoresetting the SCSI negotiations with this device may be a good idea. Sowe register a callback for this event withCAM. The request is passed to CAM by requesting CAM action on a CAM

Page 163: 139920579 Versao Traduzida de Book

control block for this type of request:struct ccb_setasync csa;xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);csa.ccb_h.func_code = XPT_SASYNC_CB;csa.event_enable = AC_LOST_DEVICE;csa.callback = xxx_async;csa.callback_arg = sim;xpt_action((union ccb *)&csa);Now we take a look at thexxx_action()and exxx_poll()driver entry points.static void *xxx_action* ( /struct cam_sim *sim/ , /union ccb *ccb/ );Do some action on request of the CAM subsystem. Sim describes the SIMfor the request, CCB is the request itself.CCB stands for "CAM Control Block". It is a union of many specificinstances, each describing arguments for sometype of transactions. All of these instances share the CCB header wherethe common part of arguments is stored.CAM supports the SCSI controllers working in both initiator ("normal")mode and target (simulating a SCSI device)mode. modo. Here we only consider the part relevant to the initiator mode.There are a few function and macros (in other words, methods) defined toaccess the public data in the struct sim:• •cam_sim_path(sim)- the path ID (see above)• •cam_sim_name(sim)- the name of the sim• •cam_sim_softc(sim)- the pointer to the softc (driver private data) structure• •cam_sim_unit(sim)- the unit number• •cam_sim_bus(sim)- the bus IDTo identify the device,xxx_action()can get the unit number and pointer to its structure softc using thesefunctions./154/ /154/------------------------------------------------------------------------*Page 163* *Página 163*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/The type of request is stored in /ccb-/ > /ccb_h.func_code/ . So generallyxxx_action()consists of a big switch:struct xxx_softc *softc = (struct xxx_softc *) cam_sim_softc(sim);struct ccb_hdr *ccb_h = &ccb->ccb_h;int unit = cam_sim_unit(sim);int bus = cam_sim_bus(sim);switch(ccb_h->func_code) {case ...:... ...default: default:

Page 164: 139920579 Versao Traduzida de Book

ccb_h->status = CAM_REQ_INVALID;xpt_done(ccb);break; quebrar;} }As can be seen from the default case (if an unknown command wasreceived) the return code of the command is setinto /ccb-/ > /ccb_h.status/ and the completed CCB is returned back toCAM by callingxpt_done(ccb). .xpt_done()does not have to be called fromxxx_action(): For example an I/O request may be enqueued insidethe SIM driver and/or its SCSI controller. Then when the device wouldpost an interrupt signaling that the processingof this request is completexpt_done()may be called from the interrupt handling routine.Actually, the CCB status is not only assigned as a return code but a CCBhas some status all the time. Before CCB ispassed to thexxx_action()routine it gets the status CCB_REQ_INPROG meaning that it's in progress.There are Tema surprising number of status values defined in/sys/cam/cam.hwhich should be able to represent the status of arequest in great detail. More interesting yet, the status is in fact a"bitwise or" of an enumerated status value (thelower 6 bits) and possible additional flag-like bits (the upper bits).The enumerated values will be discussed later inmore detail. The summary of them can be found in the Errors Summarysection. The possible status flags are:• •/CAM_DEV_QFRZN/ - if the SIM driver gets a serious error (for example,the device does not respond to theselection or breaks the SCSI protocol) when processing a CCB it shouldfreeze the request queue by callingxpt_freeze_simq(), return the other enqueued but not processed yet CCBs for this deviceback to the CAMqueue, then set this flag for the troublesome CCB and callxpt_done(). . This flag causes the CAM subsystem tounfreeze the queue after it handles the error.• •/CAM_AUTOSNS_VALID/ - if the device returned an error condition and theflag CAM_DIS_AUTOSENSE is notset in CCB the SIM driver must execute the REQUEST SENSE commandautomatically to extract the sense(extended error information) data from the device. If this attempt wassuccessful the sense data should be saved inthe CCB and this flag set.• •/CAM_RELEASE_SIMQ/ - like CAM_DEV_QFRZN but used in case there is someproblem (or resource shortage)with the SCSI controller itself. Then all the future requests to thecontroller should be stopped by/155/ /155/

Page 165: 139920579 Versao Traduzida de Book

------------------------------------------------------------------------*Page 164* *Página 164*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/xpt_freeze_simq(). . The controller queue will be restarted after the SIM driverovercomes the shortage andinforms CAM by returning some CCB with this flag set.• •/CAM_SIM_QUEUED/ - when SIM puts a CCB into its request queue this flagshould be set (and removed whenthis CCB gets dequeued before being returned back to CAM). This flag isnot used anywhere in the CAM codenow, so its purpose is purely diagnostic.The function A funçãoxxx_action()is not allowed to sleep, so all the synchronization for resource accessmust be doneusing SIM or device queue freezing. Besides the aforementioned flags theCAM subsystem provides functionsxpt_selease_simq()and expt_release_devq()to unfreeze the queues directly, without passing a CCB toCAM.The CCB header contains the following fields:• •/path/ - path ID for the request• •/target_id/ - target device ID for the request• •/target_lun/ - LUN ID of the target device• •/timeout/ - timeout interval for this command, in milliseconds• •/timeout_ch/ - a convenience place for the SIM driver to store thetimeout handle (the CAM subsystem itself doesnot make any assumptions about it)• •/flags/ - various bits of information about the request spriv_ptr0,spriv_ptr1 - fields reserved for private use by theSIM driver (such as linking to the SIM queues or SIM private controlblocks); actually, they exist as unions:spriv_ptr0 and spriv_ptr1 have the type (void *), spriv_field0 andspriv_field1 have the type unsigned long,sim_priv.entries[0].bytes and sim_priv.entries[1].bytes are byte arraysof the size consistent with the otherincarnations of the union and sim_priv.bytes is one array, twice bigger.The recommended way of using the SIM private fields of CCB is to definesome meaningful names for them and usethese meaningful names in the driver, like:#define ccb_some_meaningful_namesim_priv.entries[0].bytes#define ccb_hcb spriv_ptr1 /* for hardware control block */The most common initiator mode requests are:• •/XPT_SCSI_IO/ - execute an I/O transactionThe instance "struct ccb_scsiio csio" of the union ccb is used totransfer the arguments. They are:• •

Page 166: 139920579 Versao Traduzida de Book

/cdb_io/ - pointer to the SCSI command buffer or the buffer itself• •/cdb_len/ - SCSI command length• •/data_ptr/ - pointer to the data buffer (gets a bit complicated ifscatter/gather is used)/156/ /156/------------------------------------------------------------------------*Page 165* *Página 165*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/• •/dxfer_len/ - length of the data to transfer• •/sglist_cnt/ - counter of the scatter/gather segments• •/scsi_status/ - place to return the SCSI status• •/sense_data/ - buffer for the SCSI sense information if the commandreturns an error (the SIM driver is supposedto run the REQUEST SENSE command automatically in this case if the CCBflag CAM_DIS_AUTOSENSE isnot set)• •/sense_len/ - the length of that buffer (if it happens to be higher thansize of sense_data the SIM driver mustsilently assume the smaller value) resid, sense_resid - if the transferof data or SCSI sense returned an errorthese are the returned counters of the residual (not transferred) data.They do not seem to be especiallymeaningful, so in a case when they are difficult to compute (say,counting bytes in the SCSI controller's FIFObuffer) an approximate value will do as well. For a successfullycompleted transfer they must be set to zero.• •/tag_action/ - the kind of tag to use:• •CAM_TAG_ACTION_NONE - don't use tags for this transaction• •MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG, MSG_ORDERED_Q_TAG - value equal to theappropriate tag message (see /sys/cam/scsi/scsi_message.h); this givesonly the tag type, the SIM driver mustassign the tag value itselfThe general logic of handling this request is the following:The first thing to do is to check for possible races, to make sure thatthe command did not get aborted when it wassitting in the queue:struct ccb_scsiio *csio = &ccb->csio;if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {xpt_done(ccb);return; voltar;} }Also we check that the device is supported at all by our controller:if(ccb_h->target_id > OUR_MAX_SUPPORTED_TARGET_ID|| cch_h->target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {ccb_h->status = CAM_TID_INVALID;xpt_done(ccb);return; voltar;} }if(ccb_h->target_lun > OUR_MAX_SUPPORTED_LUN) {

Page 167: 139920579 Versao Traduzida de Book

ccb_h->status = CAM_LUN_INVALID;xpt_done(ccb);return; voltar;} }/157/ /157/------------------------------------------------------------------------*Page 166* *Página 166*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/Then allocate whatever data structures (such as card-dependent hardwarecontrol block) we need to process thisrequest. pedido. If we can't then freeze the SIM queue and remember thatwe have a pending operation, return the CCBback and ask CAM to re-queue it. Later when the resources becomeavailable the SIM queue must be unfrozen byreturning a ccb with the CAM_SIMQ_RELEASE bit set in its status.Otherwise, if all went well, link the CCBwith the hardware control block (HCB) and mark it as queued.struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);if(hcb == NULL) {softc->flags |= RESOURCE_SHORTAGE;xpt_freeze_simq(sim, /*count*/1);ccb_h->status = CAM_REQUEUE_REQ;xpt_done(ccb);return; voltar;} }hcb->ccb = ccb; ccb_h->ccb_hcb = (void *)hcb;ccb_h->status |= CAM_SIM_QUEUED;Extract the target data from CCB into the hardware control block. Checkif we are asked to assign a tag and if yesthen generate an unique tag and build the SCSI tag messages. The SIMdriver is also responsible for negotiationswith the devices to set the maximal mutually supported bus width,synchronous rate and offset.hcb->target = ccb_h->target_id; hcb->lun = ccb_h->target_lun;generate_identify_message(hcb);if( ccb_h->tag_action != CAM_TAG_ACTION_NONE )generate_unique_tag_message(hcb, ccb_h->tag_action);if( !target_negotiated(hcb) )generate_negotiation_messages(hcb);Then set up the SCSI command. The command storage may be specified inthe CCB in many interesting ways,specified by the CCB flags. The command buffer can be contained in CCBor pointed to, in the latter case thepointer may be physical or virtual. Since the hardware commonly needsphysical address we always convert theaddress to the physical one.A NOT-QUITE RELATED NOTE: Normally this is done by a call to vtophys(),but for the PCI device (whichaccount for most of the SCSI controllers now) drivers' portability tothe Alpha architecture the conversion must bedone by vtobus() instead due to special Alpha quirks. [IMHO it would bemuch better to have two separatefunctions, vtop() and ptobus() then vtobus() would be a simplesuperposition of them.] In case if a physicaladdress is requested it's OK to return the CCB with the statusCAM_REQ_INVALID, the current drivers do that.But it's also possible to compile the Alpha-specific piece of code, asin this example (there should be a more directway to do that, without conditional compilation in the drivers). If

Page 168: 139920579 Versao Traduzida de Book

necessary a physical address can be alsoconverted or mapped back to a virtual address but with big pain, so wedon't do that.if(ccb_h->flags & CAM_CDB_POINTER) {/* CDB is a pointer *//158/ /158/------------------------------------------------------------------------*Page 167* *Página 167*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/if(!(ccb_h->flags & CAM_CDB_PHYS)) {/* CDB pointer is virtual */hcb->cmd = vtobus(csio->cdb_io.cdb_ptr);} else { } Else {/* CDB pointer is physical */#if defined(__alpha__)hcb->cmd = csio->cdb_io.cdb_ptr | alpha_XXX_dmamap_or ;#else # Elsehcb->cmd = csio->cdb_io.cdb_ptr ;#endif # Endif} }} else { } Else {/* CDB is in the ccb (buffer) */hcb->cmd = vtobus(csio->cdb_io.cdb_bytes);} }hcb->cmdlen = csio->cdb_len;Now it's time to set up the data. Again, the data storage may bespecified in the CCB in many interesting ways,specified by the CCB flags. First we get the direction of the datatransfer. The simplest case is if there is no data totransfer:int dir = (ccb_h->flags & CAM_DIR_MASK);if (dir == CAM_DIR_NONE)goto end_data;Then we check if the data is in one chunk or in a scatter-gather list,and the addresses are physical or virtual. The OSCSI controller may be able to handle only a limited number of chunks oflimited length. If the request hits thislimitation we return an error. We use a special function to return theCCB to handle in one place the HCB resourceshortages. The functions to add chunks are driver-dependent, and here weleave them without detailedimplementation. implementação. See description of the SCSI command (CDB)handling for the details on the address-translationissues. questões. If some variation is too difficult or impossible toimplement with a particular card it's OK to return thestatus CAM_REQ_INVALID. Actually, it seems like the scatter-gatherability is not used anywhere in the CAMcode now. But at least the case for a single non-scattered virtualbuffer must be implemented, it's actively used byCAM.int rv;initialize_hcb_for_data(hcb);if((!(ccb_h->flags & CAM_SCATTER_VALID)) {/* single buffer */if(!(ccb_h->flags & CAM_DATA_PHYS)) {rv = add_virtual_chunk(hcb, csio->data_ptr, csio->dxfer_len, dir);} }} else { } Else {/159/ /159/

Page 169: 139920579 Versao Traduzida de Book

------------------------------------------------------------------------*Page 168* *Página 168*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/rv = add_physical_chunk(hcb, csio->data_ptr, csio->dxfer_len, dir);} }} else { } Else {int i; int i;struct bus_dma_segment *segs;segs = (struct bus_dma_segment *)csio->data_ptr;if ((ccb_h->flags & CAM_SG_LIST_PHYS) != 0) {/* The SG list pointer is physical */rv = setup_hcb_for_physical_sg_list(hcb, segs, csio->sglist_cnt);} else if (!(ccb_h->flags & CAM_DATA_PHYS)) {/* SG buffer pointers are virtual */for (i = 0; i < csio->sglist_cnt; i++) {rv = add_virtual_chunk(hcb, segs[i].ds_addr,segs[i].ds_len, dir);if (rv != CAM_REQ_CMP)break; quebrar;} }} else { } Else {/* SG buffer pointers are physical */for (i = 0; i < csio->sglist_cnt; i++) {rv = add_physical_chunk(hcb, segs[i].ds_addr,segs[i].ds_len, dir);if (rv != CAM_REQ_CMP)break; quebrar;} }} }} }if(rv != CAM_REQ_CMP) {/* we expect that add_*_chunk() functions return CAM_REQ_CMP* if they added a chunk successfully, CAM_REQ_TOO_BIG if* the request is too big (too many bytes or too many chunks),* CAM_REQ_INVALID in case of other troubles*/ * /free_hcb_and_ccb_done(hcb, ccb, rv);return; voltar;} }end_data:If disconnection is disabled for this CCB we pass this information tothe hcb:if(ccb_h->flags & CAM_DIS_DISCONNECT)hcb_disable_disconnect(hcb);/160/ /160/------------------------------------------------------------------------*Page 169* *Página 169*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/If the controller is able to run REQUEST SENSE command all by itselfthen the value of the flagCAM_DIS_AUTOSENSE should also be passed to it, to prevent automaticREQUEST SENSE if the CAMsubsystem does not want it.The only thing left is to set up the timeout, pass our hcb to thehardware and return, the rest will be done by theinterrupt handler (or timeout handler).ccb_h->timeout_ch = timeout(xxx_timeout, (caddr_t) hcb,(ccb_h->timeout * hz) / 1000); /* convert milliseconds to ticks */

Page 170: 139920579 Versao Traduzida de Book

put_hcb_into_hardware_queue(hcb);return; voltar;And here is a possible implementation of the function returning CCB:static void static voidfree_hcb_and_ccb_done(struct xxx_hcb *hcb, union ccb *ccb, u_int32_tstatus){ {struct xxx_softc *softc = hcb->softc;ccb->ccb_h.ccb_hcb = 0;if(hcb != NULL) {untimeout(xxx_timeout, (caddr_t) hcb, ccb->ccb_h.timeout_ch);/* we're about to free a hcb, so the shortage has ended */if(softc->flags & RESOURCE_SHORTAGE) {softc->flags &=RESOURCE_SHORTAGE;status |= CAM_RELEASE_SIMQ;} }free_hcb(hcb); /* also removes hcb from any internal lists */} }ccb->ccb_h.status = status |(ccb->ccb_h.status &(CAM_STATUS_MASK|CAM_SIM_QUEUED));xpt_done(ccb);} }• •/XPT_RESET_DEV/ - send the SCSI "BUS DEVICE RESET" message to a deviceThere is no data transferred in CCB except the header and the mostinteresting argument of it is target_id.Depending on the controller hardware a hardware control block just likefor the XPT_SCSI_IO request may beconstructed (see XPT_SCSI_IO request description) and sent to thecontroller or the SCSI controller may beimmediately programmed to send this RESET message to the device or thisrequest may be just not supported (andreturn the status CAM_REQ_INVALID). Also on completion of the requestall the disconnected transactions forthis target must be aborted (probably in the interrupt routine).Also all the current negotiations for the target are lost on reset, sothey might be cleaned too. Or they clearing maybe deferred, because anyway the target would request re-negotiation onthe next transaction./161/ /161/------------------------------------------------------------------------*Page 170* *Página 170*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/• •/XPT_RESET_BUS/ - send the RESET signal to the SCSI busNo arguments are passed in the CCB, the only interesting argument is theSCSI bus indicated by the struct simpointer. ponteiro.A minimalistic implementation would forget the SCSI negotiations for allthe devices on the bus and return thestatus CAM_REQ_CMP.The proper implementation would in addition actually reset the SCSI bus(possible also reset the SCSI controller)and mark all the CCBs being processed, both those in the hardware queueand those being disconnected, as donewith the status CAM_SCSI_BUS_RESET. Like: Como:int targ, lun;struct xxx_hcb *h, *hh;struct ccb_trans_settings neg;

Page 171: 139920579 Versao Traduzida de Book

struct cam_path *path;/* The SCSI bus reset may take a long time, in this case its completion* should be checked by interrupt or timeout. But for simplicity* we assume here that it's really fast.*/ * /reset_scsi_bus(softc);/* drop all enqueued CCBs */for(h = softc->first_queued_hcb; h != NULL; h = hh) {hh = h->next;free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);} }/* the clean values of negotiations to report */neg.bus_width = 8;neg.sync_period = neg.sync_offset = 0;neg.valid = (CCB_TRANS_BUS_WIDTH_VALID| CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);/* drop all disconnected CCBs and clean negotiations */for(targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {clean_negotiations(softc, targ);/* report the event if possible */if(xpt_create_path(&path, /*periph*/NULL,cam_sim_path(sim), targ,CAM_LUN_WILDCARD) == CAM_REQ_CMP) {xpt_async(AC_TRANSFER_NEG, path, &neg);xpt_free_path(path);/162/ /162/------------------------------------------------------------------------*Page 171* *Página 171*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/} }for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)for(h = softc->first_discon_hcb[targ][lun]; h != NULL; h = hh) {hh=h->next;free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);} }} }ccb->ccb_h.status = CAM_REQ_CMP;xpt_done(ccb);/* report the event */xpt_async(AC_BUS_RESET, softc->wpath, NULL);return; voltar;Implementing the SCSI bus reset as a function may be a good idea becauseit would be re-used by the timeoutfunction as a last resort if the things go wrong.• •/XPT_ABORT/ - abort the specified CCBThe arguments are transferred in the instance "struct ccb_abort cab" ofthe union ccb. The only argument field in itis: é:/abort_ccb/ - pointer to the CCB to be abortedIf the abort is not supported just return the status CAM_UA_ABORT. Thisis also the easy way to minimallyimplement this call, return CAM_UA_ABORT in any case.The hard way is to implement this request honestly. First check thatabort applies to a SCSI transaction:struct ccb *abort_ccb;abort_ccb = ccb->cab.abort_ccb;if(abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {ccb->ccb_h.status = CAM_UA_ABORT;

Page 172: 139920579 Versao Traduzida de Book

xpt_done(ccb);return; voltar;} }Then it's necessary to find this CCB in our queue. This can be done bywalking the list of all our hardware controlblocks in search for one associated with this CCB:struct xxx_hcb *hcb, *h;hcb = NULL;/163/ /163/------------------------------------------------------------------------*Page 172* *Página 172*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers//* We assume that softc->first_hcb is the head of the list of all* HCBs associated with this bus, including those enqueued for* processing, being processed by hardware and disconnected ones.*/ * /for(h = softc->first_hcb; h != NULL; h = h->next) {if(h->ccb == abort_ccb) {hcb = h;break; quebrar;} }} }if(hcb == NULL) {/* no such CCB in our queue */ccb->ccb_h.status = CAM_PATH_INVALID;xpt_done(ccb);return; voltar;} }hcb=found_hcb;Now we look at the current processing status of the HCB. It may beeither sitting in the queue waiting to be sent tothe SCSI bus, being transferred right now, or disconnected and waitingfor the result of the command, or actuallycompleted by hardware but not yet marked as done by software. To makesure that we don't get in any races withhardware we mark the HCB as being aborted, so that if this HCB is aboutto be sent to the SCSI bus the SCSIcontroller will see this flag and skip it.int hstatus;/* shown as a function, in case special action is needed to make* this flag visible to hardware*/ * /set_hcb_flags(hcb, HCB_BEING_ABORTED);abort_again:hstatus = get_hcb_status(hcb);switch(hstatus) {case HCB_SITTING_IN_QUEUE:remove_hcb_from_hardware_queue(hcb);/* FALLTHROUGH */case HCB_COMPLETED:/* this is an easy case */free_hcb_and_ccb_done(hcb, abort_ccb, CAM_REQ_ABORTED);break; quebrar;/164/ /164/------------------------------------------------------------------------*Page 173* *Página 173*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/If the CCB is being transferred right now we would like to signal to the

Page 173: 139920579 Versao Traduzida de Book

SCSI controller in somehardware-dependent way that we want to abort the current transfer. TheSCSI controller would set the SCSIATTENTION signal and when the target responds to it send an ABORTmessage. We also reset the timeout tomake sure that the target is not sleeping forever. If the command wouldnot get aborted in some reasonable timelike 10 seconds the timeout routine would go ahead and reset the wholeSCSI bus. Because the command will beaborted in some reasonable time we can just return the abort request nowas successfully completed, and mark theaborted CCB as aborted (but not mark it as done yet).case HCB_BEING_TRANSFERRED:untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);abort_ccb->ccb_h.timeout_ch =timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);abort_ccb->ccb_h.status = CAM_REQ_ABORTED;/* ask the controller to abort that HCB, then generate* an interrupt and stop*/ * /if(signal_hardware_to_abort_hcb_and_stop(hcb) < 0) {/* oops, we missed the race with hardware, this transaction* got off the bus before we aborted it, try again */goto abort_again;} }break; quebrar;If the CCB is in the list of disconnected then set it up as an abortrequest and re-queue it at the front of hardwarequeue. fila. Reset the timeout and report the abort request to becompleted.case HCB_DISCONNECTED:untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);abort_ccb->ccb_h.timeout_ch =timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);put_abort_message_into_hcb(hcb);put_hcb_at_the_front_of_hardware_queue(hcb);break; quebrar;} }ccb->ccb_h.status = CAM_REQ_CMP;xpt_done(ccb);return; voltar;That's all for the ABORT request, although there is one more issue.Because the ABORT message cleans all theongoing transactions on a LUN we have to mark all the other activetransactions on this LUN as aborted. That Queshould be done in the interrupt routine, after the transaction getsaborted.Implementing the CCB abort as a function may be quite a good idea, thisfunction can be re-used if an I/Otransaction times out. The only difference would be that the timed outtransaction would return the statusCAM_CMD_TIMEOUT for the timed out request. Then the case XPT_ABORT wouldbe small, like that:/165/ /165/------------------------------------------------------------------------*Page 174* *Página 174*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/case XPT_ABORT:struct ccb *abort_ccb;

Page 174: 139920579 Versao Traduzida de Book

abort_ccb = ccb->cab.abort_ccb;if(abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {ccb->ccb_h.status = CAM_UA_ABORT;xpt_done(ccb);return; voltar;} }if(xxx_abort_ccb(abort_ccb, CAM_REQ_ABORTED) < 0)/* no such CCB in our queue */ccb->ccb_h.status = CAM_PATH_INVALID;else outroccb->ccb_h.status = CAM_REQ_CMP;xpt_done(ccb);return; voltar;• •/XPT_SET_TRAN_SETTINGS/ - explicitly set values of SCSI transfer settingsThe arguments are transferred in the instance "struct ccb_trans_settingcts" of the union ccb:• •/valid/ - a bitmask showing which settings should be updated:• •/CCB_TRANS_SYNC_RATE_VALID/ - synchronous transfer rate• •/CCB_TRANS_SYNC_OFFSET_VALID/ - synchronous offset• •/CCB_TRANS_BUS_WIDTH_VALID/ - bus width• •/CCB_TRANS_DISC_VALID/ - set enable/disable disconnection• •/CCB_TRANS_TQ_VALID/ - set enable/disable tagged queuing• •/flags/ - consists of two parts, binary arguments and identification ofsub-operations. The binary arguments are :• •/CCB_TRANS_DISC_ENB/ - enable disconnection• •/CCB_TRANS_TAG_ENB/ - enable tagged queuing• •the sub-operations are:• •/CCB_TRANS_CURRENT_SETTINGS/ - change the current negotiations• •/CCB_TRANS_USER_SETTINGS/ - remember the desired user valuessync_period, sync_offset -self-explanatory, if sync_offset==0 then the asynchronous mode isrequested bus_width - bus width, in bits(not bytes)/166/ /166/------------------------------------------------------------------------*Page 175* *Página 175*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/Two sets of negotiated parameters are supported, the user settings andthe current settings. The user settings arenot really used much in the SIM drivers, this is mostly just a piece ofmemory where the upper levels can store(and later recall) its ideas about the parameters. Setting the userparameters does not cause re-negotiation of thetransfer rates. But when the SCSI controller does a negotiation it mustnever set the values higher than the userparameters, so it's essentially the top boundary.

Page 175: 139920579 Versao Traduzida de Book

The current settings are, as the name says, current. Changing them meansthat the parameters must bere-negotiated on the next transfer. Again, these "new current settings"are not supposed to be forced on the device,just they are used as the initial step of negotiations. Also they mustbe limited by actual capabilities of the SCSIcontroller: for example, if the SCSI controller has 8-bit bus and therequest asks to set 16-bit wide transfers thisparameter must be silently truncated to 8-bit transfers before sendingit to the device.One caveat is that the bus width and synchronous parameters are pertarget while the disconnection and tagenabling parameters are per lun.The recommended implementation is to keep 3 sets of negotiated (buswidth and synchronous transfer) parameters:• •/user/ - the user set, as above• •/current/ - those actually in effect• •/goal/ - those requested by setting of the "current" parametersThe code looks like:struct ccb_trans_settings *cts;int targ, lun;int flags;cts = &ccb->cts;targ = ccb_h->target_id;lun = ccb_h->target_lun;flags = cts->flags;if(flags & CCB_TRANS_USER_SETTINGS) {if(flags & CCB_TRANS_SYNC_RATE_VALID)softc->user_sync_period[targ] = cts->sync_period;if(flags & CCB_TRANS_SYNC_OFFSET_VALID)softc->user_sync_offset[targ] = cts->sync_offset;if(flags & CCB_TRANS_BUS_WIDTH_VALID)softc->user_bus_width[targ] = cts->bus_width;if(flags & CCB_TRANS_DISC_VALID) {softc->user_tflags[targ][lun] &=CCB_TRANS_DISC_ENB;softc->user_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;} }if(flags & CCB_TRANS_TQ_VALID) {softc->user_tflags[targ][lun] &=CCB_TRANS_TQ_ENB;/167/ /167/------------------------------------------------------------------------*Page 176* *Página 176*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/softc->user_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;} }} }if(flags & CCB_TRANS_CURRENT_SETTINGS) {if(flags & CCB_TRANS_SYNC_RATE_VALID)softc->goal_sync_period[targ] =max(cts->sync_period, OUR_MIN_SUPPORTED_PERIOD);if(flags & CCB_TRANS_SYNC_OFFSET_VALID)softc->goal_sync_offset[targ] =min(cts->sync_offset, OUR_MAX_SUPPORTED_OFFSET);if(flags & CCB_TRANS_BUS_WIDTH_VALID)softc->goal_bus_width[targ] = min(cts->bus_width, OUR_BUS_WIDTH);if(flags & CCB_TRANS_DISC_VALID) {

Page 176: 139920579 Versao Traduzida de Book

softc->current_tflags[targ][lun] &=CCB_TRANS_DISC_ENB;softc->current_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;} }if(flags & CCB_TRANS_TQ_VALID) {softc->current_tflags[targ][lun] &=CCB_TRANS_TQ_ENB;softc->current_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;} }} }ccb->ccb_h.status = CAM_REQ_CMP;xpt_done(ccb);return; voltar;Then when the next I/O request will be processed it will check if it hasto re-negotiate, for example by calling thefunction target_negotiated(hcb). It can be implemented like this:int inttarget_negotiated(struct xxx_hcb *hcb){ {struct softc *softc = hcb->softc;int targ = hcb->targ;if( softc->current_sync_period[targ] != softc->goal_sync_period[targ]|| softc->current_sync_offset[targ] != softc->goal_sync_offset[targ]|| softc->current_bus_width[targ] != softc->goal_bus_width[targ] )return 0; /* FALSE */else outroreturn 1; /* TRUE */} }After the values are re-negotiated the resulting values must be assignedto both current and goal parameters, so forfuture I/O transactions the current and goal parameters would be thesame andtarget_negotiated()would seriareturn TRUE. When the card is initialized (inxxx_attach()) the current negotiation values must be initialized to/168/ /168/------------------------------------------------------------------------*Page 177* *Página 177*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/narrow asynchronous mode, the goal and current values must beinitialized to the maximal values supported bycontroller. controlador.• •/XPT_GET_TRAN_SETTINGS/ - get values of SCSI transfer settingsThis operations is the reverse of XPT_SET_TRAN_SETTINGS. Fill up the CCBinstance "structccb_trans_setting cts" with data as requested by the flagsCCB_TRANS_CURRENT_SETTINGS orCCB_TRANS_USER_SETTINGS (if both are set then the existing driversreturn the current settings). Set all thebits in the valid field.• •/XPT_CALC_GEOMETRY/ - calculate logical (BIOS) geometry of the diskThe arguments are transferred in the instance "struct ccb_calc_geometryccg" of the union ccb:• •/block_size/ - input, block (AKA sector) size in bytes• •/volume_size/ - input, volume size in bytes

Page 177: 139920579 Versao Traduzida de Book

• •/cylinders/ - output, logical cylinders• •/heads/ - output, logical heads• •/secs_per_track/ - output, logical sectors per trackIf the returned geometry differs much enough from what the SCSIcontroller BIOS thinks and a disk on this SCSIcontroller is used as bootable the system may not be able to boot. Thetypical calculation example taken from theaic7xxx driver is:struct structccb_calc_geometry *ccg;u_int32_t size_mb;u_int32_t secs_per_cylinder;int intextended;ccg = &ccb->ccg;size_mb = ccg->volume_size/ ((1024L * 1024L) / ccg->block_size);extended = check_cards_EEPROM_for_extended_geometry(softc);if (size_mb > 1024 && extended) {ccg->heads = 255;ccg->secs_per_track = 63;} else { } Else {ccg->heads = 64;ccg->secs_per_track = 32;} }/169/ /169/------------------------------------------------------------------------*Page 178* *Página 178*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/secs_per_cylinder = ccg->heads * ccg->secs_per_track;ccg->cylinders = ccg->volume_size / secs_per_cylinder;ccb->ccb_h.status = CAM_REQ_CMP;xpt_done(ccb);return; voltar;This gives the general idea, the exact calculation depends on the quirksof the particular BIOS. If BIOS providesno way set the "extended translation" flag in EEPROM this flag shouldnormally be assumed equal to 1. Other Outropopular geometries are:128 heads, 63 sectors - Symbios controllers16 heads, 63 sectors - old controllersSome system BIOSes and SCSI BIOSes fight with each other with variablesuccess, for example a combination ofSymbios 875/895 SCSI and Phoenix BIOS can give geometry 128/63 afterpower up and 255/63 after a hard resetor soft reboot.• •/XPT_PATH_INQ/ - path inquiry, in other words get the SIM driver andSCSI controller (also known as HBA - HostBus Adapter) propertiesThe properties are returned in the instance "struct ccb_pathinq cpi" ofthe union ccb:• •version_num - the SIM driver version number, now all drivers use 1• •hba_inquiry - bitmask of features supported by the controller:

Page 178: 139920579 Versao Traduzida de Book

• •PI_MDP_ABLE - supports MDP message (something from SCSI3?)• •PI_WIDE_32 - supports 32 bit wide SCSI• •PI_WIDE_16 - supports 16 bit wide SCSI• •PI_SDTR_ABLE - can negotiate synchronous transfer rate• •PI_LINKED_CDB - supports linked commands• •PI_TAG_ABLE - supports tagged commands• •PI_SOFT_RST - supports soft reset alternative (hard reset and soft resetare mutually exclusive within a SCSIbus)• •target_sprt - flags for target mode support, 0 if unsupported• •hba_misc - miscellaneous controller features:• •PIM_SCANHILO - bus scans from high ID to low ID• •PIM_NOREMOVE - removable devices not included in scan• •PIM_NOINITIATOR - initiator role not supported/170/ /170/------------------------------------------------------------------------*Page 179* *Página 179*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/• •PIM_NOBUSRESET - user has disabled initial BUS RESET• •hba_eng_cnt - mysterious HBA engine count, something related tocompression, now is always set to 0• •vuhba_flags - vendor-unique flags, unused now• •max_target - maximal supported target ID (7 for 8-bit bus, 15 for 16-bitbus, 127 for Fibre Channel)• •max_lun - maximal supported LUN ID (7 for older SCSI controllers, 63 fornewer ones)• •async_flags - bitmask of installed Async handler, unused now• •hpath_id - highest Path ID in the subsystem, unused now• •unit_number - the controller unit number, cam_sim_unit(sim)• •bus_id - the bus number, cam_sim_bus(sim)• •initiator_id - the SCSI ID of the controller itself• •base_transfer_speed - nominal transfer speed in KB/s for asynchronousnarrow transfers, equals to 3300 forSCSI SCSI• •sim_vid - SIM driver's vendor id, a zero-terminated string of maximal

Page 179: 139920579 Versao Traduzida de Book

length SIM_IDLEN including theterminating zero• •hba_vid - SCSI controller's vendor id, a zero-terminated string ofmaximal length HBA_IDLEN including theterminating zero• •dev_name - device driver name, a zero-terminated string of maximallength DEV_IDLEN including theterminating zero, equal to cam_sim_name(sim)The recommended way of setting the string fields is using strncpy, like:strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);After setting the values set the status to CAM_REQ_CMP and mark the CCBas done.*21.3.* *Polling* *Votação*static void *xxx_poll* ( /struct cam_sim *sim/ );The poll function is used to simulate the interrupts when the interruptsubsystem is not functioning (for example,when the system has crashed and is creating the system dump). The CAMsubsystem sets the proper interrupt levelbefore calling the poll routine. So all it needs to do is to call theinterrupt routine (or the other way around, the poll/171/ /171/------------------------------------------------------------------------*Page 180* *Página 180*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/routine may be doing the real action and the interrupt routine wouldjust call the poll routine). Why bother about aseparate function then ? Because of different calling conventions. The Oxxx_pollroutine gets the struct cam_simpointer as its argument when the PCI interrupt routine by commonconvention gets pointer to the struct xxx_softcand the ISA interrupt routine gets just the the device unit number. Sothe poll routine would normally look as:static void static voidxxx_poll(struct cam_sim *sim){ {xxx_intr((struct xxx_softc *)cam_sim_softc(sim)); /* for PCI device */} }or oustatic void static voidxxx_poll(struct cam_sim *sim){ {xxx_intr(cam_sim_unit(sim)); /* for ISA device */} }*21.4. Asynchronous Events*If an asynchronous event callback has been set up then the callbackfunction should be defined.static void static voidahc_async(void *callback_arg, u_int32_t code, struct cam_path *path,void *arg)• •callback_arg - the value supplied when registering the callback• •code - identifies the type of event• •path - identifies the devices to which the event applies• •

Page 180: 139920579 Versao Traduzida de Book

arg - event-specific argumentImplementation for a single type of event, AC_LOST_DEVICE, looks like:struct xxx_softc *softc;struct cam_sim *sim;int targ;struct ccb_trans_settings neg;sim = (struct cam_sim *)callback_arg;softc = (struct xxx_softc *)cam_sim_softc(sim);/172/ /172/------------------------------------------------------------------------*Page 181* *Página 181*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/switch (code) {case AC_LOST_DEVICE:targ = xpt_path_target_id(path);if(targ <= OUR_MAX_SUPPORTED_TARGET) {clean_negotiations(softc, targ);/* send indication to CAM */neg.bus_width = 8;neg.sync_period = neg.sync_offset = 0;neg.valid = (CCB_TRANS_BUS_WIDTH_VALID| CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);xpt_async(AC_TRANSFER_NEG, path, &neg);} }break; quebrar;default: default:break; quebrar;} }*21.5.* *Interrupts* *Interrupções*The exact type of the interrupt routine depends on the type of theperipheral bus (PCI, ISA and so on) to which theSCSI controller is connected.The interrupt routines of the SIM drivers run at the interrupt levelsplcam. So Assimsplcam()should be used in the driverto synchronize activity between the interrupt routine and the rest ofthe driver (for a multiprocessor-aware driverthings get yet more interesting but we ignore this case here). Thepseudo-code in this document happily ignores theproblems of synchronization. The real code must not ignore them. Asimple-minded approach is to setsplcam()on emthe entry to the other routines and reset it on return thus protectingthem by one big critical section. To make sure thatthe interrupt level will be always restored a wrapper function can bedefined, like:static void static voidxxx_action(struct cam_sim *sim, union ccb *ccb){ {int s;s = splcam();xxx_action1(sim, ccb);splx(s);} }static void static voidxxx_action1(struct cam_sim *sim, union ccb *ccb){ {

Page 181: 139920579 Versao Traduzida de Book

... ... process the request .../173/ /173/------------------------------------------------------------------------*Page 182* *Página 182*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/} }This approach is simple and robust but the problem with it is thatinterrupts may get blocked for a relatively longtime and this would negatively affect the system's performance. On theother hand the functions of thespl()family famíliahave rather high overhead, so vast amount of tiny critical sections maynot be good either.The conditions handled by the interrupt routine and the details dependvery much on the hardware. We consider the Consideramos oset of "typical" conditions.First, we check if a SCSI reset was encountered on the bus (probablycaused by another SCSI controller on the sameSCSI bus). If so we drop all the enqueued and disconnected requests,report the events and re-initialize our SCSIcontroller. controlador. It is important that during this initializationthe controller won't issue another reset or else two controllerson the same SCSI bus could ping-pong resets forever. The case of fatalcontroller error/hang could be handled in thesame place, but it will probably need also sending RESET signal to theSCSI bus to reset the status of theconnections with the SCSI devices.int fatal=0;struct ccb_trans_settings neg;struct cam_path *path;if( detected_scsi_reset(softc)|| (fatal = detected_fatal_controller_error(softc)) ) {int targ, lun;struct xxx_hcb *h, *hh;/* drop all enqueued CCBs */for(h = softc->first_queued_hcb; h != NULL; h = hh) {hh = h->next;free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);} }/* the clean values of negotiations to report */neg.bus_width = 8;neg.sync_period = neg.sync_offset = 0;neg.valid = (CCB_TRANS_BUS_WIDTH_VALID| CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);/* drop all disconnected CCBs and clean negotiations */for(targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {clean_negotiations(softc, targ);/* report the event if possible */if(xpt_create_path(&path, /*periph*/NULL,cam_sim_path(sim), targ,CAM_LUN_WILDCARD) == CAM_REQ_CMP) {/174/ /174/------------------------------------------------------------------------*Page 183* *Página 183*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/xpt_async(AC_TRANSFER_NEG, path, &neg);xpt_free_path(path);

Page 182: 139920579 Versao Traduzida de Book

} }for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)for(h = softc->first_discon_hcb[targ][lun]; h != NULL; h = hh) {hh=h->next;if(fatal)free_hcb_and_ccb_done(h, h->ccb, CAM_UNREC_HBA_ERROR);else outrofree_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);} }} }/* report the event */xpt_async(AC_BUS_RESET, softc->wpath, NULL);/* re-initialization may take a lot of time, in such case* its completion should be signaled by another interrupt or* checked on timeout - but for simplicity we assume here that* it's really fast*/ * /if(!fatal) {reinitialize_controller_without_scsi_reset(softc);} else { } Else {reinitialize_controller_with_scsi_reset(softc);} }schedule_next_hcb(softc);return; voltar;} }If interrupt is not caused by a controller-wide condition then probablysomething has happened to the currenthardware control block. Depending on the hardware there may be othernon-HCB-related events, we just do notconsider them here. Then we analyze what happened to this HCB:struct xxx_hcb *hcb, *h, *hh;int hcb_status, scsi_status;int ccb_status;int targ;int lun_to_freeze;hcb = get_current_hcb(softc);if(hcb == NULL) {/* either stray interrupt or something went very wrong* or this is something hardware-dependent/175/ /175/------------------------------------------------------------------------*Page 184* *Página 184*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/*/ * /handle as necessary;return; voltar;} }targ = hcb->target;hcb_status = get_status_of_current_hcb(softc);First we check if the HCB has completed and if so we check the returnedSCSI status.if(hcb_status == COMPLETED) {scsi_status = get_completion_status(hcb);Then look if this status is related to the REQUEST SENSE command and ifso handle it in a simple way.if(hcb->flags & DOING_AUTOSENSE) {if(scsi_status == GOOD) { /* autosense was successful */hcb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID;free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);

Page 183: 139920579 Versao Traduzida de Book

} else { } Else {autosense_failed:free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_AUTOSENSE_FAIL);} }schedule_next_hcb(softc);return; voltar;} }Else the command itself has completed, pay more attention to details. Ifauto-sense is not disabled for this CCB andthe command has failed with sense data then run REQUEST SENSE command toreceive that data.hcb->ccb->csio.scsi_status = scsi_status;calculate_residue(hcb);if( (hcb->ccb->ccb_h.flags & CAM_DIS_AUTOSENSE)==0&& ( scsi_status == CHECK_CONDITION|| scsi_status == COMMAND_TERMINATED) ) {/* start auto-SENSE */hcb->flags |= DOING_AUTOSENSE;setup_autosense_command_in_hcb(hcb);restart_current_hcb(softc);return; voltar;} }if(scsi_status == GOOD)free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_REQ_CMP);else outro/176/ /176/------------------------------------------------------------------------*Page 185* *Página 185*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);schedule_next_hcb(softc);return; voltar;} }One typical thing would be negotiation events: negotiation messagesreceived from a SCSI target (in answer to ournegotiation attempt or by target's initiative) or the target is unableto negotiate (rejects our negotiation messages ordoes not answer them).switch(hcb_status) {case TARGET_REJECTED_WIDE_NEG:/* revert to 8-bit bus */softc->current_bus_width[targ] = softc->goal_bus_width[targ] = 8;/* report the event */neg.bus_width = 8;neg.valid = CCB_TRANS_BUS_WIDTH_VALID;xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);continue_current_hcb(softc);return; voltar;case TARGET_ANSWERED_WIDE_NEG:{ {int wd;wd = get_target_bus_width_request(softc);if(wd <= softc->goal_bus_width[targ]) {/* answer is acceptable */softc->current_bus_width[targ] =softc->goal_bus_width[targ] = neg.bus_width = wd;/* report the event */neg.valid = CCB_TRANS_BUS_WIDTH_VALID;xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);

Page 184: 139920579 Versao Traduzida de Book

} else { } Else {prepare_reject_message(hcb);} }} }continue_current_hcb(softc);return; voltar;case TARGET_REQUESTED_WIDE_NEG:{ {int wd;wd = get_target_bus_width_request(softc);wd = min (wd, OUR_BUS_WIDTH);wd = min (wd, softc->user_bus_width[targ]);/177/ /177/------------------------------------------------------------------------*Page 186* *Página 186*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/if(wd != softc->current_bus_width[targ]) {/* the bus width has changed */softc->current_bus_width[targ] =softc->goal_bus_width[targ] = neg.bus_width = wd;/* report the event */neg.valid = CCB_TRANS_BUS_WIDTH_VALID;xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);} }prepare_width_nego_rsponse(hcb, wd);} }continue_current_hcb(softc);return; voltar;} }Then we handle any errors that could have happened during auto-sense inthe same simple-minded way as before.Otherwise we look closer at the details again.if(hcb->flags & DOING_AUTOSENSE)goto autosense_failed;switch(hcb_status) {The next event we consider is unexpected disconnect. Which is considerednormal after an ABORT or BUS DEVICERESET message and abnormal in other cases.case UNEXPECTED_DISCONNECT:if(requested_abort(hcb)) {/* abort affects all commands on that target+LUN, so* mark all disconnected HCBs on that target+LUN as aborted too*/ * /for(h = softc->first_discon_hcb[hcb->target][hcb->lun];h != NULL; h = hh) {hh=h->next;free_hcb_and_ccb_done(h, h->ccb, CAM_REQ_ABORTED);} }ccb_status = CAM_REQ_ABORTED;} else if(requested_bus_device_reset(hcb)) {int lun;/* reset affects all commands on that target, so* mark all disconnected HCBs on that target+LUN as reset*/ * //178/ /178/------------------------------------------------------------------------*Page 187* *Página 187*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/

Page 185: 139920579 Versao Traduzida de Book

for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)for(h = softc->first_discon_hcb[hcb->target][lun];h != NULL; h = hh) {hh=h->next;free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);} }/* send event */xpt_async(AC_SENT_BDR, hcb->ccb->ccb_h.path_id, NULL);/* this was the CAM_RESET_DEV request itself, it's completed */ccb_status = CAM_REQ_CMP;} else { } Else {calculate_residue(hcb);ccb_status = CAM_UNEXP_BUSFREE;/* request the further code to freeze the queue */hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;lun_to_freeze = hcb->lun;} }break; quebrar;If the target refuses to accept tags we notify CAM about that and returnback all commands for this LUN:case TAGS_REJECTED:/* report the event */neg.flags = 0 &CCB_TRANS_TAG_ENB;neg.valid = CCB_TRANS_TQ_VALID;xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);ccb_status = CAM_MSG_REJECT_REC;/* request the further code to freeze the queue */hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;lun_to_freeze = hcb->lun;break; quebrar;Then we check a number of other conditions, with processing basicallylimited to setting the CCB status:case SELECTION_TIMEOUT:ccb_status = CAM_SEL_TIMEOUT;/* request the further code to freeze the queue */hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;lun_to_freeze = CAM_LUN_WILDCARD;break; quebrar;case PARITY_ERROR:ccb_status = CAM_UNCOR_PARITY;/179/ /179/------------------------------------------------------------------------*Page 188* *Página 188*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/break; quebrar;case DATA_OVERRUN:case ODD_WIDE_TRANSFER:ccb_status = CAM_DATA_RUN_ERR;break; quebrar;default: default:/* all other errors are handled in a generic way */ccb_status = CAM_REQ_CMP_ERR;/* request the further code to freeze the queue */hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;lun_to_freeze = CAM_LUN_WILDCARD;break; quebrar;} }Then we check if the error was serious enough to freeze the input queueuntil it gets proceeded and do so if it is:

Page 186: 139920579 Versao Traduzida de Book

if(hcb->ccb->ccb_h.status & CAM_DEV_QFRZN) {/* freeze the queue */xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);/* re-queue all commands for this target/LUN back to CAM */for(h = softc->first_queued_hcb; h != NULL; h = hh) {hh = h->next;if(targ == h->targ&& (lun_to_freeze == CAM_LUN_WILDCARD || lun_to_freeze == h->lun) )free_hcb_and_ccb_done(h, h->ccb, CAM_REQUEUE_REQ);} }} }free_hcb_and_ccb_done(hcb, hcb->ccb, ccb_status);schedule_next_hcb(softc);return; voltar;This concludes the generic interrupt handling although specificcontrollers may require some additions.*21.6. Errors Summary*When executing an I/O request many things may go wrong. The reason oferror can be reported in the CCB statuswith great detail. Examples of use are spread throughout this document.For completeness here is the summary ofrecommended responses for the typical error conditions:/180/ /180/------------------------------------------------------------------------*Page 189* *Página 189*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/• •/CAM_RESRC_UNAVAIL/ - some resource is temporarily unavailable and theSIM driver can not generate an eventwhen it will become available. An example of this resource would be someintra-controller hardware resource forwhich the controller does not generate an interrupt when it becomesavailable.• •/CAM_UNCOR_PARITY/ - unrecovered parity error occurred• •/CAM_DATA_RUN_ERR/ - data overrun or unexpected data phase (going inother direction than specified inCAM_DIR_MASK) or odd transfer length for wide transfer• •/CAM_SEL_TIMEOUT/ - selection timeout occurred (target does not respond)• •/CAM_CMD_TIMEOUT/ - command timeout occurred (the timeout function ran)• •/CAM_SCSI_STATUS_ERROR/ - the device returned error• •/CAM_AUTOSENSE_FAIL/ - the device returned error and the REQUEST SENSECOMMAND failed• •/CAM_MSG_REJECT_REC/ - MESSAGE REJECT message was received• •/CAM_SCSI_BUS_RESET/ - received SCSI bus reset• •/CAM_REQ_CMP_ERR/ - "impossible" SCSI phase occurred or something elseas weird or just a generic error iffurther detail is not available• •/CAM_UNEXP_BUSFREE/ - unexpected disconnect occurred• •

Page 187: 139920579 Versao Traduzida de Book

/CAM_BDR_SENT/ - BUS DEVICE RESET message was sent to the target• •/CAM_UNREC_HBA_ERROR/ - unrecoverable Host Bus Adapter Error• •/CAM_REQ_TOO_BIG/ - the request was too large for this controller• •/CAM_REQUEUE_REQ/ - this request should be re-queued to preservetransaction ordering. This typically occurswhen the SIM recognizes an error that should freeze the queue and mustplace other queued requests for the targetat the sim level back into the XPT queue. Typical cases of such errorsare selection timeouts, command timeoutsand other like conditions. In such cases the troublesome command returnsthe status indicating the error, the andthe other commands which have not be sent to the bus yet get re-queued.• •/CAM_LUN_INVALID/ - the LUN ID in the request is not supported by theSCSI controller• •/CAM_TID_INVALID/ - the target ID in the request is not supported by theSCSI controller*21.7. Timeout Handling*When the timeout for an HCB expires that request should be aborted, justlike with an XPT_ABORT request. The Oonly difference is that the returned status of aborted request should beCAM_CMD_TIMEOUT instead ofCAM_REQ_ABORTED (that's why implementation of the abort better be doneas a function). But there is one morepossible problem: what if the abort request itself will get stuck? Inthis case the SCSI bus should be reset, just likewith an XPT_RESET_BUS request (and the idea about implementing it as afunction called from both places applies/181/ /181/------------------------------------------------------------------------*Page 190* *Página 190*

/Chapter 21./ /Capítulo 21./ /Common Access Method SCSI Controllers/here too). Also we should reset the whole SCSI bus if a device resetrequest got stuck. So after all the timeoutfunction would look like:static void static voidxxx_timeout(void *arg){ {struct xxx_hcb *hcb = (struct xxx_hcb *)arg;struct xxx_softc *softc;struct ccb_hdr *ccb_h;softc = hcb->softc;ccb_h = &hcb->ccb->ccb_h;if(hcb->flags & HCB_BEING_ABORTED|| ccb_h->func_code == XPT_RESET_DEV) {xxx_reset_bus(softc);} else { } Else {xxx_abort_ccb(hcb->ccb, CAM_CMD_TIMEOUT);} }} }When we abort a request all the other disconnected requests to the sametarget/LUN get aborted too. So there appearsa question, should we return them with status CAM_REQ_ABORTED orCAM_CMD_TIMEOUT ? The current A actualdrivers use CAM_CMD_TIMEOUT. This seems logical because if one request

Page 188: 139920579 Versao Traduzida de Book

got timed out then probablysomething really bad is happening to the device, so if they would not bedisturbed they would time out by themselves./182/ /182/------------------------------------------------------------------------*Page 191* *Page 191*

*Chapter 22.* *Capítulo 22.* *USB Devices* *Dispositivos USB*/This chapter was written by Nick Hibma <//[email protected]//>./ />./ /Modifications made for the handbook by//Murray Stokely <//[email protected]//>./ />./*22.1.* *Introduction* *Introdução*The Universal Serial Bus (USB) is a new way of attaching devices topersonal computers. The bus architecturefeatures two-way communication and has been developed as a response todevices becoming smarter and requiringmore interaction with the host. USB support is included in all currentPC chipsets and is therefore available in allrecently built PCs. Apple's introduction of the USB-only iMac has been amajor incentive for hardwaremanufacturers to produce USB versions of their devices. The future PCspecifications specify that all legacyconnectors on PCs should be replaced by one or more USB connectors,providing generic plug and play capabilities.Support for USB hardware was available at a very early stage in NetBSDand was developed by Lennart Augustssonfor the NetBSD project. The code has been ported to FreeBSD and we arecurrently maintaining a shared code base.For the implementation of the USB subsystem a number of features of USBare important./Lennart Augustsson has done most of the implementation of the USBsupport for the NetBSD project./ /Many thanks/ /Muito obrigado//for this incredible amount of work. Many thanks also to Ardy and Dirkfor their comments and proofreading of this//paper./ /papel./• •Devices connect to ports on the computer directly or on devices calledhubs, forming a treelike device structure.• •The devices can be connected and disconnected at run time.• •Devices can suspend themselves and trigger resumes of the host system• •As the devices can be powered from the bus, the host software has tokeep track of power budgets for each hub.• •Different quality of service requirements by the different device typestogether with the maximum of 126 devicesthat can be connected to the same bus, require proper scheduling oftransfers on the shared bus to take fulladvantage of the 12Mbps bandwidth available. (over 400Mbps with USB 2.0)• •Devices are intelligent and contain easily accessible information aboutthemselvesThe development of drivers for the USB subsystem and devices connectedto it is supported by the specifications thathave been developed and will be developed. These specifications are

Page 189: 139920579 Versao Traduzida de Book

publicly available from the USB home pages.Apple has been very strong in pushing for standards based drivers, bymaking drivers for the generic classesavailable in their operating system MacOS and discouraging the use ofseparate drivers for each new device. This Estechapter tries to collate essential information for a basic understandingof the present implementation of the USBstack in FreeBSD/NetBSD. It is recommended however to read it togetherwith the relevant specifications mentionedin the references below./183/ /183/------------------------------------------------------------------------*Page 192* *Página 192*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/*22.1.1. Structure of the USB Stack*The USB support in FreeBSD can be split into three layers. The lowestlayer contains the host controller driver,providing a generic interface to the hardware and its schedulingfacilities. It supports initialisation of the hardware,scheduling of transfers and handling of completed and/or failedtransfers. Each host controller driver implements avirtual hub providing hardware independent access to the registerscontrolling the root ports on the back of themachine. máquina.The middle layer handles the device connection and disconnection, basicinitialisation of the device, driver selection,the communication channels (pipes) and does resource management. Thisservices layer also controls the defaultpipes and the device requests transferred over them.The top layer contains the individual drivers supporting specific(classes of) devices. These drivers implement theprotocol that is used over the pipes other than the default pipe. Theyalso implement additional functionality to makethe device available to other parts of the kernel oruserland. They usethe USB driver interface (USBDI) exposed bythe services layer.*22.2. Host Controllers*The host controller (HC) controls the transmission of packets on thebus. Frames of 1 millisecond are used. At the Nostart of each frame the host controller generates a Start of Frame (SOF)packet.The SOF packet is used to synchronise to the start of the frame and tokeep track of the frame number. Within eachframe packets are transferred, either from host to device (out) or fromdevice to host (in). Transfers are alwaysinitiated by the host (polled transfers). Therefore there can only beone host per USB bus. Each transfer of a packethas a status stage in which the recipient of the data can return eitherACK (acknowledge reception), NAK (retry),STALL (error condition) or nothing (garbled data stage, device notavailable or disconnected). Section 8.5 of theUSB specification (http://www.usb.org/developers/docs.html) explains thedetails of packets in more detail. Four Quatrodifferent types of transfers can occur on a USB bus: control, bulk,interrupt and isochronous. The types of transfersand their characteristics are described below ('Pipes' subsection).Large transfers between the device on the USB bus and the device driverare split up into multiple packets by the hostcontroller or the HC driver.

Page 190: 139920579 Versao Traduzida de Book

Device requests (control transfers) to the default endpoints arespecial. They consist of two or three phases: SETUP,DATA (optional) and STATUS. The set-up packet is sent to the device. Ifthere is a data phase, the direction of thedata packet(s) is given in the set-up packet. The direction in thestatus phase is the opposite of the direction duringthe data phase, or IN if there was no data phase. The host controllerhardware also provides registers with the currentstatus of the root ports and the changes that have occurred since thelast reset of the status change register. Access to O acesso aothese registers is provided through a virtualised hub as suggested inthe USB specification [ 2]. Thevirtual hub mustcomply with the hub device class given in chapter 11 of thatspecification. It must provide a default pipe throughwhich device requests can be sent to it. It returns the standard andhubclass specific set of descriptors. It should also/184/ /184/------------------------------------------------------------------------*Page 193* *Página 193*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/provide an interrupt pipe that reports changes happening at its ports.There are currently two specifications for hostcontrollers available: Universal Host Controller Interface(http://developer.intel.com/design/USB/UHCI11D.htm)(UHCI; Intel) and Open Host Controller Interface(http://www.compaq.com/productinfo/development/openhci.html)(OHCI; Compaq, Microsoft, National Semiconductor). The UHCIspecification has been designed to reducehardware complexity byrequiring the host controller driver to supply acomplete schedule of the transfers for eachframe. quadro. OHCI type controllers are much more independent byproviding a more abstract interface doing alot of workthemselves. si.*22.2.1. UHCI*The UHCI host controller maintains a framelist with 1024 pointers to perframe data structures. It understands twodifferent data types: transfer descriptors (TD) and queue heads (QH).Each TD represents a packet to becommunicated to or from a device endpoint. QHs are a means to groupTDs(and QHs) together.Each transfer consists of one or more packets. The UHCI driver splitslarge transfers into multiple packets. For everytransfer, apart from isochronous transfers, a QH is allocated. For everytype of transfer these QHs are collected at aQH for that type. Isochronous transfers have to be executed firstbecause of the fixed latency requirement and aredirectly referred to by the pointer in the framelist. The lastisochronous TD refers to the QH for interrupt transfers forthat frame. All QHs for interrupt transfers point at the QH for controltransfers, which in turn points at the QH forbulk transfers. The following diagram gives a graphical overview of this:This results in the following schedule being run in each frame. Afterfetching the pointer for the current frame fromthe framelist the controller first executes the TDs for all theisochronous packets in that frame. The last of these TDsrefers to the QH for the interrupt transfers for thatframe. The hostcontroller will then descend from that QH to theQHs for the individual interrupt transfers. After finishing that queue,the QH for the interrupt transfers will refer the

Page 191: 139920579 Versao Traduzida de Book

controller to the QH for all control transfers. It will execute all thesubqueues scheduled there, followed by all thetransfers queued at the bulk QH. To facilitate the handling of finishedor failed transfers different types of interruptsare generatedby the hardware at the end of each frame. In the last TDfor a transfer the Interrupt-On Completion bitis set by the HC driver to flag an interrupt when the transfer hascompleted. An error interrupt is flagged if a TDreaches its maximum error count. If the short packet detect bit is setin a TD and less than the set packet length istransferred this interrupt is flagged to notify the controller driver ofthe completed transfer. It is the host controllerdriver's task to find out which transfer has completed or produced anerror. When called the interrupt service routinewill locate all the finished transfers and call their callbacks.See for a more elaborate description the UHCI specification.(http://developer.intel.com/design/USB/UHCI11D.htm)*22.2.2. OHCI*Programming an OHCI host controller is much simpler. The controllerassumes that a set of endpoints is available,and is aware of scheduling priorities and the ordering of the types oftransfers in a frame. The main data structureused by the host controller is the endpoint descriptor (ED) to whichaqueue of transfer descriptors (TDs) is attached./185/ /185/------------------------------------------------------------------------*Page 194* *Página 194*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/The ED contains the maximum packet size allowed for an endpoint and thecontroller hardware does the splittinginto packets. The pointers to the data buffers are updated after eachtransfer and when the start and end pointer areequal, the TD is retired to the done-queue. The four types of endpointshave their own queues. Control and bulkendpoints are queued each at their own queue. Interrupt EDs are queuedin a tree, with the level in the tree definingthe frequency at which they run.framelist interruptisochronous control bulkThe schedule being run by the host controller in each frame looks asfollows. The controller will first run thenon-periodic control and bulk queues, up to a time limit set by the HCdriver. Then the interrupt transfers for thatframe number are run, by using the lower five bits of the frame numberas an index into level 0 of the tree ofinterrupts EDs. At the end of this tree the isochronous EDs areconnected and these are traversed subsequently. The Oisochronous TDs contain the frame number of the first frame the transfershould be run in. After all the periodictransfers have been run, the control and bulk queues are traversedagain. Periodically the interrupt service routine iscalled to process the done queue and call the callbacks for eachtransfer and reschedule interrupt and isochronousendpoints. endpoints.See for a more elaborate description the OHCI specification(http://www.compaq.com/productinfo/development/openhci.html). Serviceslayer The middle layer provides accessto the device in a controlled way and maintains resources inuse by thedifferent drivers and the services layer. The Olayer takes care of the following aspects:

Page 192: 139920579 Versao Traduzida de Book

• •The device configuration information• •The pipes to communicate with a device• •Probing and attaching and detaching form a device.*22.3. USB Device Information**22.3.1. Device configuration information*Each device provides different levels of configuration information. Eachdevice has one or more configurations, ofwhich one is selected during probe/attach. A configuration providespower and bandwidth requirements. Within eachconfiguration there can be multiple interfaces. A device interface is acollection of endpoints. For example USBspeakers can have an interface for the audio data (Audio Class) and aninterface for the knobs, dials and buttons (HIDClass). All interfaces in a configuration areactive at the same time andcan be attached to by different drivers. Each Cadainterface can have alternates, providing different quality of serviceparameters. In for example cameras this is used toprovide different frame sizes and numbers of frames per second./186/ /186/------------------------------------------------------------------------*Page 195* *Página 195*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/Within each interface 0 or more endpoints can be specified. Endpointsare the unidirectional access points forcommunicating with a device. They provide buffers to temporarily storeincoming or outgoing data from the device.Each endpoint has a unique address within a configuration, theendpoint's number plus its direction. The default O padrãoendpoint, endpoint 0, is not part of any interface and available in allconfigurations. It is managed by the serviceslayer and not directly available to device drivers.Level 0 Level 1 Level 2 Slot 0Slot 3 Slot 2 Slot 1(Only 4 out of 32 slots shown)This hierarchical configuration information is described in the deviceby a standard set of descriptors (see section 9.6of the USB specification [ 2]). They can be requested through the GetDescriptor Request. The services layer cachesthese descriptors to avoid unnecessary transferson the USB bus. Accessto the descriptors is provided throughfunction calls. chamadas de função.• •Device descriptors: General information about the device, like Vendor,Product and Revision Id, supported deviceclass, subclass and protocol if applicable, maximum packet size for thedefault endpoint, etc.• •Configuration descriptors: The number of interfaces in thisconfiguration, suspend and resume functionalitysupported and power requirements.• •Interface descriptors: interface class, subclass and protocol ifapplicable, number of alternate settings for theinterface and the number of endpoints.• •Endpoint descriptors: Endpoint address, direction and type, maximum

Page 193: 139920579 Versao Traduzida de Book

packet size supported and polling frequencyif type is interrupt endpoint. There is no descriptor for thedefaultendpoint (endpoint 0) and it is never counted inan interface descriptor.• •String descriptors: In the other descriptors string indices are suppliedfor some fields.These can be used to retrievedescriptive strings, possibly in multiple languages.Class specifications can add their own descriptor types that areavailable through the GetDescriptor Request.Pipes Communication to end points on a device flows through so-calledpipes. Drivers submit transfers to endpointsto a pipe and provide a callback to be called on completion or failureof the transfer (asynchronous transfers) or waitfor completion (synchronous transfer). Transfers to an endpoint areserialised in the pipe. A transfer can eithercomplete, fail or time-out (if a time-out has been set). There are twotypes of time-outs for transfers. Time-outs canhappen due to time-out on the USBbus (milliseconds). These time-outs areseen as failures and can be due todisconnection of the device. A second form of time-out is implemented insoftware and is triggered when a transferdoes not complete within a specified amount of time (seconds). These arecaused by a device acknowledgingnegatively (NAK) the transferred packets. The cause for this is thedevice not being ready to receive data, bufferunder- or overrun or protocol errors.If a transfer over a pipe is larger than the maximum packet sizespecified in the associated endpoint descriptor, thehost controller (OHCI) or the HC driver (UHCI) will split the transferinto packets of maximum packet size, with the/187/ /187/------------------------------------------------------------------------*Page 196* *Página 196*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/last packet possibly smaller than the maximum packetsize.Sometimes it is not a problem for a device to return less data thanrequested. For example abulk-in-transfer to amodem might request 200 bytes of data, but the modem has only 5 bytesavailable at that time. The driver can set theshort packet (SPD) flag. It allows the host controller to accept apacket even if the amount of data transferred is lessthan requested. This flag is only valid for in-transfers, as the amountof data to be sent to a device is always knownbeforehand. antemão. If an unrecoverable error occurs in a device duringa transfer the pipe is stalled. Before any more data isaccepted or sent the driver needs to resolve the cause of the stall andclear the endpoint stall condition through sendthe clear endpoint halt device request over the default pipe. Thedefault endpoint should never stall.There are four different types of endpoints and corresponding pipes: -Control pipe / default pipe: There is one controlpipe per device, connected to the default endpoint (endpoint 0). Thepipe carries the device requests and associateddata. dados. The difference between transfers over the default pipe andother pipes is that the protocol for thetransfers isdescribed in the USB specification [ 2]. These requests are used toreset and configure the device. A basic set ofcommands that must be supported by each device is provided in chapter 9

Page 194: 139920579 Versao Traduzida de Book

of the USB specification [ 2]. The Ocommands supported on this pipe canbe extended by a device classspecification to support additional functionality.• •Bulk pipe: This is the USB equivalent to a raw transmission medium.• •Interrupt pipe: The host sends a request for data to the device and ifthe device has nothing to send, it will NAK thedata packet. Interrupt transfers are scheduled at a frequencyspecifiedwhen creating the pipe.• •Isochronous pipe: These pipes are intended for isochronous data, forexample video oraudio streams, with fixedlatency, but no guaranteed delivery. Some support for pipes of this typeis available in the current implementation.Packets in control, bulk and interrupt transfers are retried if an erroroccurs during transmission or the deviceacknowledges the packet negatively (NAK) due to for example lack ofbuffer space to store the incoming data.Isochronous packets are however not retried in case of failed deliveryor NAK of a packet as this might violate thetiming constraints.The availability of the necessary bandwidth is calculated during thecreation of the pipe. Transfersare scheduledwithin frames of 1 millisecond. The bandwidth allocation within a frameis prescribed by the USB specification,section 5.6 [ 2]. Isochronous and interrupt transfers areallowed toconsume up to 90% of the bandwidth within aframe. quadro. Packets for control and bulk transfers are scheduledafter all isochronous and interrupt packets and willconsume all the remaining bandwidth.More information on scheduling of transfers and bandwidth reclamationcan be found in chapter 5of the USBspecification [ 2], section 1.3 of the UHCI specification [ 3] andsection 3.4.2 of the OHCI specification [4].*22.4. Device probe and attach*After the notification by the hub that a new device has been connected,the service layer switcheson the port,providing the device with 100 mA of current. At this point the device isin its default state and listening to device/188/ /188/------------------------------------------------------------------------*Page 197* *Página 197*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/address 0. The services layer will proceed to retrieve the variousdescriptors through the default pipe. After that itwill send a Set Address request to move the device away from the defaultdevice address (address 0). Multiple devicedrivers might be able to support the device. For example a modem drivermight beable to support an ISDN TAthrough the AT compatibility interface. A driver for that specific modelof the ISDN adapter might however be ableto provide much better support for this device. To support thisflexibility, the probes return priorities indicating theirlevel of support. Support for a specific revision of a product ranks thehighest and the generic driver the lowestpriority. It might also be that multiple drivers could attach to onedevice if there are multiple interfaceswithin oneconfiguration. configuração. Each driver only needs to support a subset

Page 195: 139920579 Versao Traduzida de Book

of the interfaces.The probing for a driver for a newly attached device checks first fordevice specific drivers. If notfound, the probecode iterates over all supported configurations until a driver attachesin a configuration. To support devices withmultiple drivers on different interfaces, the probe iteratesover allinterfaces in a configuration that have not yet beenclaimed by a driver. Configurations that exceed the power budget for thehub are ignored. During attach the drivershould initialise the device to its proper state, but not reset it, asthis will make the device disconnect itself from thebus and restart the probing process for it. To avoid consumingunnecessary bandwidth should not claim the interruptpipe at attach time, but should postpone allocating the pipe until thefile is opened and the data is actually used.When the file is closed the pipe should be closed again, eventhough thedevice might still be attached.*22.4.1. Device disconnect and detach*A device driver should expect to receive errors during any transactionwith the device. The designof USB supportsand encourages the disconnection of devices at any point in time.Drivers should make sure that they do the rightthing when the device disappears.Furthermore a device that has been disconnected and reconnected will notbe reattached at the same device instance.This might change in the future when more devices support serial numbers(see the device descriptor) or other meansof defining an identity for a device have been developed.The disconnection of a device is signalled by a hub in the interruptpacket delivered to the hub driver. The statuschange information indicates which port has seen a connection change.The device detach method for all devicedrivers for the device connected on that port are called and thestructures cleaned up. If the port status indicates thatin the mean time a device has been connected to that port, the procedurefor probing and attaching the device will bestarted. iniciado. A device reset will produce a disconnect-connectsequence on the hub and will be handled as describedabove. acima.*22.5. USB Drivers Protocol Information*The protocol used over pipes other than the default pipe is undefined bythe USB specification. Information on thiscan be found from various sources. The most accurate source is thedeveloper's section on the USB home pages [ 1]./189/ /189/------------------------------------------------------------------------*Page 198* *Página 198*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/From these pages a growing number of deviceclass specifications areavailable. These specifications specify what acompliant device should look like from a driver perspective, basicfunctionality it needs to provide and the protocolthat is to be used over the communication channels. The USBspecification [ 2] includes the description of the HubClass. Classe. A class specification for Human Interface Devices (HID)has been created to cater for keyboards, tablets,bar-code readers, buttons, knobs, switches, etc. A third example is theclass specification for mass storage devices.For a full list of device classes see the developers sectionon the USB

Page 196: 139920579 Versao Traduzida de Book

home pages [ 1].For many devices the protocol information has not yet been publishedhowever. Information on the protocol beingused might be available from the company making the device. Somecompanies will require you to sign a Non-Disclosure Agreement (NDA) before giving you the specifications. Thisin most cases precludes making the driveropen source.Another good source of information is the Linux driver sources, as anumber of companies have started to providedrivers for Linux for their devices. It is always a good idea to contactthe authors of those drivers for their source ofinformation. informação.Example: Human Interface Devices The specification for the HumanInterface Devices like keyboards, mice, tablets,buttons, dials,etc. is referred to in other device class specificationsand is used in many devices.For example audio speakers provide endpoints to the digital to analogueconverters and possibly an extra pipe for amicrophone. microfone. They also provide a HID endpoint in a separateinterface for the buttons and dials on the front of thedevice. dispositivo. The same is true for the monitor control class. Itis straightforward to build support for these interfacesthrough the available kernel and userland libraries together with theHID class driver or the generic driver. Another Outrodevice that serves as an example for interfaces within one configurationdriven by different device drivers is a cheapkeyboard with built-in legacy mouse port. To avoid having the cost ofincluding the hardware for a USB hub in thedevice, manufacturers combined the mouse data received from the PS/2port on the back of the keyboard and thekeypresses from the keyboard into two separate interfaces in the sameconfiguration. The mouse and keyboarddrivers each attach to the appropriate interface and allocate the pipesto the two independent endpoints.Example: Firmware download Many devices that have been developed arebased on a general purpose processor withanadditional USB core added to it. Because the development of driversand firmware for USB devices is still verynew, many devices require the downloading of the firmware after theyhave been connected.The procedure followed is straightforward. The device identifies itselfthrough a vendor and product Id. The first O primeirodriver probes and attaches to it and downloads the firmware into it.After that the device soft resets itself and thedriver is detached. After a short pause the devicere announces itspresence on the bus. The device will have changedits vendor/product/revision Id to reflect the fact that it has beensupplied with firmware and as a consequence asecond driver will probe it and attach to it.An example of these types of devices is the ActiveWire I/O board, basedon the EZ-USB chip. For this chip a genericfirmware downloader is available. The firmware downloaded into theActiveWire board changes the revision Id. It Elewill then perform a soft reset of the USB part of the EZ-USB chip todisconnect from the USB bus and againreconnect.Example: Mass Storage Devices Support for mass storage devices is mainlybuilt around existing protocols. The O/190/ /190/

Page 197: 139920579 Versao Traduzida de Book

------------------------------------------------------------------------*Page 199* *Página 199*

/Chapter 22./ /Capítulo 22./ /USB Devices/ /Dispositivos USB/Iomega USB Zipdrive is based on the SCSI version of their drive. TheSCSI commands and status messages arewrapped in blocks and transferred over the bulk pipes to and from thedevice, emulating a SCSI controller over theUSB wire. ATAPI and UFI commands are supported in a similar fashion.The Mass Storage Specification supports 2 different types of wrapping ofthe command block.The initial attempt wasbased on sending the command and status through the default pipe andusing bulk transfers for the data to be movedbetween the host and the device. Based on experience a second approachwas designed that was based on wrappingthe command and status blocks and sending them over the bulk out and inendpoint. The specification specifiesexactly what has to happen when and what has to be done in case an errorcondition is encountered. The biggestchallenge when writing drivers for these devices is to fit USB basedprotocol into theexisting support for massstorage devices. dispositivos de armazenamento. CAM provides hooks to dothis in a fairly straight forward way. ATAPI is less simple as historicallythe IDE interface has never had many different appearances.The support for the USB floppy from YE Data is again lessstraightforward as a new command set has beendesigned. projetado./191/ /191/------------------------------------------------------------------------*Page 200* *Página 200*

*Chapter 23. NewBus*This chapter will talk about the FreeBSD NewBus architecture./192/ /192/------------------------------------------------------------------------*Page 201* *Página 201*

*XII.* *XII.* *Architectures*------------------------------------------------------------------------*Page 202* *Página 202*

*Chapter 24. x86 Assembly Language**Programming* *Programação*/This chapter written by G. Adam Stanislav. Whiz Kid Technomagic(http://www.whizkidtech.net/) Modifications for//the Handbook made by Wylie Stilwell <//[email protected]//>, &.logo;, and Murray Stokely//</ /<//[email protected]//>/ />/*24.1.* *Synopsis* *Sinopse*Assembly language programing under Unix is highly undocumented. It isgenerally assumed that no one would everwant to use it because various Unix systems run on differentmicroprocessors, so everything should be written in Cfor portability.In reality, C portability is quite a myth. Even C programs need to bemodified when ported from one Unix to another,regardless of what processor each runs on. Typically, such a program is

Page 198: 139920579 Versao Traduzida de Book

full of conditional statements depending onthe system it is compiled for.Even if we believe that all of Unix software should be written in C, orsome other high-level language, we still needassembly language programmers: Who else would write the section of Clibrary that accesses the kernel?In this tutorial, which is quite brief at this time, I will attempt toshow you how you can use assembly languagewriting Unix programs, specifically under FreeBSD. I hope to turn itinto a complete course of FreeBSD assemblylanguage eventually.This tutorial does not explain the basics of assembly language. Thereare enough resources about that (for a completeonline course in assembly language, see Randall Hyde's Art of AssemblyLanguage (http://webster.cs.ucr.edu/); or ifyou prefer a printed book, take a look at Jeff Duntemann's AssemblyLanguage Step-by-Step. However, once thetutorial is finished, any assembly language programmer will be able towrite programs for FreeBSD quickly andefficiently.Copyright © 2000 G. Adam Stanislav.All rights reserved.*24.2. The Tools**24.2.1. The Assembler*The most important tool for assembly language programming is theassembler, the software that converts assemblylanguage code into machine language./194/ /194/------------------------------------------------------------------------*Page 203* *Página 203*

/Chapter 24. x86 Assembly Language Programming/Two very different assemblers are available for FreeBSD. One is as(1),which uses the traditional Unix assemblylanguage syntax. It comes with the system.The other is/usr/ports/devel/nasm. . It uses the Intel syntax. Its main advantage is that it can assemblecode formany operating systems. It needs to be installed separately, but iscompletely free.This tutorial uses /nasm/ syntax because most assembly languageprogrammers coming to FreeBSD from otheroperating systems will find it easier to understand. And, because, quitefrankly, that is what I am used to.*24.2.2. The Linker*The output of the assembler, like that of any compiler, needs to belinked to form an executable file.The standard ld(1) linker comes with FreeBSD. It works with the codeassembled with either assembler.*24.3. System Calls**24.3.1. Default Calling Convention*By default, the FreeBSD kernel uses the C calling convention. Further,although the kernel is accessed using int 80h,it is assumed the program will call a function that issues int 80h,rather than issuing int 80h directly.This convention is very convenient, and quite superior to the Microsoftconvention used by MS DOS. Why? Por quê? Because Porquethe Unix convention allows any program written in any language to accessthe kernel.An assembly language program can do that as well. For example, we could

Page 199: 139920579 Versao Traduzida de Book

open a file:kernel:int 80h ; Call kernelretopen:push dword modepush dword flagspush dword pathmov eax, 5call kerneladd esp, byte 12ret/195/ /195/------------------------------------------------------------------------*Page 204* *Página 204*

/Chapter 24. x86 Assembly Language Programming/This is a very clean and portable way of coding. If you need to port thecode to a Unix system which uses a differentinterrupt, or a different way of passing parameters, all you need tochange is the kernel procedure.But assembly language programmers like to shave off cycles. The aboveexample requires acall/retcombination. combinação.We can eliminate it by pushing an extra dword:open:push dword modepush dword flagspush dword pathmov eax, 5push eax ; Or any other dwordint 80hadd esp, byte 16The /5/ that we have placed in /EAX/ identifies the kernel function, inthis case /open/ .*24.3.2. Alternate Calling Convention*FreeBSD is an extremely flexible system. It offers other ways of callingthe kernel. For it to work, however, thesystem must have Linux emulation installed.Linux is a Unix-like system. However, its kernel uses the Microsoftsystem-call convention of passing parameters inregisters. registra. As with the Unix convention, the function number isplaced in /EAX/ . The parameters, however, are notpassed on the stack but /EBX, ECX, EDX, ESI, EDI, EBP/ :open:mov eax, 5mov ebx, pathmov ecx, flagsmov edx, modeint 80hThis convention has a great disadvantage over the Unix way, at least asfar as assembly language programming isconcerned: Every time you make a kernel call you must /push/ theregisters, then /pop/ them later. This makes your codebulkier and slower. Nevertheless, FreeBSD gives you a choice.If you do choose the Microsoft/Linux convention, you must let the systemknow about it. After your program isassembled and linked, you need to brand the executable:% %

Page 200: 139920579 Versao Traduzida de Book

*brandelf -f Linux filename*/196/ /196/------------------------------------------------------------------------*Page 205* *Página 205*

/Chapter 24. x86 Assembly Language Programming/*24.3.3. Which convention should you use?*If you are coding specifically for FreeBSD, you should always use theUnix convention: It is faster, you can storeglobal variables in registers, you do not have to brand the executable,and you do not impose the installation of theLinux emulation package on the target system.If you want to create portable code that can also run on Linux, you willprobably still want to give the FreeBSD usersas efficient a code as possible. I will show you how you can accomplishthat after I have explained the basics.*24.3.4. Call Numbers*To tell the kernel which system service you are calling, place itsnumber in /EAX/ . Of course, you need to know whatthe number is.*24.3.4.1. The Syscalls File*The numbers are listed insyscalls. /locate syscalls/ finds this file in several different formats, allproducedautomatically fromsyscalls.master. .You can find the master file for the default Unix calling convention in/usr/src/sys/kern/syscalls.master. .If you need to use the Microsoft convention implemented in the Linuxemulation mode, read/usr/src/sys/i386/linux/syscalls.master. ./NB:/ Not only do FreeBSD and Linux use different calling conventions,they sometimes use different numbers forthe same functions.syscalls.masterdescribes how the call is to be made:0 0STD STDNOHIDE{ int nosys(void); } syscall nosys_args int1 1STD STDNOHIDE{ void exit(int rval); } exit rexit_args void2 2STD STDPOSIX POSIX{ int fork(void); }3 3STD STDPOSIX POSIX{ ssize_t read(int fd, void *buf, size_t nbyte); }4 4STD STDPOSIX POSIX{ ssize_t write(int fd, const void *buf, size_t nbyte); }

Page 201: 139920579 Versao Traduzida de Book

5 5STD STDPOSIX POSIX{ int open(char *path, int flags, int mode); }6 6STD STDPOSIX POSIX{ int close(int fd); }etc... etc ..It is the leftmost column that tells us the number to place in /EAX/ .The rightmost column tells us what parameters to /push/ . They are/push/ ed from right to left./EXAMPLE 3.1:/ For example, to /open/ a file, we need to /push/ the/mode/ first, then /flags/ , then the address at which the/path/ is stored./197/ /197/------------------------------------------------------------------------*Page 206* *Página 206*

/Chapter 24. x86 Assembly Language Programming/*24.4. Return Values*A system call would not be useful most of the time if it did not returnsome kind of a value: The file descriptor of anopen file, the number of bytes read to a buffer, the system time, etc.Additionally, the system needs to inform us if an error occurs: A filedoes not exist, system resources are exhausted,we passed an invalid parameter, etc.*24.4.1. man-pages*The traditional place to look for information about various system callsunder Unix systems are the man pages.FreeBSD describes its system calls in section 2, sometimes in section 3.For example, Por exemplo, aopen(2)says: diz:If successful,open() open ()returns a non-negative integer, termed a file descriptor. It returns/-1/ on failure, and sets /errno/to indicate the error.The assembly language programmer new to Unix and FreeBSD willimmediately ask the puzzling question: Whereis /errno/ and how do I get to it?/NB:/ The information presented in the man pages applies to C programs.The assembly language programmer needsadditional information.*24.4.2. Where are the return values?*Unfortunately, it depends... For most system calls it is in /EAX/ , butnot for all. A good rule of thumb, when workingwith a system call for the first time, look for the return value in/EAX/ . If it is not there, you need further research./NB:/ I am aware of one system call that returns the value in /EDX/ :/SYS_fork/ . All others I have worked with use /EAX/ .But I have not worked with them all yet./TIP/ : If you cannot find the answer here or anywhere else, study libcsource code and see how it interfaces with thekernel. kernel.*24.4.3. Where is**errno**>?*Actually, nowhere...

Page 202: 139920579 Versao Traduzida de Book

errnois part of the C language, not the Unix kernel. When accessing kernelservices directly, the error code isreturned in /EAX/ , the same register the proper return value generallyends up in./198/ /198/------------------------------------------------------------------------*Page 207* *Página 207*

/Chapter 24. x86 Assembly Language Programming/This makes perfect sense. If there is no error, there is no error code.If there is an error, there is no return value. One Umregister can contain either.*24.4.4. Determining an Error Occurred*When using the standard FreeBSD calling convention, the /carry flag/ iscleared upon success, set upon failure.When using the Linux emulation mode, the signed value in /EAX/ isnon-negative upon success, and contains thereturn value. retornar o valor. In case of an error, the value isnegative, ie, /-errno/ .*24.5. Creating Portable Code*Portability is generally not one of the strengths of assembly language.Yet, writing assembly language programs fordifferent platforms is possible, especially with /nasm/ . I have writtenassembly language libraries that can beassembled for such different operating systems as Windows and FreeBSD.It is all the more possible when you want your code to run on twoplatforms which, while different, are based onsimilar architectures.For example, FreeBSD is Unix, Linux is Unix-like. I only mentioned threedifferences between them (from anassembly language programmerâs perspective): The calling convention, thefunction numbers, and the way ofreturning values.*24.5.1. Dealing With Function Numbers*In many cases the function numbers are the same. However, even when theyare not, the problem is easy to deal with:Instead of using numbers in your code, use constants which you havedeclared differently depending on the targetarchitecture:%ifdef LINUX%define SYS_execve 11%else%define SYS_execve 59%endif/199/ /199/------------------------------------------------------------------------*Page 208* *Página 208*

/Chapter 24. x86 Assembly Language Programming/*24.5.2. Dealing With Conventions*Both, the calling convention, and the return value (the /errno/ problem)can be resolved with macros:%ifdef LINUX%macro system 0call kernel%endmacroalign 4kernel:push ebx empurrar ebx

Page 203: 139920579 Versao Traduzida de Book

push ecxpush edxpush esipush edipush ebpmov ebx, [esp+32]mov ecx, [esp+36]mov edx, [esp+40]mov esi, [esp+44]mov ebp, [esp+48]int 80hpop ebppop edipop esipop edxpop ecxpop ebxor eax, eaxjs .errnoclcret.errno:neg eaxstcret%else/200/ /200/------------------------------------------------------------------------*Page 209* *Página 209*

/Chapter 24. x86 Assembly Language Programming/%macro system 0int 80h%endmacro%endif*24.5.3. Dealing With Other Portability Issues*The above solutions can handle most cases of writing code portablebetween FreeBSD and Linux. Nevertheless, withsome kernel services the differences are deeper.In that case, you need to write two different handlers for thoseparticular system calls, and use conditional assembly.Luckily, most of your code does something other than calling the kernel,so usually you will only need a few suchconditional sections in your code.*24.5.4. Using a Portable Library*You can avoid portability issues in your main code altogether by writinga library of system calls. Create a separatelibrary for FreeBSD, a different one for Linux, and yet other librariesfor more operating systems.In your library, write a separate function (or procedure, if you preferthe traditional assembly language terminology)for each system call. Use the C calling convention of passingparameters. But still use /EAX/ to pass the call numberin. In that case, your FreeBSD library can be very simple, as manyseemingly different functions can be just labels tothe same code:sys.open:sys.close:[etc...]int 80h

Page 204: 139920579 Versao Traduzida de Book

retYour Linux library will require more different functions. But even hereyou can group system calls using the samenumber of parameters:sys.exit:sys.close:[etc... one-parameter functions]push ebx empurrar ebxmov ebx, [esp+12]/201/ /201/------------------------------------------------------------------------*Page 210* *Página 210*

/Chapter 24. x86 Assembly Language Programming/int 80hpop ebxjmp sys.return... ...sys.return:or eax, eaxjs sys.errclcretsys.err:neg eaxstcretThe library approach may seem inconvenient at first because it requiresyou to produce a separate file your codedepends on. But it has many advantages: For one, you only need to writeit once and can use it for all your programs.You can even let other assembly language programmers use it, or perhapsuse one written by someone else. But Masperhaps the greatest advantage of the library is that your code can beported to other systems, even by otherprogrammers, by simply writing a new library without any changes to yourcode.If you do not like the idea of having a library, you can at least placeall your system calls in a separate assemblylanguage file and link it with your main program. Here, again, allporters have to do is create a new object file to linkwith your main program.*24.5.5. Using a Portable Include File*If you are releasing your software as (or with) source code, you can usemacros and place them in a separate file,which you include in your code.Porters of your software will simply write a new include file. Nolibrary or external object file is necessary, yet yourcode is portable without any need to edit the code./NB:/ This is the approach we will use throughout this tutorial. We willname our include file /system.inc/ , and add to itwhenever we deal with a new system call.We can start oursystem.incby declaring the standard file descriptors:%definestdin 0%definestdout 1%define

Page 205: 139920579 Versao Traduzida de Book

stderr 2/202/ /202/------------------------------------------------------------------------*Page 211* *Página 211*

/Chapter 24. x86 Assembly Language Programming/Next, we create a symbolic name for each system call:%defineSYS_nosys 0%defineSYS_exit 1%defineSYS_fork 2%defineSYS_read 3%defineSYS_write 4; [etc...]We add a short, non-global procedure with a long name, so we do notaccidentally reuse the name in our code:section .codealign 4access.the.bsd.kernel:int int80h 80hretWe create a macro which takes one argument, the syscall number:%macro system 1mov eax, %1call access.the.bsd.kernel%endmacroFinally, we create macros for each syscall. These macros take no arguments.%macro sys.exit 0system SYS_exit%endmacro%macro sys.fork 0system sistemaSYS_fork%endmacro%macro sys.read 0system sistemaSYS_read%endmacro%macro sys.write 0system SYS_write/203/ /203/------------------------------------------------------------------------*Page 212* *Página 212*

/Chapter 24. x86 Assembly Language Programming/%endmacro; [etc...]Go ahead, enter it into your editor and save it assystem.inc. . We will add more to it as we discuss more syscalls.*24.6. Our First Program*We are now ready for our first program, the mandatory /Hello, World!/1: %include 'system.inc'2: 2:3: section .data

Page 206: 139920579 Versao Traduzida de Book

4: hello db 'Hello, World!', 0Ah5: hbytes equ $-hello6: 6:7: section .code8: global _start9: _start:10: push dword hbytes11: push dword hello12: push dword stdout13: sys.write14: 14:15: push dword 016: sys.exitHere is what it does: Line 1 includes the defines, the macros, and thecode fromsystem.inc. .Lines 3-5 are the data: Line 3 starts the data section/segment. Line 4contains the string "Hello, World!" followed by seguidoa new line (0Ah). Line 5 creates a constant that contains the length ofthe string from line 4 in bytes.Lines 7-16 contain the code. Note that FreeBSD uses the elf file formatfor its executables, which requires everyprogram to start at the point labeled _start (or, more precisely, thelinker expects that). This label has to be global.Lines 10-13 ask the system to write /hbytes/ bytes of the /hello/ string tostdout. .Lines 15-16 ask the system to end the program with the return value of/0/ . The OSYS_exitsyscall never returns, so thecode ends there./NB:/ If you have come to Unix from MS DOS assembly language background,you may be used to writing directlyto the video hardware. You will never have to worry about this inFreeBSD, or any other flavor of Unix. As far as you/204/ /204/------------------------------------------------------------------------*Page 213* *Página 213*

/Chapter 24. x86 Assembly Language Programming/are concerned, you are writing to a file known asstdout. . This can be the video screen, or a Telnet terminal, or anactual file, or even the input of another program. Which it is, is forthe system to figure out.*24.6.1. Assembling the Code*Type the code (except the line numbers) in an editor, and save it in afile namedhello.asm. . You need /nasm/ toassemble it.*24.6.1.1. Installing NASM*If you do not have /nasm/ , type:% %*su*Password: *your root password*# #*cd /usr/ports/devel/nasm*

Page 207: 139920579 Versao Traduzida de Book

# #*make install*# #*exit*% %% %*su*Password: *your root password*# #*cd /usr/ports/devel/nasm*# #*make install*# #*exit*% %You may type /make install clean/ instead of just /make install/ if youdo not want to keep /nasm/ source code.Either way, FreeBSD will automatically download /nasm/ from theInternet, compile it, and install it on your system./NB:/ If your system is not FreeBSD, you need to get /nasm/ from itshome page (http://www.web-sites.co.uk/nasm/).You can still use it to assemble FreeBSD code.*24.6.2. Assemble, link and run*Now you can assemble, link, and run the code:% %*nasm -f elf hello.asm*% %*ld -s -o hello hello.o*% %*./hello*Hello, World!% %/205/ /205/------------------------------------------------------------------------*Page 214* *Página 214*

/Chapter 24. x86 Assembly Language Programming/*24.7. Writing Unix Filters*A common type of Unix application is a filterâa program that reads datafrom the /stdin/ , processes it somehow, thenwrites the result to /stdout/ .In this chapter, we shall develop a simple filter, and learn how to readfrom /stdin/ and write to /stdout/ . This filter willconvert each byte of its input into a hexadecimal number followed by ablank space.%include 'system.inc'section .datahex feitiçodb '0123456789ABCDEF'buffer db 0, 0, ' 'section .codeglobal _start_start:; read a byte from stdinpush dword 1push dword bufferpush dword stdinsys.readadd esp, byte 12or eax, eax

Page 208: 139920579 Versao Traduzida de Book

je .done; convert it to hexmovzx eax, byte [buffer]mov edx, eaxshr dl, 4mov dl, [hex+edx]mov [buffer], dland al, 0Fhmov al, [hex+eax]mov [buffer+1], al; print itpush dword 3push dword bufferpush dword stdoutsys.writeadd esp, byte 12jmp short _start.done: :/206/ /206/------------------------------------------------------------------------*Page 215* *Página 215*

/Chapter 24. x86 Assembly Language Programming/push empurrardword 0sys.exitIn the data section we create an array called /hex/ . It contains the 16hexadecimal digits in ascending order. The arrayis followed by a buffer which we will use for both input and output. Thefirst two bytes of the buffer are initially setto /0/ . This is where we will write the two hexadecimal digits (thefirst byte also is where we will read the input). The Othird byte is a space.The code section consists of four parts: Reading the byte, converting itto a hexadecimal number, writing the result,and eventually exiting the program.To read the byte, we ask the system to read one byte from /stdin/ , andstore it in the first byte of the /buffer/ . The systemreturns the number of bytes read in /EAX/ . This will be /1/ while datais coming, or /0/ , when no more input data isavailable. disponível. Therefore, we check the value of /EAX/ . If it is/0/ , we jump to /.done/ , otherwise we continue./NB:/ For simplicity sake, we are ignoring the possibility of an errorcondition at this time.The hexadecimal conversion reads the byte from the /buffer/ into /EAX/ ,or actually just /AL/ , while clearing theremaining bits of /EAX/ to zeros. We also copy the byte to /EDX/ becausewe need to convert the upper four bits(nibble) separately from the lower four bits. We store the result in thefirst two bytes of the buffer.Next, we ask the system to write the three bytes of the buffer, ie, thetwo hexadecimal digits and the blank space, to/stdout/ . We then jump back to the beginning of the program and processthe next byte.Once there is no more input left, we ask the system to exit our program,returning a zero, which is the traditionalvalue meaning the program was successful.Go ahead, and save the code in a file namedhex.asm

Page 209: 139920579 Versao Traduzida de Book

, then type the following (the /^D/ means press the control keyand type /D/ while holding the control key down):% %*nasm -f elf hex.asm*% %*ld -s -o hex hex.o*% %*./hex*Hello, World!48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 0AHere I come!48 65 72 65 20 49 20 63 6F 6D 65 21 0A*^D* *^ D*% %/NB:/ If you are migrating to Unix from MS DOS, you may be wondering whyeach line ends with /0A/ instead of /0D//0A/ . This is because Unix does not use the cr/lf convention, but aânew lineâ convention, which is /0A/ in hexadecimal.Can we improve this? Well, for one, it is a bit confusing because oncewe have converted a line of text, our input nolonger starts at the begining of the line. We can modify it to print anew line instead of a space after each /0A/ :%include 'system.inc'/207/ /207/------------------------------------------------------------------------*Page 216* *Página 216*

/Chapter 24. x86 Assembly Language Programming/section .datahex db '0123456789ABCDEF'buffer db 0, 0, ' 'section .codeglobal _start_start:mov cl, ' '.loop:; read a byte from stdinpush dword 1push dword bufferpush dword stdinsys.readadd esp, byte 12or eax, eaxje .done; convert it to hexmovzx eax, byte [buffer]mov [buffer+2], clcmp al, 0Ahjne .hexmov [buffer+2], al.hex:mov edx, eaxshr dl, 4mov dl, [hex+edx]mov [buffer], dland al, 0Fhmov al, [hex+eax]mov [buffer+1], al; print itpush dword 3

Page 210: 139920579 Versao Traduzida de Book

push dword bufferpush dword stdoutsys.writeadd esp, byte 12jmp short .loop.done:/208/ /208/------------------------------------------------------------------------*Page 217* *Página 217*

/Chapter 24. x86 Assembly Language Programming/push dword 0sys.exitWe have stored the space in the /CL/ register. We can do this safelybecause, unlike Microsoft Windows, Unix systemcalls do not modify the value of any register they do not use to returna value in.That means we only need to set /CL/ once. We have, therefore, added anew label /.loop/ and jump to it for the next byteinstead of jumping at /_start/ . We have also added the /.hex/ label sowe can either have a blank space or a new line asthe third byte of the /buffer/ .Once you have changed /hex.asm/ to reflect these changes, type:% %*nasm -f elf hex.asm*% %*ld -s -o hex hex.o*% %*./hex*Hello, World!48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 0AHere I come!48 65 72 65 20 49 20 63 6F 6D 65 21 0A*^D* *^ D*% %That looks better. But this code is quite inefficient! We are making asystem call for every single byte twice (once toread it, another time to write the output).*24.8. Buffered Input and Output*We can improve the efficiency of our code by buffering our input andoutput. We create an input buffer and read awhole sequence of bytes at one time. Then we fetch them one by one fromthe buffer.We also create an output buffer. We store our output in it until it isfull. At that time we ask the kernel to write thecontents of the buffer to /stdout/ .The program ends when there is no more input. But we still need to askthe kernel to write the contents of our outputbuffer to /stdout/ one last time, otherwise some of our output wouldmake it to the output buffer, but never be sent out.Do not forget that, or you will be wondering why some of your output ismissing.%include 'system.inc'%define BUFSIZE 2048section .datahex db '0123456789ABCDEF'/209/ /209/------------------------------------------------------------------------*Page 218* *Página 218*

Page 211: 139920579 Versao Traduzida de Book

/Chapter 24. x86 Assembly Language Programming/section .bssibuffer resb BUFSIZEobuffer resb BUFSIZEsection .codeglobal _start_start:sub eax, eaxsub ebx, ebxsub ecx, ecxmov edi, obuffer.loop:; read a byte from stdincall getchar; convert it to hexmov dl, alshr al, 4mov al, [hex+eax]call putcharmov al, dland al, 0Fhmov al, [hex+eax]call putcharmov al, ' 'cmp dl, 0Ahjne .putmov al, dl.put:call putcharjmp short .loopalign 4getchar:or ebx, ebxjne .fetchcall read.fetch:lodsb/210/ /210/------------------------------------------------------------------------*Page 219* *Página 219*

/Chapter 24. x86 Assembly Language Programming/dec ebxretread: leia-se:push dword BUFSIZEmov esi, ibufferpush esipush dword stdinsys.readadd esp, byte 12mov ebx, eaxor eax, eaxje .donesub eax, eaxretalign 4.done:call write ; flush output bufferpush dword 0

Page 212: 139920579 Versao Traduzida de Book

sys.exitalign 4putchar:stosb stosbinc ecxcmp ecx, BUFSIZEje writeretalign 4write: escrever:sub edi, ecx ; start of bufferpush ecxpush edipush dword stdoutsys.writeadd esp, byte 12sub eax, eaxsub ecx, ecx ; buffer is empty nowretWe now have a third section in the source code, named /.bss/ . Thissection is not included in our executable file, and,therefore, cannot be initialized. We use /resb/ instead of /db/ . Itsimply reserves the requested size of uninitializedmemory for our use./211/ /211/------------------------------------------------------------------------*Page 220* *Página 220*

/Chapter 24. x86 Assembly Language Programming/We take advantage of the fact that the system does not modify theregisters: We use registers for what, otherwise,would have to be global variables stored in the /.data/ section. This isalso why the Unix convention of passingparameters to system calls on the stack is superior to the Microsoftconvention of passing them in the registers: Wecan keep the registers for our own use.We use /EDI/ and /ESI/ as pointers to the next byte to be read from orwritten to. We use /EBX/ and /ECX/ to keep count ofthe number of bytes in the two buffers, so we know when to dump theoutput to, or read more input from, the system.Let us see how it works now:% %*nasm -f elf hex.asm*% %*ld -s -o hex hex.o*% %*./hex*Hello, World!Here I come!48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 0A48 65 72 65 20 49 20 63 6F 6D 65 21 0A*^D* *^ D*% %Not what you expected? The program did not print the output until wepressed /^D/ . That is easy to fix by insertingthree lines of code to write the output every time we have converted anew line to /0A/ . I have marked the three lineswith > (do not copy the > in yourhex.asm%include 'system.inc'

Page 213: 139920579 Versao Traduzida de Book

%define BUFSIZE 2048section .datahex db '0123456789ABCDEF'section .bssibuffer resb BUFSIZEobuffer resb BUFSIZEsection .codeglobal _start_start:sub eax, eaxsub ebx, ebxsub ecx, ecxmov edi, obuffer.loop:; read a byte from stdin/212/ /212/------------------------------------------------------------------------*Page 221* *Página 221*

/Chapter 24. x86 Assembly Language Programming/call getchar; convert it to hexmov dl, alshr al, 4mov al, [hex+eax]call putcharmov al, dland al, 0Fhmov al, [hex+eax]call putcharmov al, ' 'cmp dl, 0Ahjne .putmov al, dl.put:call putchar> cmp al, 0Ah> jne .loop> call writejmp short .loopalign 4getchar:or ebx, ebxjne .fetchcall read.fetch:lodsbdec ebxretread: leia-se:push dword BUFSIZEmov esi, ibufferpush esipush dword stdinsys.readadd esp, byte 12mov ebx, eax/213/ /213/------------------------------------------------------------------------*Page 222* *Página 222*

Page 214: 139920579 Versao Traduzida de Book

/Chapter 24. x86 Assembly Language Programming/or eax, eaxje .donesub eax, eaxretalign 4.done:call write ; flush output bufferpush dword 0sys.exitalign 4putchar:stosb stosbinc ecxcmp ecx, BUFSIZEje writeretalign 4write: escrever:sub edi, ecx ; start of bufferpush ecxpush edipush dword stdoutsys.writeadd esp, byte 12sub eax, eaxsub ecx, ecx ; buffer is empty nowretNow, let us see how it works:% %*nasm -f elf hex.asm*% %*ld -s -o hex hex.o*% %*./hex*Hello, World!48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 0AHere I come!48 65 72 65 20 49 20 63 6F 6D 65 21 0A*^D* *^ D*% %Not bad for a 644-byte executable, is it!/214/ /214/------------------------------------------------------------------------*Page 223* *Página 223*

/Chapter 24. x86 Assembly Language Programming/*24.8.1. How to Unread a Character*/WARNING:/ This may be a somewhat advanced topic, mostly of interest toprogrammers familiar with the theory ofcompilers. If you wish, you may skip to the next chapter(#command-line), and perhaps read this later.While our sample program does not require it, more sophisticated filtersoften need to look ahead. In other words, Em outras palavras,they may need to see what the next character is (or even severalcharacters). If the next character is of a certain value,it is part of the token currently being processed. Otherwise, it is not.For example, you may be parsing the input stream for a textual string(eg, when implementing a language

Page 215: 139920579 Versao Traduzida de Book

compiler): If a character is followed by another character, or perhaps adigit, it is part of the token you areprocessing. processamento. If it is followed by white space, or someother value, then it is not part of the current token.This presents an interesting problem: How to return the next characterback to the input stream, so it can be readagain later?One possible solution is to store it in a character variable, then set aflag. We can modifygetcharto check the flag,and if it is set, fetch the byte from that variable instead of the inputbuffer, and reset the flag. But, of course, thatslows us down.The C language has anungetc() ungetc ()function, just for that purpose. Is there a quick way to implement it inour code? I Euwould like you to scroll back up and take a look at thegetcharprocedure and see if you can find a nice and fastsolution before reading the next paragraph. Then come back here and seemy own solution.The key to returning a character back to the stream is in how we aregetting the characters to start with:First we check if the buffer is empty by testing the value of /EBX/ . Ifit is zero, we call the /read/ procedure.If we do have a character available, we use /lodsb/ , then decrease thevalue of /EBX/ . The /lodsb/ instruction is effectivelyidentical to:mov al, [esi]inc esiThe byte we have fetched remains in the buffer until the next timeread leris called. We do not know when thathappens, but we do know it will not happen until the next call togetchar. . Hence, to âreturnâ the last-read byte backto the stream, all we have to do is decrease the value of /ESI/ andincrease the value of /EBX/ :ungetc:dec esiinc ebxretBut, be careful! We are perfectly safe doing this if our look-ahead isat most one character at a time. If we areexamining more than one upcoming character and callungetcseveral times in a row, it will work most of the time,but not all the time (and will be tough to debug). Why? Por quê?/215/ /215/------------------------------------------------------------------------*Page 224* *Página 224*

/Chapter 24. x86 Assembly Language Programming/Because as long asgetchardoes not have to callread lerall of the pre-read bytes are still in the buffer, and our

Page 216: 139920579 Versao Traduzida de Book

ungetcworks without a glitch. But the momentgetcharcalls chamadasread ler, the contents of the buffer change.We can always rely onungetcworking properly on the last character we have read withgetchar, but not onanything we have read before that.If your program reads more than one byte ahead, you have at least twochoices:If possible, modify the program so it only reads one byte ahead. This isthe simplest solution.If that option is not available, first of all determine the maximumnumber of characters your program needs to returnto the input stream at one time. Increase that number slightly, just tobe sure, preferably to a multiple of 16âso italigns nicely. Then modify the /.bss/ section of your code, and create asmall âspareâ buffer right before your inputbuffer, something like this:section .bssresb 16 ; or whatever the value you came up withibuffer resb BUFSIZEobuffer resb BUFSIZEYou also need to modify yourungetcto pass the value of the byte to unget in /AL/ :ungetc:dec esiinc ebxmov [esi], alretWith this modification, you can callungetcup to 17 times in a row safely (the first call will still be within thebuffer, the remaining 16 may be either within the buffer or within theâspareâ).*24.9. Command-line Arguments*Our /hex/ program will be more useful if it can read the names of aninput and output file from its command line, ie,if it can process the command line arguments. But... Mas ... Where arethey? Onde eles estão?Before a Unix system starts a program, it pushes some data on the stack,then jumps at the /_start/ label of theprogram. programa. Yes, I said jumps, not calls. That means the data canbe accessed by reading /[esp+offset]/ , or by simply/pop/ ping it.The value at the top of the stack contains the number of command linearguments. It is traditionally called /argc/ , forâargument count.â/216/ /216/------------------------------------------------------------------------*Page 225* *Página 225*

/Chapter 24. x86 Assembly Language Programming/Command line arguments follow next, all /argc/ of them. These aretypically referred to as /argv/ , for âargument

Page 217: 139920579 Versao Traduzida de Book

value(s).â That is, we get /argv[0]/ , /argv[1]/ , /.../ ,/argv[argc-1]/ . These are not the actual arguments, but pointers toarguments, ie, memory addresses of the actual arguments. The argumentsthemselves are NUL-terminated characterstrings. strings.The /argv/ list is followed by a /NULL/ pointer, which is simply a /0/ .There is more, but this is enough for our purposesright now. agora./NB:/ If you have come from the MS DOS programming environment, the maindifference is that each argument is ina separate string. The second difference is that there is no practicallimit on how many arguments there can be.Armed with this knowledge, we are almost ready for the next version ofhex.asm. . First, however, we need to add afew lines tosystem.inc: :First, we need to add two new entries to our list of system call numbers:%define SYS_open 5%define SYS_close 6Then we add two new macros at the end of the file:%macro sys.open 0system SYS_open%endmacro%macro sys.close 0system SYS_close%endmacroHere, then, is our modified source code:%include 'system.inc'%define BUFSIZE 2048section .datafd.in dd stdinfd.out dd stdouthex db '0123456789ABCDEF'section .bssibuffer resb BUFSIZEobuffer resb BUFSIZEsection .codealign 4/217/ /217/------------------------------------------------------------------------*Page 226* *Página 226*

/Chapter 24. x86 Assembly Language Programming/err:push dword 1 ; return failuresys.exitalign 4global _start_start:add esp, byte 8 ; discard argc and argv[0]pop ecxjecxz .init ; no more arguments; ECX contains the path to input filepush dword 0 ; O_RDONLYpush ecxsys.openjc err ; open failedadd esp, byte 8

Page 218: 139920579 Versao Traduzida de Book

mov [fd.in], eaxpop ecxjecxz .init ; no more arguments; ECX contains the path to output filepush dword 420 ; file mode (644 octal)push dword 0200h | 0400h | 01h; O_CREAT | O_TRUNC | O_WRONLYpush ecxsys.openjc erradd esp, byte 12mov [fd.out], eax.init:sub eax, eaxsub ebx, ebxsub ecx, ecxmov edi, obuffer.loop:; read a byte from input file or stdincall getchar/218/ /218/------------------------------------------------------------------------*Page 227* *Página 227*

/Chapter 24. x86 Assembly Language Programming/; convert it to hexmov dl, alshr al, 4mov al, [hex+eax]call putcharmov al, dland al, 0Fhmov al, [hex+eax]call putcharmov al, ' 'cmp dl, 0Ahjne .putmov al, dl.put:call putcharcmp al, dljne .loopcall writejmp short .loopalign 4getchar:or ebx, ebxjne .fetchcall read.fetch:lodsbdec ebxretread: leia-se:push dword BUFSIZEmov esi, ibufferpush esipush dword [fd.in]sys.readadd esp, byte 12

Page 219: 139920579 Versao Traduzida de Book

mov ebx, eaxor eax, eaxje .done/219/ /219/------------------------------------------------------------------------*Page 228* *Página 228*

/Chapter 24. x86 Assembly Language Programming/sub eax, eaxretalign 4.done:call write ; flush output buffer; close filespush dword [fd.in]sys.closepush dword [fd.out]sys.close; return successpush dword 0sys.exitalign 4putchar:stosbinc ecxcmp ecx, BUFSIZEje writeretalign 4write: escrever:sub edi, ecx ; start of bufferpush ecxpush edipush dword [fd.out]sys.writeadd esp, byte 12sub eax, eaxsub ecx, ecx ; buffer is empty nowretIn our /.data/ section we now have two new variables, /fd.in/ and/fd.out/ . We store the input and output file descriptorshere. aqui.In the /.code/ section we have replaced the references to /stdin/ and/stdout/ with /[fd.in]/ and /[fd.out]/ .The /.code/ section now starts with a simple error handler, which doesnothing but exit the program with a return valueof /1/ . The error handler is before /_start/ so we are within a shortdistance from where the errors occur./220/------------------------------------------------------------------------*Page 229* *Página 229*

/Chapter 24. x86 Assembly Language Programming/Naturally, the program execution still begins at /_start/ . First, weremove /argc/ and /argv[0]/ from the stack: They are ofno interest to us (in this program, that is).We pop /argv[1]/ to /ECX/ . This register is particularly suited forpointers, as we can handle /NULL/ pointers with /jecxz/ .If /argv[1]/ is not /NULL/ , we try to open the file named in the firstargument. Otherwise, we continue the program as

Page 220: 139920579 Versao Traduzida de Book

before: Reading from /stdin/ , writing to /stdout/ . If we fail to openthe input file (eg, it does not exist), we jump to theerror handler and quit.If all went well, we now check for the second argument. If it is there,we open the output file. Otherwise, we send theoutput to /stdout/ . If we fail to open the output file (eg, it existsand we do not have the write permission), we, again,jump to the error handler.The rest of the code is the same as before, except we close the inputand output files before exiting, and, asmentioned, we use /[fd.in]/ and /[fd.out]/ .Our executable is now a whopping 768 bytes long.Can we still improve it? Of course! Of course! Every program can beimproved. Here are a few ideas of what we could do:• •Have our error handler print a message to /stderr/ .• •Add error handlers to theread lerand ewrite escreverfunctions. funções.• •Close /stdin/ when we open an input file, /stdout/ when we open anoutput file.• •Add command line switches, such as /-i/ and /-o/ , so we can list theinput and output files in any order, or perhapsread from /stdin/ and write to a file.• •Print a usage message if command line arguments are incorrect.I shall leave these enhancements as an exercise to the reader: Youalready know everything you need to know toimplement them.*24.10.* *24.10.* *Unix Environment*An important Unix concept is the environment, which is defined by/environment variables/ . Some are set by thesystem, others by you, yet others by the /shell/ , or any program thatloads another program.*24.10.1. How to Find Environment Variables*I said earlier that when a program starts executing, the stack contains/argc/ followed by the /NULL/ -terminated /argv/array, followed by something else. The âsomething elseâ is the/environment/ , or, to be more precise, a/NULL/ -terminated array of pointers to /environment variables/ . Thisis often referred to as /env/ ./221/ /221/------------------------------------------------------------------------*Page 230* *Página 230*

/Chapter 24. x86 Assembly Language Programming/The structure of /env/ is the same as that of /argv/ , a list of memoryaddresses followed by a /NULL/ ( /0/ ). In this case, Neste caso,there is no /âenvcâ/ âwe figure out where the array ends by searchingfor the final /NULL/ .The variables usually come in the /name=value/ format, but sometimes the=value part may be missing. We need to Precisamosaccount for that possibility.*24.10.2. Webvar*I could just show you some code that prints the environment the same way

Page 221: 139920579 Versao Traduzida de Book

the Unix /env/ command does. But I Mas euthought it would be more interesting to write a simple assembly languageCGI utility.*24.10.2.1. CGI: A Quick Overview*/10.2.1. CGI: A Quick Overview/I have a detailed CGI tutorial(http://www.whizkidtech.net/cgi-bin/tutorial) on my web site, but hereis a very quickoverview of CGI:• •The web server communicates with the CGI program by setting /environmentvariables/ .• •The CGI program sends its output to /stdout/ . The web server reads itfrom there.• •It must start with an HTTP header followed by two blank lines.• •It then prints the HTML code, or whatever other type of data it isproducing./NB:/ While certain /environment variables/ use standard names, othersvary, depending on the web server. That makes Isso faz com que/webvars/ quite a useful diagnostic tool.*24.10.3. Webvar continued...*Our /webvar/ program, then, must send out the HTTP header followed bysome HTML mark-up. It then must read the/environment variable/ one by one and send them out as part of the HTMLpage.The code follows. I placed comments and explanations right inside the code:;;;;;;; webvars.asm;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Copyright (c) 2000 G. Adam Stanislav; All rights reserved.; ;; Redistribution and use in source and binary forms, with or without; modification, are permitted provided that the following conditions/222/ /222/------------------------------------------------------------------------*Page 231* *Página 231*

/Chapter 24. x86 Assembly Language Programming/; are met:; 1. Redistributions of source code must retain the above copyright; ;notice, this list of conditions and the following disclaimer. avisoprévio, esta lista de condições ea seguinte renúncia.; 2. Redistributions in binary form must reproduce the above copyrightAs redistribuições em formato binário devem reproduzir o copyright acima; ;notice, this list of conditions and the following disclaimer in theaviso, esta lista de condições ea seguinte isenção de responsabilidade na; ;documentation and/or other materials provided with the distribution.; ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS “AS IS” AND; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE

Page 222: 139920579 Versao Traduzida de Book

; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION); HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF; SUCH DAMAGE.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; ;; Version 1.0; ;; Started: 8-Dec-2000; Updated: 8-Dec-2000; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

%include 'system.inc'section .datahttp db 'Content-type: text/html', 0Ah, 0Ahdb ' < ?xml version="1.0" encoding="UTF-8"? > ', 0Ahdb ' < !DOCTYPE html PUBLIC "-//W3C/DTD XHTML Strict//EN" 'db '"DTD/xhtml1-strict.dtd" > ', 0Ahdb ' < html xmlns="http://www.w3.org/1999/xhtml" 'db 'xml.lang="en" lang="en" > ', 0Ahdb ' < head > ', 0Ahdb ' < title > Web Environment < /title > ', 0Ahdb ' < meta name="author" content="G. Adam Stanislav" / > ', 0Ahdb ' < /head > ', 0Ah, 0Ahdb ' < body bgcolor="#ffffff" text="#000000" link="#0000ff" 'db 'vlink="#840084" alink="#0000ff" > ', 0Ahdb ' < div class="webvars" > ', 0Ahdb ' < h1 > Web Environment < /h1 > ', 0Ahdb ' < p > The following < b > environment variables < /b > are defined 'db 'on this web server: < /p > ', 0Ah, 0Ah/223/ /223/------------------------------------------------------------------------*Page 232* *Página 232*

/Chapter 24. x86 Assembly Language Programming/db ' < table align="center" width="80" border="0" cellpadding="10" 'db 'cellspacing="0" class="webvars" > ', 0Ahhttplen equ $-httpleft db ' < tr > ', 0Ahdb ' < td class="name" >< tt > 'leftlen equ $-leftmiddle db ' < /tt >< /td > ', 0Ahdb ' < td class="value" >< tt >< b > 'midlen equ $-middleundef db ' < i > (undefined) < /i > 'undeflen equ $-undefright db ' < /b >< /tt >< /td > ', 0Ahdb ' < /tr > ', 0Ahrightlen equ $-rightwrap db ' < /table > ', 0Ahdb ' < /div > ', 0Ahdb ' < /body > ', 0Ahdb ' < /html > ', 0Ah, 0Ah

Page 223: 139920579 Versao Traduzida de Book

wraplen equ $-wrapsection .codeglobal _start_start:; First, send out all the http and xhtml stuff that is; needed before we start showing the environmentpush dword httplenpush dword httppush dword stdoutsys.write; Now find how far on the stack the environment pointers; are. We have 12 bytes we have pushed before "argc"mov eax, [esp+12]; We need to remove the following from the stack:; ;; The 12 bytes we pushed for sys.write; The 4 bytes of argc; The EAX*4 bytes of argv; The 4 bytes of the NULL after argv; ;; Total:; 20 + eax * 4; ;; Because stack grows down, we need to ADD that many bytes/224/ /224/------------------------------------------------------------------------*Page 233* *Página 233*

/Chapter 24. x86 Assembly Language Programming/; to ESP.lea esp, [esp+20+eax*4]cld ; This should already be the case, but let's be sure.; Loop through the environment, printing it out.loop:pop edior edi, edi ; Done yet?je near .wrap; Print the left part of HTMLpush dword leftlenpush dword leftpush dword stdoutsys.write; It may be tempting to search for the '=' in the env string next.; But it is possible there is no '=', so we search for the; terminating NUL first.mov esi, edi ; Save start of stringsub ecx, ecxnot ecx ; ECX = FFFFFFFFsub eax, eaxrepne scasb REPNE scasbnot ecx ; ECX = string length + 1mov ebx, ecx ; Save it in EBX; Now is the time to find '='mov edi, esi ; Start of stringmov al, '='repne scasb REPNE scasbnot ecxadd ecx, ebx ; Length of namepush ecxpush esi

Page 224: 139920579 Versao Traduzida de Book

push dword stdoutsys.write; Print the middle part of HTML table codepush dword midlenpush dword middlepush dword stdoutsys.write/225/ /225/------------------------------------------------------------------------*Page 234* *Página 234*

/Chapter 24. x86 Assembly Language Programming/; Find the length of the valuenot ecxlea ebx, [ebx+ecx-1]; Print "undefined" if 0or ebx, ebxjne .valuemov ebx, undeflenmov edi, undef.value:push ebx empurrar ebxpush edipush dword stdoutsys.write; Print the right part of the table rowpush dword rightlenpush dword rightpush dword stdoutsys.write; Get rid of the 60 bytes we have pushedadd esp, byte 60; Get the next variablejmp .loop.wrap:; Print the rest of HTMLpush dword wraplenpush dword wrappush dword stdoutsys.write; Return successpush dword 0sys.exitThis code produces a 1,396-byte executable. Most of it is data, ie, theHTML mark-up we need to send out.Assemble and link it as usual:/226/ /226/------------------------------------------------------------------------*Page 235* *Página 235*

/Chapter 24. x86 Assembly Language Programming/% %*nasm -f elf webvars.asm*% %*ld -s -o webvars webvars.o*To use it, you need to upload /webvars/ to your web server. Depending onhow your web server is set up, you mayhave to store in a special /cgi-bin/ directory, or perhaps rename itwith a /.cgi/ extension.Then you need to use your browser to view its output. To see its output

Page 225: 139920579 Versao Traduzida de Book

on my web server, please instruct yourbrowser to go to /http://www.int80h.org/webvars// . I am deliberatelynot placing a regular link here because I do notwant its output to appear on all the search engines...*24.11.* *24.11.* *Working with Files*We have already done some basic file work: We know how to open and closethem, how to read and write them usingbuffers. But Unix offers much more functionality when it comes to files.We will examine some of it in this section,and end up with a nice file conversion utility.Indeed, let us start at the end, that is, with the file conversionutility. It always makes programming easier when weknow from the start what the end product is supposed to do.One of the first programs I wrote for Unix was /tuc/(ftp://ftp.int80h.org/unix/tuc/), a text-to-Unix file converter. It Eleconverts a text file from other operating systems to a Unix text file.In other words, it changes from different kind ofline endings to the newline convention of Unix. It saves the output in adifferent file. Optionally, it converts a Unixtext file to a DOS text file.I have used /tuc/ extensively, but always only to convert from someother OS to Unix, never the other way. I have Eu tenhoalways wished it would just overwrite the file instead of me having tosend the output to a different file. Most of the A maior parte dotime, I end up using it like this:% %*tuc myfile tempfile*% %*mv tempfile myfile*It would be nice to have aftuc, ie,fast tuc, and use it like this:% %*ftuc myfile*In this chapter, then, we will write /ftuc/ in assembly language (theoriginal /tuc/ is in /C/ ), and study various file-orientedkernel services in the process.At first sight, such a file conversion is very simple: All you have todo is strip the carriage returns, right?If you answered yes, think again: That approach will work most of thetime (at least with MS DOS text files), butwill fail occasionally./227/ /227/------------------------------------------------------------------------*Page 236* *Página 236*

/Chapter 24. x86 Assembly Language Programming/The problem is that not all non-Unix text files end their line with thecarriage return / line feed sequence. Some usecarriage returns without line feeds. Others combine several blank linesinto a single carriage return followed byseveral line feeds. And so on. E assim por diante.A text file converter, then, must be able to handle any possible lineendings:• •carriage return / line feed• •carriage return retorno de carro

Page 226: 139920579 Versao Traduzida de Book

• •line feed / carriage return• •line feedIt should also handle files that use some kind of a combination of theabove (eg, carriage return followed by severalline feeds).*24.11.1. Finite State Machine*The problem is easily solved by the use of a technique called /finitestate machine/ , originally developed by thedesigners of digital electronic circuits. A /finite state machine/ is adigital circuit whose output is dependent not onlyon its input but on its previous input, ie, on its state. Themicroprocessor is an example of a /finite state machine/ : Ourassembly language code is assembled to machine language in which someassembly language code produces a singlebyte of machine language, while others produce several bytes. As themicroprocessor fetches the bytes from thememory one by one, some of them simply change its state rather thanproduce some output. When all the bytes of theop code are fetched, the microrpocessor produces some output, or changesthe value of a register, etc.Because of that, all software is essentially a sequence of stateinstructions for the microprocessor. Nevertheless, the No entanto, oconcept of /finite state machine/ is useful in software design as well.Our text file converter can be designed as a /finite state machine/ withthree possible states. We could call them states0-2, but it will make our life easier if we give them symbolic names:• •/ordinary/ /comum/• •/cr/ /cr/• •/lf/ /lf/Our program will start in the /ordinary/ state. During this state, theprogram action depends on its input as follows:• •If the input is anything other than a carriage return or line feed, theinput is simply passed on to the output. The Ostate remains unchanged.• •If the input is a carriage return, the state is changed to /cr/ . Theinput is then discarded, ie, no output is made.• •If the input is a line feed, the state is changed to /lf/ . The input isthen discarded./228/ /228/------------------------------------------------------------------------*Page 237* *Página 237*

/Chapter 24. x86 Assembly Language Programming/Whenever we are in the /cr/ state, it is because the last input was acarriage return, which was unprocessed. What oursoftware does in this state again depends on the current input:• •If the input is anything other than a carriage return or line feed,output a line feed, then output the input, thenchange the state to /ordinary/ .• •If the input is a carriage return, we have received two (or more)

Page 227: 139920579 Versao Traduzida de Book

carriage returns in a row. We discard the input, weoutput a line feed, and leave the state unchanged.• •If the input is a line feed, we output the line feed and change thestate to /ordinary/ . Note that this is not the same asthe first case above â if we tried to combine them, we would beoutputting two line feeds instead of one.Finally, we are in the /lf/ state after we have received a line feedthat was not preceded by a carriage return. This willhappen when our file already is in Unix format, or whenever severallines in a row are expressed by a single carriagereturn followed by several line feeds, or when line ends with a linefeed / carriage return sequence. Here is how weneed to handle our input in this state:• •If the input is anything other than a carriage return or line feed, weoutput a line feed, then output the input, thenchange the state to /ordinary/ . This is exactly the same action as inthe /cr/ state upon receiving the same kind ofinput. entrada.• •If the input is a carriage return, we discard the input, we output aline feed, then change the state to /ordinary/ .• •If the input is a line feed, we output the line feed, and leave thestate unchanged.*24.11.1.1. The Final State*The above /finite state machine/ works for the entire file, but leavesthe possibility that the final line end will beignored. ignorados. That will happen whenever the file ends with asingle carriage return or a single line feed. I did not think ofit when I wrote /tuc/ , just to discover that occasionally it strips thelast line ending.This problem is easily fixed by checking the state after the entire filewas processed. If the state is not /ordinary/ , wesimply need to output one last line feed./NB:/ Now that we have expressed our algorithm as a /finite statemachine/ , we could easily design a dedicated digitalelectronic circuit (a âchipâ) to do the conversion for us. Of course,doing so would be considerably more expensivethan writing an assembly language program.*24.11.1.2. The Output Counter*Because our file conversion program may be combining two characters intoone, we need to use an output counter.We initialize it to 0, and increase it every time we send a character tothe output. At the end of the program, thecounter will tell us what size we need to set the file to./229/ /229/------------------------------------------------------------------------*Page 238* *Página 238*

/Chapter 24. x86 Assembly Language Programming/*24.11.2. Implementing FSM in Software*The hardest part of working with a /finite state machine/ is analyzingthe problem and expressing it as a /finite state//machine/ . That accomplished, the software almost writes itself.In a high-level language, such as C, there are several main approaches.One is to use a /switch/ statement whichchooses what function should be run. For example, Por exemplo, aswitch (state) {

Page 228: 139920579 Versao Traduzida de Book

default: default:case REGULAR:regular(inputchar);break; quebrar;case CR:cr(inputchar);break; quebrar;case LF:lf(inputchar);break; quebrar;} }Another approach is by using an array of function pointers, somethinglike this:(output[state])(inputchar);Yet another is to have /state/ be a function pointer, set to point atthe appropriate function:(*state)(inputchar);This is the approach we will use in our program because it is very easyto do in assembly language, and very fast,too. também. We will simply keep the address of the right procedure in/EBX/ , and then just issue:call ebxThis is possibly faster than hardcoding the address in the code becausethe microprocessor does not have to fetch theaddress from the memoryâit is already stored in one of its registers. Isaid /possibly/ because with the caching modernmicroprocessors do, either way may be equally fast./230/ /230/------------------------------------------------------------------------*Page 239* *Página 239*

/Chapter 24. x86 Assembly Language Programming/*24.11.3. Memory Mapped Files*Because our program works on a single file, we cannot use the approachthat worked for us before, ie, to read froman input file and to write to an output file.Unix allows us to map a file, or a section of a file, into memory. To dothat, we first need to open the file with theappropriate read/write flags. Then we use the /mmap/ system call to mapit into the memory. One nice thing about/mmap/ is that it automatically works with virtual memory: We can mapmore of the file into the memory than we havephysical memory available, yet still access it through regular memory opcodes, such as /mov/ , /lods/ , and /stos/ .Whatever changes we make to the memory image of the file will be writtento the file by the system. We do not evenhave to keep the file open: As long as it stays mapped, we can read fromit and write to it.The 32-bit Intel microprocessors can access up to four gigabytes ofmemory â physical or virtual. The FreeBSDsystem allows us to use up to a half of it for file mapping.For simplicity sake, in this tutorial we will only convert files thatcan be mapped into the memory in their entirety.There are probably not too many text files that exceed two gigabytes insize. If our program encounters one, it willsimply display a message suggesting we use the original /tuc/ instead.If you examine your copy ofsyscalls.master, you will find two separate syscalls named /mmap/ . This is becauseIsto é porque

Page 229: 139920579 Versao Traduzida de Book

of evolution of Unix: There was the traditional BSD /mmap/ , syscall 71.That one was superceded by the POSIX/mmap/ , syscall 197. The FreeBSD system supports both because olderprograms were written by using the originalBSD version. But new software uses the POSIX version, which is what wewill use.The Osyscalls.masterfile lists the POSIX version like this:197 STD BSD { caddr_t mmap(caddr_t addr, size_t len, int prot, \int flags, int fd, long pad, off_t pos); }This differs slightly from whatmmap(2)says. diz. That is because Isso é porquemmap(2)describes the C version.The difference is in the /long pad/ argument, which is not present inthe C version. However, the FreeBSD syscalls adda 32-bit pad after pushing a 64-bit argument. In this case, /off_t/ is a64-bit value.When we are finished working with a memory-mapped file, we unmap it withthe /munmap/ syscall:/TIP:/ For an in-depth treatment ofmmap, see W. Richard Stevensâ Unix Network Programming, Volume 2, Chapter12 (http://www.int80h.org/cgi-bin/isbn?isbn=0130810819).*24.11.4. Determining File size*Because we need to tellmmaphow many bytes of the file to map into the memory, and because we wantto map theentire file, we need toq determine the size of the file./231/ /231/------------------------------------------------------------------------*Page 240* *Página 240*

/Chapter 24. x86 Assembly Language Programming/We can use thefstatsyscall to get all the information about an open file that the systemcan give us. That includes Isso incluithe file size.Again, Novamente,syscalls.masterlists two versions offstat, a traditional one (syscall 69), and a POSIX one (syscall189)Naturally, we will use the POSIX version:189 STD POSIX { int fstat(int fd, struct stat *sb); }This is a very straightforward call: We pass to it the address of a/stat/ structure and the descriptor of an open file. It Elewill fill out the contents of the /stat/ structure.I do, however, have to say that I tried to declare thestat estatísticasstructure in the.bsssection, andfstatdid not like it: Itset the carry flag indicating an error. After I changed the code to

Page 230: 139920579 Versao Traduzida de Book

allocate the structure on the stack, everything wasworking fine.*24.11.5. Changing the File Size*/11.5./ /11.5./ /Changing the File Size/Because our program may combine carriage return / line feed sequencesinto straight line feeds, our output may besmaller than our input. However, since we are placing our output intothe same file we read the input from, we mayhave to change the size of the file.The Oftruncatesystem call allows us to do just that. Despite its somewhat misleadingname, theftruncatesystem call can be used to both truncate the file (make it smaller) andto grow it.And yes, we will find two versions offtruncatein emsyscalls.master, an older one (130), and a newer one (201).We will use the newer one:201 STD BSD { int ftruncate(int fd, int pad, off_t length); }Please note that this one contains aint padagain. novamente.*24.11.6. ftuc*We now know everything we need to write /ftuc/ . We start by adding somenew lines insystem.inc. . First, we definesome constants and structures, somewhere at or near the beginning of thefile:;;;;;;; open flags%define O_RDONLY 0%define O_WRONLY 1/232/ /232/------------------------------------------------------------------------*Page 241* *Página 241*

/Chapter 24. x86 Assembly Language Programming/%define O_RDWR 2;;;;;;; mmap flags%define PROT_NONE 0%define PROT_READ 1%define PROT_WRITE 2%define PROT_EXEC 4;; ;;%define MAP_SHARED 0001h%define MAP_PRIVATE 0002h;;;;;;; stat structurestruc statst_dev resd 1 ; = 0st_ino resd 1 ; = 4st_mode resw 1 ; = 8, size is 16 bitsst_nlink resw 1 ; = 10, dittost_uid resd 1 ; = 12st_gid resd 1 ; = 16st_rdev resd 1 ; = 20st_atime resd 1 ; = 24

Page 231: 139920579 Versao Traduzida de Book

st_atimensec resd 1 ; = 28st_mtime resd 1 ; = 32st_mtimensec resd 1 ; = 36st_ctime resd 1 ; = 40st_ctimensec resd 1 ; = 44st_size resd 2 ; = 48, size is 64 bitsst_blocks resd 2 ; = 56, dittost_blksize resd 1 ; = 64st_flags resd 1 ; = 68st_gen resd 1 ; = 72st_lspare resd 1 ; = 76st_qspare resd 4 ; = 80endstrucWe define the new syscalls:%define SYS_mmap 197%define SYS_munmap 73%define SYS_fstat 189%define SYS_ftruncate 201We add the macros for their use:%macro sys.mmap 0/233/ /233/------------------------------------------------------------------------*Page 242* *Página 242*

/Chapter 24. x86 Assembly Language Programming/system SYS_mmap%endmacro%macro sys.munmap 0system SYS_munmap%endmacro%macro sys.ftruncate 0system SYS_ftruncate%endmacro%macro sys.fstat 0system SYS_fstat%endmacroAnd here is our code:;;;;;;; Fast Text-to-Unix Conversion (ftuc.asm);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Started: 21-Dec-2000;; Updated: 22-Dec-2000;; ;;;; Copyright 2000 G. Adam Stanislav.;; All rights reserved.;; ;;;;;;;;; v.1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%include 'system.inc'section .datadb 'Copyright 2000 G. Adam Stanislav.', 0Ahdb 'All rights reserved.', 0Ahusg db 'Usage: ftuc filename', 0Ahusglen equ $-usgco db "ftuc: Can't open file.", 0Ahcolen equ $-cofae db 'ftuc: File access error.', 0Ahfaelen equ $-faeftl db 'ftuc: File too long, use regular tuc instead.', 0Ahftllen equ $-ftl

Page 232: 139920579 Versao Traduzida de Book

mae db 'ftuc: Memory allocation error.', 0Ahmaelen equ $-maesection .codealign 4/234/ /234/------------------------------------------------------------------------*Page 243* *Página 243*

/Chapter 24. x86 Assembly Language Programming/memerr:push dword maelenpush dword maejmp short erroralign 4toolong:push dword ftllenpush dword ftljmp short erroralign 4facerr:push dword faelenpush dword faejmp short erroralign 4cantopen:push dword colenpush dword cojmp short erroralign 4usage: uso:push dword usglenpush dword usgerror:push dword stderrsys.writepush dword 1sys.exitalign 4global _start_start:pop eax ; argcpop eax ; program namepop ecx ; file to convertjecxz usagepop eaxor eax, eax ; Too many arguments?/235/ /235/------------------------------------------------------------------------*Page 244* *Página 244*

/Chapter 24. x86 Assembly Language Programming/jne usage; Open the filepush dword O_RDWRpush ecxsys.openjc cantopenmov ebp, eax ; Save fdsub esp, byte stat_sizemov ebx, esp

Page 233: 139920579 Versao Traduzida de Book

; Find file sizepush ebx empurrar ebxpush ebp ; fdsys.fstatjc facerrmov edx, [ebx + st_size + 4]; File is too long if EDX != 0 ...or edx, edxjne near toolongmov ecx, [ebx + st_size]; ... ; ... or if it is above 2 GBor ecx, ecxjs near toolong; Do nothing if the file is 0 bytes in sizejecxz .quit; Map the entire file in memorypush edxpush edx ; starting at offset 0push edx ; padpush ebp ; fdpush dword MAP_SHAREDpush dword PROT_READ | PROT_WRITEpush ecx ; entire file sizepush edx ; let system decide on the addresssys.mmapjc near memerrmov edi, eax/236/ /236/------------------------------------------------------------------------*Page 245* *Página 245*

/Chapter 24. x86 Assembly Language Programming/mov esi, eaxpush ecx ; for SYS_munmappush edi; Use EBX for state machinemov ebx, ordinarymov ah, 0Ahcld.loop:lodsbcall ebxloop .loopcmp ebx, ordinaryje .filesize; Output final lfmov al, ahstosb stosbinc edx.filesize:; truncate file to new sizepush dword 0 ; high dwordpush edx ; low dwordpush eax ; padpush ebpsys.ftruncate; close it (ebp still pushed)sys.closeadd esp, byte 16sys.munmap

Page 234: 139920579 Versao Traduzida de Book

.quit:push dword 0sys.exitalign 4ordinary:cmp al, 0Dhje .cr/237/ /237/------------------------------------------------------------------------*Page 246* *Página 246*

/Chapter 24. x86 Assembly Language Programming/cmp al, ahje .lfstosb stosbinc edxretalign 4.cr:mov ebx, crretalign 4.lf:mov ebx, lfretalign 4cr:cmp al, 0Dhje .crcmp al, ahje .lfxchg al, ahstosb stosbinc edxxchg al, ah; fall through.lf:stosb stosbinc edxmov ebx, ordinaryretalign 4.cr:mov al, ahstosb stosbinc edxret/238/ /238/------------------------------------------------------------------------*Page 247* *Página 247*

/Chapter 24. x86 Assembly Language Programming/align 4lf:cmp al, ahje .lfcmp al, 0Dhje .crxchg al, ahstosb stosb

Page 235: 139920579 Versao Traduzida de Book

inc edxxchg al, ahstosb stosbinc edxmov ebx, ordinaryretalign 4.cr:mov ebx, ordinarymov al, ah; fall through.lf:stosb stosbinc edxret/WARNING:/ Do not use this program on files stored on a disk formated byMS DOS or Windows. There seems to be asubtle bug in the FreeBSD code when usingmmapon these drives mounted under FreeBSD: If the file is over acertain size,mmapwill just fill the memory with zeros, and then copy them to the fileoverwriting its contents.*24.12. Caveats*Assembly language programmers who "grew up" under MS DOS and Windowsoften tend to take shortcuts. Reading Leiturathe keyboard scan codes and writing directly to video memory are twoclassical examples of practices which, underMS DOS are not frowned upon but considered the right thing to do.The reason? Both the PC BIOS and MS DOS are notoriously slow whenperforming these operations./239/ /239/------------------------------------------------------------------------*Page 248* *Página 248*

/Chapter 24. x86 Assembly Language Programming/You may be tempted to continue similar practices in the Unixenvironment. For example, I have seen a web sitewhich explains how to access the keyboard scan codes on a popular Unixclone.That is generally a /very bad idea/ in Unix environment! Let me explainwhy. Deixe-me explicar o porquê.*24.12.1. Unix Is Protected*For one thing, it may simply not be possible. Unix runs in protectedmode. Only the kernel and device drivers areallowed to access hardware directly. Perhaps a particular Unix clonewill let you read the keyboard scan codes, butchances are a real Unix operating system will not. And even if oneversion may let you do it, the next one may not,so your carefully crafted software may become a dinosaur overnight.*24.12.2. Unix is an Abstraction*But there is a much more important reason not to try accessing thehardware directly (unless, of course, you arewriting a device driver), even on the Unix-like systems that let you do it:/Unix is an abstraction!/There is a major difference in the philosophy of design between MS DOSand Unix. MS DOS was designed as asingle-user system. It is run on a computer with a keyboard and a videoscreen attached directly to that computer.

Page 236: 139920579 Versao Traduzida de Book

User input is almost guaranteed to come from that keyboard. Yourprogramâs output virtually always ends up on thatscreen. tela.This is NEVER guaranteed under Unix. It is quite common for a Unix userto pipe and redirect program input andoutput: saída:% %*program1 | program2 | program3 > file1*If you have written /program2/ , your input does not come from thekeyboard but from the output /program1/ . Similarly, Da mesma forma,your output does not go to the screen but becomes the input for/program3/ whose output, in turn, goes tofile1. .But there is more! Even if you made sure that your input comes from, andyour output goes to, the terminal, there isno guarantee the terminal is a PC: It may not have its video memorywhere you expect it, nor may its keyboard beproducing PC-style scan codes. It may be a Macintosh, or any othercomputer.Now you may be shaking your head: My software is in assembly language,how can it run on a Macintosh? But I didnot say your software would be running on a Macintosh, only that itsterminal may be a Macintosh.Under Unix, the terminal does not have to be directly attached to thecomputer that runs your software, it can even beon another continent, or, for that matter, on another planet. It isperfectly possible that a Macintosh user in Australiaconnects to a Unix system in North America (or anywhere else) via/telnet/ . The software then runs on one computer,while the terminal is on a different computer: If you try to read thescan codes, you will get the wrong input!/240/ /240/------------------------------------------------------------------------*Page 249* *Página 249*

/Chapter 24. x86 Assembly Language Programming/Same holds true about any other hardware: A file you are reading may beon a disk you have no direct access to. A Acamera you are reading images from may be on a space shuttle, connectedto you via satellites.That is why under Unix you must never make any assumptions about whereyour data is coming from and going to.Always let the system handle the physical access to the hardware./NB:/ These are caveats, not absolute rules. Exceptions are possible.For example, if a text editor has determined it isrunning on a local machine, it may want to read the scan codes directlyfor improved control. I am not mentioningthese caveats to tell you what to do or what not to do, just to make youaware of certain pitfalls that await you if youhave just arrived to Unix form MS DOS. Of course, creative people oftenbreak rules, and it is OK as long as theyknow they are breaking them and why.*24.13.* *Acknowledgements* *Agradecimentos*This tutorial would never have been possible without the help of manyexperienced FreeBSD programmers from theFreeBSD hackers (mailto:[email protected]) mailing list, manyof whom have patiently answered myquestions, and pointed me in the right direction in my attempts toexplore the inner workings of Unix system

Page 237: 139920579 Versao Traduzida de Book

programming in general and FreeBSD in particular.Thomas M. Sommers opened the door for me. His How do I write "Hello,world" in FreeBSD assembler?(http://home.ptd.net/tms2/hello.html) web page was my first encounterwith an example of assembly languageprogramming under FreeBSD.Jake Burkholder has kept the door open by willingly answering all of myquestions and supplying me with exampleassembly language source code.Copyright © 2000 G. Adam Stanislav.All rights reserved./241/ /241/------------------------------------------------------------------------*Page 250* *Página 250*

*Chapter 25.* *Alpha* *Alfa*Talk about the architectural specifics of FreeBSD/alpha.Explanation of allignment errors, how to fix, how to ignore.Example assembly language code for FreeBSD/alpha./242/ /242/------------------------------------------------------------------------*Page 251* *Página 251*

*Chapter 26.* *Capítulo 26.* *IA-64*Talk about the architectural specifics of FreeBSD/ia64./243/ /243/------------------------------------------------------------------------*Page 252* *Página 252*

*XIII.* *XIII.* *Debugging* *Depuração*------------------------------------------------------------------------*Page 253* *Página 253*

*Chapter 27.* *Truss* *Treliça*various descriptions on how to debug certain aspects of the system usingtruss, ktrace, gdb, kgdb, etc/245/ /245/------------------------------------------------------------------------*Page 254* *Página 254*

*XIV.* *XIV.* *Compatibility Layers*------------------------------------------------------------------------*Page 255* *Página 255*

*Chapter 28.* *Capítulo 28.* *Linux* *Linux*Linux, SVR4, etc/247/ /247/------------------------------------------------------------------------*Page 256* *Página 256*

*XV.* *XV.* *Appendices* *Apêndices*------------------------------------------------------------------------*Page 257* *Página 257*

*Bibliography* *Bibliografia*[1] Dave A Patterson and John L Hennessy, 1998, 1-55860-428-6, MorganKaufmann Publishers, Inc., /Computer//Organization and Design: The Hardware / Software Interface, 1-2./[2] W. Richard Stevens, 1993, 0-201-56317-7, Addison Wesley Longman,Inc., /Advanced Programming in the Unix//Environment, 1-2./

Page 238: 139920579 Versao Traduzida de Book

[3] Marshall Kirk McKusick, Keith Bostic, Michael J Karels, and John SQuarterman, 1996, 0-201-54979-4,Addison-Wesley Publishing Company, Inc., /The Design and Implementationof the 4.4 BSD Operating System,//1-2./ /1-2./[4] Aleph One, /Phrack 49; "Smashing the Stack for Fun and Profit"./[5] Chrispin Cowan, Calton Pu, and Dave Maier, /StackGuard; AutomaticAdaptive Detection and Prevention of//Buffer-Overflow Attacks./[6] Todd Miller and Theo de Raadt, /strlcpy and strlcat -- consistent,safe string copy and concatenation../Texto original em inglês:Developing on <#8>Sugira uma tradução melhor