terça-feira, 19 de junho de 2012

Fork e Thread


Evite o fork() em caso de multithread...

Em sistemas Unix e Unix-like, quando uma chamada de sistema cria um fork, o processo faz uma cópia de si mesmo que chamamos de processo filho (child process). O SO pode diferenciar um do outro pelo retorno da função fork() que é zero no processo filho, enquanto que retorna o PID do processo filho no processo pai.

Quando vários processos rodam concomitantemente no mesmo processador, o kernel do SO pode dividí-los em unidades de processamento que podem ser agendadas segundo uma multiplexação por fração de tempo (time-slice multiplexing). Estas unidades são chamadas de threads de um processo. Processos podem rodar várias threads concorrentemente (multithread process) que otimiza a utilização da memória. Threads de um processo podem compartilhar recursos e memória, o que dois processos não podem fazer, por terem address space diferentes.

A maneira como o SO lida com os processos depende de como o processo foi programado e como ele realiza as chamadas de sistema (system call). Quando dois processos iguais correm em um mesmo sistema Unix, o kernel faz o fork() do processo e cria um novo processo (processo filho) com um novo address space. Além disso, o fork precisa do IPC (InterProcess Comunication) para trocar informações entre o processo pai e o processo filho, depois do fork. [1]

Alternativamente, o SO pode usar o recurso de múltiplos threads de um mesmo processo. Isto é mais vantajoso porque a comunicação e compartilhamento de recursos entre as threads é mais fácil (por estarem no mesmo address space) [2].

Existe, porém, um problema decorrente da chamada de um fork() em um processo multithread. Por exemplo, em um processamento multitarefa um fork() registra no processo pai o PID do processo filho. Mas, quando um thread em uma tarefa multithread executa um fork() qual delas conteria o processo filho? Se bem que é uma situação evitada sempre que possível, existem situações onde o fork do processo multithread resulta no processo filho (também multithread) e o término do processo filho precisa retornar informação para o processo pai via IPC.

Bem, pode ser que o processo filho contenha um thread correspondente ao thread do processo pai. Ou, talvez, é possível igualar o número de threads do processo filho ao do processo pai de tal forma que haja correspondência dos threads.http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

Mas, antes de implementar um fork() em um processo multithread, é preciso planejar muito bem. Normalmente, o processo "forked" deve ser criado como uma única thread e, se um processo multithreaded chama a função fork(), o novo processo deve ser um réplica exata de todas as  threads, bem como de seu espaço de endereçamento.

Por isso,  Pense duas vezes [3] antes de misturar fork() e threads.

Referências:

[1] Stevens, W. R. Unix Network Programming, 2nd Ed., Vol. 1, Prentice Hall, NJ, 1998.

[2] Stevens, W. R. Advanced Programming in the Unix Environment, Addison-Wesley, Reading, Mass., 1992

[3] http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

terça-feira, 12 de junho de 2012

Chamadas de sistema


Chamadas em C... cadê o C?

A postagem de hoje é um pouco técnica mas bem interessante. O objetivo é dar uma espiada no problema do "ovo ou a galinha". Bem, o kernel do Unix é escrito em C e, consequentemente, alguns símbolos das bibliotecas teriam que ser resolvidos nas libs em estão em /usr/lib ou /lib. Acontece que, quando o kernel está carregando, o sistema de arquivos ainda não está disponível. Então... o que vem primeiro? O ovo ou a galinha?

Como já vimos anteriormente em outras postagens deste blog, o kernel (ou núcleo) do sistema operacional (SO) é o responsável por grande parte do gerenciamento do sistema. Assim, ele fica responsável pelo gerenciamento da memória, gerenciamento das interfaces de entrada e saída (I/O), controle das interrupções etc., além das operações de iniciar o próprio sistema [1].

Em alguns kernels (microkernels  e exokernels ) estes serviços são executados no user space (userland) mas, mesmo assim, eles ficam disponíveis por meio das chamadas de sistema (system calls). Qualquer programa que rode no userland ou no kernel space pode disparar estas chamadas de sistemas que são as interfaces entre um processo e o SO.

