Simulação do Linux Scheduler

Simulando o Linux Scheduler no espaço do usuário com o LinSched

A programação é um dos aspectos mais complexos —e interessantes— do kernel Linux. O desenvolvimento de schedulers que fornecem um comportamento adequado de máquinas de núcleo único a servidores de núcleo quádruplo pode ser difícil. Felizmente, o Linux Scheduler Simulator (LinSched) hospeda o scheduler Linux no espaço do usuário (para prototipagem do scheduler) enquanto modela destinos de hardware arbitrários para validar o seu scheduler ao longo de uma variedade de topologias. Conheça o LinSched e veja como fazer experiências com o scheduler para o Linux.

M. Tim Jones, Platform Architect, Intel

author photo - M. Tim JonesM. Tim Jones é arquiteto de firmware integrado e autor de Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming (atualmente em sua segunda edição), AI Application Programming (em sua segunda edição) e BSD Sockets Programming from a Multilanguage Perspective. Seu conhecimento em engenharia varia do desenvolvimento de kernels para naves espaciais geossíncronas até a arquitetura de sistemas embarcados e o desenvolvimento de protocolos de rede. Tim trabalha na Intel e reside em Longmont, Colorado.



12/Abr/2011

Programar tarefas no Linux é um trabalho complexo. O Linux opera em diversos modelos de uso (como servidor enterprise, área de trabalho do cliente e até mesmo dispositivos integrados) em uma variedade muito ampla de topologias de processador (núcleo único, multicore, multicore/multithread, etc.). O fato de que o pequeno número de políticas de programação no Linux funcione é surpreendente.

Para piorar as coisas, é difícil medir a eficácia das políticas de programação no Linux, porque o scheduler fica dentro do kernel. A inclusão de uma introspecção, como o rastreio, pode alterar o comportamento do scheduler e ocultar defeitos ou ineficiências. E mais: se você configurasse cenários de programação para validar uma determinada carga de trabalho ao longo das diversas topologias de processador, você arrancaria os cabelos.

Felizmente, projetos como o LinSched (User-space Linux Scheduler Simulator) pode ajudar a resolver esse problema.

Apresentando o LinSched

O LinSched é um simulador de scheduler do Linux que reside no espaço do usuário. Ele isola o subsistema do scheduler do Linux e desenvolve ao redor do mesmo uma quantidade suficiente do ambiente do kernel para que possa ser executado dentro do espaço do usuário. Ele também desenvolve ao redor do mesmo um conjunto de interfaces de programação de aplicativos (APIs) para fornecer os estímulos necessários para validar as cargas de trabalho de programação e coletar uma quantidade suficiente de dados relevantes para entender o seu comportamento (mais adiante, irei explorar a sua arquitetura geral).

A colocação do scheduler no espaço do usuário facilita a execução do scheduler (porque um travamento do mesmo não compromete toda a máquina). Também simplifica a coleta de dados sobre o scheduler, porque ele consegue coletar dados e armazená-los no sistema de arquivos local de forma fácil e eficiente.

As alternativas incluem o uso da virtualização, mas o LinSched oferece as vantagens da simplicidade e eficiência (porque não é necessário fazer o boot de outro kernel). Como processo no espaço do usuário, também é fácil conectar um depurador como o GNU Debugger (GDB) para fornecer um insight ainda maior sobre a operação do scheduler.


As origens do LinSched

O LinSched foi originalmente desenvolvido na Universidade da Carolina do Norte (com verba da IBM e da Intel), mas foi retomado recentemente pela Google para validar as políticas de programação. Essa ação é interessante e pode representar uma tendência no futuro. Embora o Linux suporte várias classes de programação e faça uma programação razoável ao longo de várias cargas de trabalho, ele pode não ser ideal para uma carga de trabalho específica em uma determinada topologia de hardware. Como a Google investe em um cluster grande de máquinas idênticas que executam uma tarefa específica (por exemplo: MapReduce), faria sentido que a programação fosse ajustada para esse tipo de tarefa e ambiente. Ao usar o LinSched, a Google também contribuiu com aprimoramentos ao Linux para o Completely Fair Scheduler (CFS), como fornecimento de largura da banda e balanceamento de carga quando há um grande diferencial de peso entre as tarefas.


Arquitetura do LinSched

O LinSched é mais do que um simulador de scheduler que executa no espaço do usuário: é uma migração do scheduler do Linux para o espaço do usuário com uma emulação leve dos componentes necessários para que o scheduler possa executar fora do kernel. A fonte do LinSched é, na verdade, uma distribuição do Linux (atualmente 2.6.35) com um novo subdiretório chamado ./linsched para os wrappers e o mecanismo de simulação. Como o LinSched usa o subsistema do scheduler do Linux dentro do Linux para a simulação do mesmo, fica muito mais simples fazer alterações e, em seguida, integrá-las novamente ao kernel.

A arquitetura geral do LinSched é mostrada na Figura 1. O sistema operacional do host está na parte inferior. O LinSched é um aplicativo do espaço do usuário desenvolvido a partir de diversos componentes (inclusive partes do próprio kernel Linux).

Figura 1. Arquitetura do LinSched Scheduler Simulator
Arquitetura do LinSched Scheduler Simulator

O módulo do ambiente fornece a abstração do kernel Linux (com sinalizadores para suportar a compilação no modo de simulação). O mecanismo de simulação, que estende uma API para uso na configuração do ambiente e na realização da simulação fica no módulo do ambiente. A API do mecanismo de simulação fornece uma função de inicialização que também define a topologia do processador e as funções para criação de tarefas, retornos de chamada (por exemplo: quando uma tarefa é programada) e uma função run para executar a simulação por um determinado número de ticks (que, por sua vez, chama a função interna do Linux chamada schedule() para tomar decisões de programação).

Acima do mecanismo de simulação, fica o ambiente de script (o código da simulação propriamente dita). Pode ser um único script, mas, como o exemplo a seguir mostra, o uso mais simples é alterar o script de ambiente já existente para incluir cenários de teste.

A arquitetura básica do LinSched é muito simples. Primeiro vamos mostrar como instalar o LinSched e, em seguida, abordar algumas das APIs estendidas e mostrar como elas são usadas em uma simulação.


Instalando o LinSched

O LinSched foi atualizado recentemente para suportar o kernel 2.6.35. Há várias formas de capturar o pacote atual do LinSched —por meio de git ou da página da Web do projeto (consulte Recursos). Para capturar a distribuição com git, clone o repositório como:

$ git clone git://google3-2.osuosl.org/linsched/2.6.35.git

Nos dois casos, você obterá um subdiretório chamado 2.6.35/ que contém a distribuição. No subdiretório LinSched, é possível executar a seguinte linha de comando para fazer um teste rápido:

$ make run_all_tests

Essa linha de comando executa vários testes no scheduler em diversas topologias de processador e emite os resultados dos testes.


APIs do LinSched

Para executar uma simulação do LinSched, você cria um script e executa um conjunto de inicializações para configurar o cenário desejado. Essa inicialização é executada por meio de um conjunto de chamadas à API do LinSched. Esta seção aborda algumas funções importantes da API (e posteriormente demonstra o seu uso). Observe que a API inteira não é divulgada abaixo, mas arquivos de origem em ./linsched fornecem uma lista mais detalhada.

Antes de executar uma simulação, é necessário inicializar o simulador. Isso é feito por meio de uma chamada a linsched_init. Essa função aceita como argumento a topologia de processador simulada, configura internamente o ambiente do simulador e inicia o kernel Linux no espaço do usuário.

void linsched_init( struct linsched_topology *topo );

A estrutura da topologia, definida em linux_linsched.h, define o número de processadores e a sua relação entre si (estabelecendo a correspondência com um pacote físico e um mapa de distância de nós). É possível especificar um pacote de processador único com TOPO_UNIPROCESSOR ou uma topologia com quatro soquetes e processador quad-core com TOPO_QUAD_CPU_QUAD_SOCKET.

As tarefas dentro do LinSched são entidades simuladas, mas o LinSched oferece a você o controle para criar um grande número de cenários de tarefas. Uma das funções mais úteis cria várias tarefas que seguem uma configuração ocupado/suspenso. O responsável pela chamada fornece o número de tarefas a ser criadas (count), a máscara de processadores para a qual essas tarefas podem executar (mask) e, em seguida, as contagens de ticks suspenso/ocupado (identificadas como sleep e run).