As chamadas de sistema são feitas por meio de funções em C do tipo read, write, open, exit, por exemplo. O FreeBSD tem cerca de 500 chamadas de sistema, enquanto o Linux tem cerca 300. Algumas delas usam bibliotecas do GCC mas existe um detalhe importante: quando o kernel está carregando o SO, ele não tem acesso, ainda, às bibliotecas e cabeçalhos do C ou do GCC porque o sistema de arquivos ainda não está montado. Isto significa que o kernel tem que ter suas próprias bibliotecas e cabeçalhos.

Então, porque não implementar a biblioteca C dentro do código do kernel? Bem, basicamente é o que se faz, mas com muitas restrições.

  1. A libc tem outras funcionalidades não necessárias ao kernel e que pode apenas servir para aumentar o tamanho do kernel depois de compilado, por exemplo, ao inserir o string.h do gcc no kernel, as referências a memcpy(), memset(), memcmp() etc. estariam no código mas não seriam usadas no kernel space.
  2. A implementação, no kernel, requer que ela tenha como chamar o sistema (system call) de dentro do kernel [3].
  3. Outros símbolos e formatos são necessários para funções implementadas no kernel como, por exemplo, a função printf().


O exemplo a saída de mensagens do sistema durante o boot que em ANSI C pode ser implementada com a função printf(). apresenta o problema de que o stdio.h e a libc ainda não estão disponíveis. Assim, a função tem que estar definida no próprio código do kernel. No Linux. por exemplo, a função é chamada de printk() que está em .../linux/kernel/printk.c [4].

Exemplos:

printk("The address of my_var is %p\n", &my_var);

printk(KERN_DEBUG "*** This is a debug message. ***\n");

Os formatos mais usados na função printk() são o KERN_INFO e KERN_DEBUG. Estes formatos KERN_* são definidos no .../include/linux/kernel.h.


Referências:

[1] http://www.makelinux.net/kernel_map/

[2] Bach, M. http://www.vivaolinux.com.br/artigo/Novidades-do-Kernel-2.6.35J., The Design of the UNIX Operating System, Prentice Hall, 1986.

[3] Tanenbaum, A. S., Modern Operating Systems, Prentice Hall, 1076 pages, 2008.

[4] Love, R. Linux Kernel Development, Novell Press, 2005.

Crédito da imagem: http://www.vivaolinux.com.br/artigo/Novidades-do-Kernel-2.6.35

quinta-feira, 7 de junho de 2012

Diablo3 no Linux


"Eu uso Windows porque gosto de jogar..." Ha... ha!

Se tu és daqueles que diz que usa Windows porque gosta de games e Linux não tem games, estás enganado. Nem precisas ficar preocupado porque não poderás jogar Diablo III! Podes sim. E aqui vai uma dica de feriado (embora um pouco off topic do blog). Divirtam-se mas deixem um tempinho para estudar para as provas.

Primeiro tens que saber se tens a configuração de hardware adequada, por exemplo placas de vídeo, memória RAM etc. e, depois, se teu sistema tem as bibliotecas adequadas. O Ubuntu 12.04 roda bem em 32 bits. O sistema operacional em 64 bits não tem todas as bibliotecas do OpenGL necessárias para rodar o programa. Então é bom ler sobre o PlayOnLinux.

Mas os passos são simples (Ubuntu 12.04):

1. Instale o Wine [1]: use o 'pkg_add install wine',  a central de programas ou o Synaptic.

2. Instale o PlayOnLinux [2]: idem.

3. Faça o Download do Diablo III: Se tiver o DVD, pule os passos 4 e 5.

4. Se não tens grana pro DVD, use uma conta do Battle.net para baixar o instalador [3].

5. Clique no instalador e escolha "Abrir com o Wine Loader". E baixe o Diablo III.

6. Abra o programa "PlayOnLinux", siga as instruções de configuração inicial e, na interface principal clique em "install" e procure o programa do Diablo III.

7. Escolha o método de instalação (DVD ou o setup do Diablo) e clique em "Next" até aparecer uma nova janela de setup (agora do programa) que desaparece em alguns segundos para dar lugar à tela de instalação do Diablo III.

Have Fun!!!

Referências
:

[1] http://www.winehq.org/