void create_tasks( unsigned int count, unsigned long mask, int sleep, int run );

Para criar um cenário de tarefas mais específico, há várias funções adicionais de API de criação de tarefas disponíveis (consulte a Listagem 1). Essas funções permitem a criação de tarefas normais, em lote ou em tempo real (primeiro a entrar, primeiro a sair [FIFO] ou round robin), com uma prioridade específica ou um nível bom. A criação de uma tarefa normal configura a política de programação como SCHED_NORMAL, onde batch, RTfifo e RTrr são configurados como SCHED_BATCH, SCHED_FIFO e SCHED_RR, respectivamente. O usuário pode fornecer uma estrutura de tarefas para controlar o comportamento de uma determinada tarefa ou usar a função de API linsched_create_sleep_run para criar uma tarefa genérica suspensa/ocupada. É possível encontrar cada uma dessas tarefas em linux_linsched.c.

Listagem 1. Funções de API de criação de tarefas do LinSched
intlinsched_create_normal_task( struct task_data* td, int niceval );
void linsched_create_batch_task( struct task_data* td, int niceval );
void linsched_create_RTfifo_task( struct task_data* td, int prio );
void linsched_create_RTrr_task( struct task_data* td, int prio );
struct task_data *linsched_create_sleep_run( int sleep, int busy );

Por meio da API, também é possível criar grupos de tarefas, anexar tarefas a esses grupos e incluir compartilhamentos de processador nos grupos para programação de tarefas. A Listagem 2 fornece uma lista dessas funções (que se encontram em linux_linsched.c).

Listagem 2. Grupo de tarefas do LinSched e funções de API de compartilhamento de grupos
intlinsched_create_task_group( int parent_group_id );
void linsched_set_task_group_shares( int group_id, unsigned long shares );
int linsched_add_task_to_group( int task_id, int group_id );

Para começar uma simulação, você faz uma chamada a linsched_run_sim. O único argumento que essa chamada aceita é o número de ticks a serem executados. A cada tick, é criado o potencial para uma decisão de programação. Quando a simulação está concluída, a função retorna (essa função se encontra em hrtimer.c).

void linsched_run_sim( int sim_ticks );

Finalmente, é possível visualizar os resultados de uma simulação por meio das chamadas mostradas na Listagem 3. Essas chamadas emitem as estatísticas de tarefas individuais e estatísticas de grupo, respectivamente.

Listagem 3. Funções do LinSched para emitir estatísticas da simulação
void linsched_print_task_stats( void );
void linsched_print_group_stats( void );

Para fazer uma análise mais detalhada, também é possível capturar uma tarefa com base no ID do processador usando a seguinte função:

struct task_struct *linsched_get_task( int task_id );

Com a estrutura de tarefas, é possível encontrar o tempo total de execução da tarefa (com task_exec_time(task)), o tempo despendido sem executar (task->sched_info.run_delay) e o número de vezes que o scheduler chamou a tarefa (task->sched_info.pcount).

Nessa breve lista, é possível ver que o LinSched fornece uma API útil para desenvolver cenários de programação. Também é possível executar essas funções de forma iterativa para que, assim que um cenário tenha começado e terminado, novas tarefas possam ser incluídas e a simulação possa continuar por meio de outra chamada a linsched_run_sim. Essa funcionalidade permite a construção de cenários de programação dinâmica que também são passíveis de repetição.


Fazendo experiências com o LinSched

Agora que você explorou a API do mecanismo de simulação do LinSched, vamos dar uma olhada na API em ação. Nesse exemplo (mostrado na Listagem 4), eu usei o framework basic_test do LinSched para incluir um novo cenário. Nesse framework, o segundo argumento que é passado é a topologia a ser usada. Há um topo_db para fornecer as várias topologias suportadas (que o framework executa por meio de todas as opções disponíveis). Com a topologia definida, você chama linsched_init para inicializar o ambiente para essa topologia de processador. Em seguida, você cria 11 tarefas em três categorias. As cinco primeiras tarefas são criadas por meio de uma função create_tasks simples, que emula as tarefas ligadas ao processador (ocupado 90% do tempo, suspenso 10% do tempo). Em seguida, você cria cinco tarefas ligadas à entrada/saída (E/S) (ocupadas 10% do tempo, suspensas 90% do tempo). Finalmente, você cria uma tarefa em tempo real (com linsched_create_RTrr_task) que está ocupada 100% do tempo e tem prioridade 90. Em seguida, você inicia o simulador com uma chamada a linssched_run_sim e emitir resultados com linsched_print_task_stats.

Nota: esse exemplo usa o CFS padrão (como ele é chamado por meio de schedule() via linsched_run_sim).

Listagem 4. Script do LinSched de amostra
void new_test(int argc, char **argv)
{
  int count, mask;
  struct linsched_topology topo;
  int type = parse_topology(argv[2]);

  topo = topo_db[type];

  // Allow all tasks to use any processor.
  mask = (1 << count) - 1;

  // Initialize the topology as provided by the script interpreter
  linsched_init(&topo);

  // Create five processor-bound tasks (sleep 10, busy 90)
  create_tasks(5, mask, 10, 90);

  // Create five I/O-bound tasks (sleep 90, busy 10)
  create_tasks(5, mask, 90, 10);

  // Create a busy real-time round-robin task with a priority of 90
  linsched_create_RTrr_task( linsched_create_sleep_run(0,100), 90 );

  // Run the simulation
  linsched_run_sim(TEST_TICKS);

  // Emit the task statistics
  linsched_print_task_stats();

  return;
}

A execução desse cenário tem como resultado uma variedade de saídas para cada tarefa de uma determinada execução. Por exemplo: na Listagem 5, é possível ver a saída de uma execução do cenário (proveniente da Listagem 4) em uma topologia de uniprocessador. Essa saída mostra a lista de tarefas (numeradas pelo ID de tarefa), o tempo total de execução (em ticks), o tempo total de espera para a execução e. finalmente, a quantidade de vezes que foram chamadas. Observe que nunca ocorre a saída dessas tarefas, embora seja possível terminar uma tarefa por meio da API.

De acordo com esse cenário, as cinco primeiras tarefas são ocupadas e ficam suspensas 10% do tempo. O segundo conjunto de cinco tarefas fica suspenso a maior parte do tempo, e ocupado 10% do tempo. A última tarefa é uma tarefa em tempo real e fica ocupada 100% do tempo. Conforme foi mostrado, a tarefa em tempo real recebe a "parte do leão" do processador único e só é chamada 61 vezes. Compare isso com as tarefas ocupadas e não ocupadas que foram chamadas aproximadamente três vezes mais, usando muito menos o processador. Observe também que o scheduler é justo com as tarefas ocupadas e não ocupadas, dando-lhes aproximadamente a mesma quantidade de acesso ao processador.

Listagem 5. Programando um teste em uma topologia de uniprocessador
Task id =  1, exec_time =   305000000, run_delay = 59659000000, pcount = 156
Task id =  2, exec_time =   302000000, run_delay = 58680000000, pcount = 154
Task id =  3, exec_time =   304000000, run_delay = 58708000000, pcount = 155
Task id =  4, exec_time =   304000000, run_delay = 58708000000, pcount = 155
Task id =  5, exec_time =   304000000, run_delay = 58708000000, pcount = 155
Task id =  6, exec_time =   296000000, run_delay = 56118000000, pcount = 177
Task id =  7, exec_time =   296000000, run_delay = 56118000000, pcount = 177
Task id =  8, exec_time =   296000000, run_delay = 56118000000, pcount = 177
Task id =  9, exec_time =   296000000, run_delay = 56118000000, pcount = 177
Task id = 10, exec_time =   296000000, run_delay = 56118000000, pcount = 177
Task id = 11, exec_time = 57001000000, run_delay =  2998000000, pcount = 61

Agora, vamos ver o mesmo teste da Listagem 4 mas, dessa vez, em uma topologia com quatro soquetes e quatro núcleos (16 processadores lógicos). Já que cada tarefa pode ter o seu próprio processador lógico, recebe muito mais tempo de processador para a mesma duração do teste. Embora as tarefas ocupadas e não ocupadas sejam chamadas o mesmo número de vezes, as tarefas não ocupadas recebem 10% do tempo de execução, em comparação com as tarefas ocupadas. Essa diferença é resultado da configuração de suspenso/ocupado (as tarefas ocupadas executam durante 90 ticks, e as não ocupadas, durante 10 ticks). Também é interessante observar que a tarefa em tempo real é chamada uma vez e executa durante todo o teste (como ela nunca é suspensa, nunca foi reprogramada no processador). A Listagem 6 mostra o teste.