[2] http://www.playonlinux.com/

[3] http://eu.battle.net

terça-feira, 5 de junho de 2012

UEFI


"Sometimes one pays most for the things one gets for nothing." [1]

A comunidade Free and Open Source Software (FOSS) está agitada, ultimamente porque a micro$oft (M$) resolveu bloquear o boot de qualquer sistema operacional não assinado digitalmente em sistemas equipados com processadores ARM por meio da Extensible Firmware Interface (EFI), melhor dizendo, Unified Extensible Firmware Interface (UEFI). Que é isso?

A ideia da EFI apareceu na criação do Itanium da Intel para resolver as limitações geradas pelo acesso ao modo real (16 bits) dos processadores, o limite de 1 MB do espaço endereçado e outras características típicas dos antigos processadores x86  e seu hardware. Estas limitações passaram a ser inaceitáveis nas plataformas que usavam o Itanium e nas modernas arquiteturas x86.

Em 2005 a Intel passou o EFI versão 1.10 para um Fórum que continuou o trabalho de especificação como Unified Extensible Firmware Interface (UEFI). A especificação da EFI continua pertencendo à Intel e as especificações posteriores da UEFI passaram a pertencer ao fórum [2].

A tecnologia envolvida na interface foi desenvolvida para melhorar certas interrupções da BIOS e permitir acesso a dispositivos mais modernos, implementando:

  • Acesso a endereçamento acima de 1 MB já no Power On Self Test (POST)
  • Acesso a discos de até 2 TB com uma tabela de partição mais completa e confiável.
  • Boot mais rápido
  • Arquitetura CPU-indenpendente
  • Drivers CPU-independentes
  • Ambiente pré Sistema Operacional mais flexível
  • Disponibilidade de rede antes de carregar o SO
  • Modularidade e escalabilidade.

Figura 1: Esquema simples da interação SO e Firmware por meio da interface UEFI.

Enfim, seria uma interface mais moderna com a BIOS e com facilidades muito mais interessantes para os modernos SOs. Mas, como a energia atômica e muitas facas têm dois gumes, a UEFI também. Em modo seguro, é possível gerar uma assinatura digital para aumentar a segurança do SO que roda sobre uma plataforma com UEFI. O que importa é que qualquer usuário pode criar a assinatura e, o mais importante, pode optar por desabilitar o modo seguro [3].

Figura 2: Detalhe da interação UEFI / BIOS

O boot acontece na sequência normal mas o Boot Manager/BIOS interage diretamente com o código da interface EFI/UEFI logo depois do POST, deixando o controle dos Drivers e APIs do manager para a UEFI. Antes de iniciar o sistema operacional, o boot autentica no próprio hardware a permissão de carregar o Operating System Loader. É aí que mora o perigo, pois se pode tornar o hardware "preso" a um sistema proprietário. Isto tem boas e más vantagens...

O que temos assistido recentemente, é que a M$ tem usado estas funcionalidades para tentar bloquear um determinado sistema, requerendo uma assinatura digital proprietária e não permitindo desabilitar o modo seguro nos processadores ARM e x86 de 64 bits.

Acontece que a M$ sempre achou que PC e liquidificador só precisariam de uma tomada (e 64 kB, claro). Veio a Internet e ela teve que "pegar" o código do TCP/IP que foi desenvolvido pela comunidade FOSS; veio, então o browser (navegador) e ela teve que "pegar" o código do Mosaic [4] que também foi desenvolvido pela comunidade FOSS. Não, não vou comentar a história do QDOS e CP/M, do X-Windows da Xerox e nem do DOSShell do Norton Commander.

Mas agora, perdendo terreno para Apple, Linux e Linux/Android, ela tenta desesperadamente uma última cartada... assinar a interface UEFI digitalmente para bloquear qualquer código não assinado. Espero que seja a última, mesmo e que os usuários deixem de ser tão etc..

Este é exatamente o exemplo de como ela pretende fazer o usuário de otário [5]. Me desculpem meus nobres leitores, mas eu diria que isto é mais uma <fêmea do cágado> da M$ e querem saber? Acho que não vai rolar!



Referências:

[1] Albert Einstein.

[2] http://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface

[3] http://www.uefi.org/home/

[4] Abra o IE e clique em "About IE".

[5] Todo usuário da Microsoft é um beta-tester (Bill Gates na apresentação do Windows 95).

Crédito das imagens:

Imagem topo: http://www.uefi.org/about/logo/

[Fig 1] http://en.wikipedia.org/wiki/File:Efi-simple.svg

[Fig 2] http://en.wikipedia.org/wiki/File:Efi_flowchart_extended.svg



domingo, 3 de junho de 2012

Fedora 17



... the magic of a gnome!


Este blog começou por causa do Unity. Quando o Ubuntu adotou o Unity como window manager (WM) a grande maioria dos usuários Linux (inclusive o próprio Linus Torvalds) sentiram uma certa aversão e abominaram a escolha da Canonical.

Eu mesmo publiquei o primeiro artigo deste blog como "O Rei morreu... Viva o Rei!", afirmando que mudaria de SO e comecei uma grande peregrinação pelo universo dos Linuces. Fiquei espantado ao descobrir quanto eu estava desatualizado neste terreno. Hoje, noto a tendência de todos os SOs que começam a ficar com interface pronta para tablets e smartphones. É a tendência e, fatalmente, acabaremos nos acostumando ao novo modelo.

Mas ainda existe muita resistência à utilização do Unity, embora o próprio Gnome 3 tenha assumido o mesmo "jeitão". Esta resistência tem vários motivos que vão desde o simples "não gostei" até as explicações técnicas sobre limitações de configuração, passando pelas justificativas sobre ergonomia e usabilidade. O fato é que alguns já estão se acostumando ao Gnome 3 e mesmo ao Unity (eu inclusive).

Mas para aqueles que não gostam do Unity, aí está o Fedora 17 (Beefy Miracle) que vem com o Gnome 3 e não deve nada ao Ubuntu. Realmente, o que me atrai no Ubuntu é a quantidade de software disponibilizado em pacotes Debian (.deb) e a sua facilidade de uso mas a equipe do Fedora tem feito um excelente trabalho, mantendo as versões mais recentes e mais estáveis dos softwares em pacotes Red Hat Packet Manager (.rpm).

O que gosto do Fedora é a rapidez e a estabilidade. Afinal o pessoal RedHat/Fedora sempre fez um excelente trabalho. Uma excelente comparação dos dois pode ser encontrado no artigo "When An Ubuntu User Revisits Fedora 17" [1].

Entretanto, nem tudo é doce no Fedora. Apesar de ser uma excelente distro do Linux é necessário fazer muitos ajustes para que ele fique pronto para as atividades comuns de um desktop. Isto se deve ao fato de que os organizadores da distro são conservadores quanto ao uso de plugins proprietários. Mas isto não se torna um problema muito sério, uma vez que se pode instalar este extras com facilidade. A instalação de aplicativos e CODECs, drivers gráficos, Fontes etc. é bastante rápida e existem várias dicas na Web de como fazê-lo [2,3,4,5].

O Fedora 17 é bem mais fácil de instalar que o Windows ou Mac, inclusive no Virtual Box com uma configuração de recursos bem acanhada, sendo bem intuitivo de tal modo que qualquer usuário pode instalá-lo sem dificuldades. O boot do sistema é rápido e o desligamento idem. Na minha opinião, o Fedora 17 é uma distribuição que rivaliza em pé de igualdade com o Ubuntu 12.04 e usar um ou outro depende apenas de gosto e da atividade e necessidade específica de cada um.

Onde encontrar? Aí está o link:

http://fedoraproject.org/get-fedora

Referências:

[1] Bhartiya, S. When An Ubuntu User Revisits Fedora 17 em  http://www.muktware.com/3650/when-ubuntu-user-revisits-fedora-17-review

[2] http://www.unixmen.com/fedora-17-install-codecs-drivers-and-fonts-in-under-5-minutes/

[3] http://www.unixmen.com/how-to-install-media-codecs-for-fedora-1415/

[4] http://www.unixmen.com/how-to-install-nvidia-drivers-in-fedora-13-and-14/

[5] http://www.unixmen.com/install-mp3-players-in-fedora-13/