Listagem 6. Programando um teste em quatro núcleos e quatro soquetes
Task id =  1, exec_time = 54000000000, run_delay = 0, pcount = 601
Task id =  2, exec_time = 54000156250, run_delay = 0, pcount = 600
Task id =  3, exec_time = 54000281250, run_delay = 0, pcount = 600
Task id =  4, exec_time = 54000406250, run_delay = 0, pcount = 600
Task id =  5, exec_time = 54000031250, run_delay = 0, pcount = 600
Task id =  6, exec_time =  6000187500, run_delay = 0, pcount = 600
Task id =  7, exec_time =  6000312500, run_delay = 0, pcount = 600
Task id =  8, exec_time =  6000437500, run_delay = 0, pcount = 600
Task id =  9, exec_time =  6000062500, run_delay = 0, pcount = 600
Task id = 10, exec_time =  6000218750, run_delay = 0, pcount = 600
Task id = 11, exec_time = 59999343750, run_delay = 0, pcount = 1

Também é possível visualizar os dados emitidos a partir do LinSched. Vamos ver mais um exemplo com uma visualização gráfica da saída. No exemplo mostrado na Listagem 7, você cria 40 tarefas com valores nice variando entre -20 e 19. Lembre-se de que os valores nice das tarefas alteram a prioridade da mesma (onde -20 é a prioridade mais alta e 20 é a mais baixa). Na programação de tarefas normais, as tarefas recebem uma parte do processador que é proporcional ao valor nice.

Listagem 7. Demonstrando o efeito dos valores nice na programação de tarefas normais
void new_test(int argc, char **argv)
{
  int count, mask, i;
  struct linsched_topology topo;
  int type = parse_topology(argv[2]);

  topo = topo_db[type];

  // Allow all tasks to use any processor.
  mask = (1 << count) - 1;

  // Initialize the topology as provided by the script interpreter
  linsched_init(&topo);

  for (i = 0 ; i < 40 ; i++) {
    linsched_create_normal_task( linsched_create_sleep_run(0,100), i-20 );
  }

  // Run the simulation
  linsched_run_sim(TEST_TICKS*10);

  // Emit the task statistics
  linsched_print_task_stats();

  return;
}

O resultado desse aplicativo é representado na Figura 2 (para uma topologia de uniprocessador). Como foi mostrado, as tarefas de alta prioridade recebem a maior parte do processador, ao passo que as tarefas de baixa prioridade recebem muito menos, em uma curva exponencial. A tarefa de prioridade mais alta (valor nice de -20) recebeu aproximadamente 120 bilhões de ticks, ao passo que a tarefa de prioridade mais baixa (valor nice de 19) recebeu 21 milhões de ticks.

Figura 2. Plot dos tempos de execução para cada tarefa da Listagem 7
Plot dos tempos de execução para cada tarefa da Listagem 7

Outras opções de visualização de programação

Embora o LinSched seja exclusivo em relação ao recurso da simulação do scheduler no espaço do usuário, existem outras ferramentas para visualizar a programação do kernel e outras atividades. O Linux Trace Toolkit (LTT) cataloga eventos de sistema detalhadamente para fornecera visibilidade da operação interna do kernel Linux. Esse projeto avançou para o LTT next generation (LTTng). O LTTng fornece uma ferramenta de espaço do usuário para visualizar graficamente (ou em texto) a operação do kernel. Também é possível usar essa ferramenta para rastrear o espaço do usuário e para fazer o rastreio combinado, que agrega o rastreio do kernel e do espaço do usuário. Confira a seção Recursos para obter mais informações.


Indo além

A partir deste breve artigo, é possível ver o valor da simulação do scheduler do Linux no espaço do usuário. O trabalho com o LinSched detectou que a simulação do espaço do usuário e a programação real baseada no kernel apresentam uma correlação razoavelmente boa — portanto, essa abordagem é útil para prever o comportamento de um scheduler em produção. A abordagem que o LinSched usa também é interessante. Em vez de desenvolver um novo framework por meio do qual seria possível obter a programação no espaço do usuário, o LinSched usa o código do próprio kernel Linux (com wrappers para emulação de plataforma). Isso significa que, após validar o scheduler no espaço do usuário, é muito simples migrá-lo para o kernel para ser usado.

Confira Recursos para obter mais informações sobre o LinSched e outras ferramentas e tecnologias úteis para simular e visualizar scheduler.

Recursos

Aprender

  • LinSched, o Linux Scheduler Simulator, é um aplicativo no espaço do usuário que hospeda o subsistema de programação do Linux. É uma ferramenta extremamente útil para analisar o comportamento das políticas de programação do Linux. Também é possível ver a origem mais recente no github (um repositório de git para o LinSched).
  • Uma das melhores formas de conhecer melhor os detalhes do LinSched é o breve white paper escrito sobre a ferramenta, chamado LinSched: The Linux Scheduler Simulator. Esse documento fornece uma boa visão geral do LinSched e uma amostra de uso e simulação da carga de trabalho.
  • No início do desenvolvimento do kernel Linux 2.6, foi introduzido um novo scheduler para tomar o lugar do scheduler já existente (e complexo). Foi chamado de scheduler O(1) porque operava em um tempo constante, independentemente do número de tarefas a serem programadas. É possível saber mais sobre esse scheduler no Inside the Linux Scheduler (developerWorks, junho de 2006).
  • Depois do scheduler O(1), o CFS foi introduzido e adotado pelo kernel Linux. O CFS se baseia na ideia de que é necessário dar a todos os processos uma quantidade justa dos processadores disponíveis. Pode-se ver essa justiça no exemplo fornecido neste artigo, no qual se dá acesso ao processador a todos os processos — inclusive ao processo com prioridade mais baixa. É possível saber mais sobre o CFS no Inside the Linux 2.6 Completely Fair Scheduler (developerWorks, dezembro de 2009).
  • O Linux Trace Toolkit next generation (LTTng) fornece um recurso de visualização do espaço do usuário para rastrear as atividades do kernel e do espaço do usuário. Essa ferramenta é útil para entender o comportamento do sistema e pode ajudar a depurar problemas de software e de desempenho. Outro site útil é o Distributed Multi-Core Tracing Research Project, que desenvolve técnicas e algoritmos para rastrear sistemas multicore com o mínimo de sobrecarga.
  • Para saber mais sobre a programação, inclusive os algoritmos implementados no kernel Linux, confira a página Escalonamento de processos da Wikipédia. Esse texto trata da programação FIFO e round robin e fornece um breve resumo dos schedulers em cada um dos principais sistemas operacionais.
  • Na zona Linux do developerWorks, encontre vários artigos de instruções e tutoriais, bem como downloads, fóruns de discussão e muitos outros recursos para desenvolvedores e administradores Linux.
  • Fique por dentro dos eventos técnicos e webcasts do developerWorks com foco em uma variedade de produtos da IBM e tópicos do segmento de mercado de TI.
  • Participe de um briefing ao vivo e gratuito developerWorks para se atualizar rapidamente sobre produtos e ferramentas da IBM, bem como tendências do segmento de mercado de TI.
  • Assista a Demos on demand no developerWorks , que abrangem desde demos de instalação e configuração de produtos para iniciantes até funcionalidades avançadas para desenvolvedores experientes.
  • Siga o DeveloperWorks no Twitter, ou inscreva-se em um feed de Linux tweets no developerWorks.

Obter produtos e tecnologias

  • Avalie produtos IBM da maneira que for melhor para você: Faça o download da avaliação de um produto, experimente um produto on-line, use um produto em um ambiente de nuvem ou passe algumas horas no SOA Sandbox aprendendo como implementar Arquitetura Orientada a Serviços de forma eficiente.

Discutir

  • Participe da comunidade do My developerWorks . Conecte-se a outros usuários do developerWorks, ao mesmo tempo em que explora os blogs, fóruns, grupos e wikis direcionados a desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux
ArticleID=646937
ArticleTitle=Simulação do Linux Scheduler
publish-date=04122011