Baixe o app para aproveitar ainda mais
Prévia do material em texto
IF66C - Sistemas Operacionais Carlos N. Silla Jr., Ph.D. Aula baseada no material desenvolvido pelo Prof. Dr. Carlos A. Maziero Avaliações e Datas Importantes Atividade Data Peso 1ª Prova 17/12/2012 25% 1º Trabalho (Entrega, Apresentação e Defesa) 19/12/2012 25% 2ª Prova 15/04/2013 25% 2º Trabalho (Entrega, Apresentação e Defesa) 24/04/2012 25% Observações: • Não serão aceitos trabalhos entregues após as data estabelecidas. • Nota final = (NP1 + NP2 + NT1 + NT2) / 4 Onde: • NP1 = Nota da primeira prova. • NP2 = Nota da segunda prova. • NT1 = Nota do primeiro trabalho. • NT2 = Nota do segundo trabalho. O que é um Sistema Operacional? Sistema de Computação Típico Sistema de Computação Típico Abstração Gerência Abstração de Recursos Acessar os recursos de hardware de um sistema de computação pode ser uma tarefa complexa, devido às características específicas de cada dispositivo físico e a complexidade de suas interfaces. O sistema operacional deve definir interfaces abstratas para os recursos do hardware, visando atender os seguintes objetivos: Abstração de Recursos – 1º Objetivo Prover interfaces de acesso aos dispositivos, mais simples de usar que as interface de baixo nível, para simplificar a construção de programas aplicativos. Exemplo: Para ler dados de um disco rígido, uma aplicação usa um conceito chamado arquivo, que implementa uma visão abstrata do disco rígido, acessível através de operações como open, read e close. Caso tivesse de acessar o disco diretamente, teria de manipular portas de entrada/saída e registradores com comandos para o controlador de disco (sem falar na dificuldade de localizar os dados desejados dentro do disco). Alocação de Recursos – 2º Objetivo Tornar os aplicativos independentes do hardware. Ao definir uma interface abstrata de acesso a um dispositivo de hardware, o sistema operacional desacopla o hardware dos aplicativos e permite que ambos evoluam de forma mais autônoma. Exemplo: o código de um editor de textos não deve ser dependente da tecnologia de discos rígidos utilizada no sistema. Abstração de Recursos – 3º Objetivo Definir interfaces de acesso homogêneas para dispositivos com tecnologias distintas. Através de suas abstrações, o sistema operacional permite aos aplicativos usar a mesma interface para dispositivos diversos. Exemplo: um aplicativo acessa dados em disco através de arquivos e diretórios, sem precisar se preocupar com a estrutura real de armazenamento dos dados, que podem estar em um disquete, um disco IDE, uma máquina fotográfica digital conectada à porta USB, um CD ou mesmo um disco remoto, compartilhado através da rede. Gerência de Recursos Os programas aplicativos usam o hardware para atingir seus objetivos: ler e armazenar dados, editar e imprimir documentos, navegar na Internet, tocar música, etc. Em um sistema com várias atividades simultâneas, podem surgir conflitos no uso do hardware, quando dois ou mais aplicativos precisam dos mesmos recurso para poder executar. Cabe ao sistema operacional definir políticas para gerenciar o uso dos recursos de hardware pelos aplicativos, e resolver eventuais disputas e conflitos. Gerência de Recursos - Exemplos Vejamos algumas situações onde a gerência de recursos do hardware se faz necessária: Cada computador normalmente possui menos processadores que o número de tarefas em execução. Por isso, o uso desses processadores deve ser distribuído entre os aplicativos presentes no sistema, de forma que cada um deles possa executar na velocidade adequada para cumprir suas funções sem prejudicar os demais. O mesmo ocorre com a memória RAM, que deve ser distribuída de forma justa entre as aplicações. Gerência de Recursos - Exemplos A impressora é um recurso cujo acesso deve ser efetuado de forma mutuamente exclusiva (apenas um aplicativo por vez), para não ocorrer mistura de conteúdo nos documentos impressos. O sistema operacional resolve essa questão definindo uma fila de trabalhos a imprimir (print jobs) normalmente atendidos de forma sequencial (FIFO). Gerência de Recursos - Exemplos Ataques de negação de serviço (DoS – Denial of Service) são comuns na Internet. Eles consistem em usar diversas técnicas para forçar um servidor de rede a dedicar seus recursos a atender um determinado usuário, em detrimento dos demais. Por exemplo, ao abrir milhares de conexões simultâneas em um servidor de e-mail, um atacante pode reservar para si todos os recursos do servidor (processos, conexões de rede, memória e processador), fazendo com que os demais usuários não sejam mais atendidos. É responsabilidade do sistema operacional do servidor detectar tais situações e impedir que todos os recursos do sistema sejam monopolizados por um só usuário (ou um pequeno grupo). Gerência de Recursos Assim, um sistema operacional visa abstrair o acesso e gerenciar os recursos de hardware, provendo aos aplicativos um ambiente de execução abstrato, no qual o acesso aos recursos se faz através de interfaces simples, independentes das características e detalhes de baixo nível, e no qual os conflitos no uso do hardware são minimizados. Tipos de Sistemas Operacionais Batch (de lote); De rede; Distribuído; Multi-usuário; Desktop; Servidor; Embarcado; Tempo Real; Sistemas Operacionais de Lote Utilizados por S.O. antigos. Todos os programas a serem executados eram colocados em uma fila, com seus dados e demais informações para execução. O processador recebia os programas e os processava sem interagir com os usuários Exemplo de S.O. de lote: OS/360. Sistemas Operacionais de Rede Deve possuir suporte à operação em rede, ou seja, a capacidade de oferecer às aplicações locais recursos que estejam localizados em outros computadores da rede, como arquivos e impressoras. Ele também deve disponibilizar seus recursos locais aos demais computadores, de forma controlada. Atualmente a maioria dos sistemas operacionais oferece esse tipo de funcionalidade. Sistemas Operacionais Distribuídos Em um sistema operacional distribuído, os recursos de cada máquina estão disponíveis globalmente, de forma transparente aos usuários. Ao lançar uma aplicação, o usuário interage com sua janela, mas não sabe onde ela está executando ou armazenando seus arquivos: o sistema é quem decide, de forma transparente. Os sistemas operacionais distribuídos já existem há tempos, por exemplo: Amoeba [Tanenbaum et al., 1991]; Clouds [Dasgupta et al.,1991]; Ainda não são uma realidade de mercado. Sistemas Operacionais Multi-Usuários Um sistema operacional multi-usuário deve suportar a identificação do “dono” de cada recurso dentro do sistema (arquivos, processos, áreas de memória, conexões de rede) e impor regras de controle de acesso para impedir o uso desses recursos por usuários não autorizados. Essa funcionalidade é fundamental para a segurança dos sistemas operacionais de rede e distribuídos. Grande parte dos sistemas atuais são multi-usuários. Sistemas Operacionais Desktop Um sistema operacional “de mesa” é voltado ao atendimento do usuário doméstico e corporativo para a realização de atividades corriqueiras, como edição de textos e gráficos, navegação na Internet e reprodução de mídias simples. Suas principaiscaracterísticas são a interface gráfica, o suporte à interatividade e a operação em rede. Exemplos de sistemas desktop são os vários sistemas Windows (XP, Vista, 7, etc), o MacOS X e Linux. Sistemas Operacionais Servidores Um sistema operacional servidor deve permitir a gestão eficiente de grandes quantidades de recursos (disco, memória, processadores), impondo prioridades e limites sobre o uso dos recursos pelos usuários e seus aplicativos. Normalmente um sistema operacional servidor também tem suporte a rede e multi-usuários. Sistemas Operacionais Embarcados Um sistema operacional é dito embarcado (embutido) quando é construído para operar sobre um hardware com poucos recursos de processamento, armazenamento e energia. Aplicações típicas desse tipo de sistema aparecem em telefones celulares, sistemas de automação industrial e controladores automotivos, equipamentos eletrônicos de uso doméstico (leitores de DVD, TVs, fornos-micro-ondas, centrais de alarme, etc.). Sistemas Operacionais Embarcados Muitas vezes um sistema operacional embarcado se apresenta na forma de uma biblioteca a ser ligada ao programa da aplicação (que é fixa). LynxOS, C/OS, Xylinx e VxWorks são exemplos de sistemas operacionais embarcados para controle e automação. Sistemas operacionais para telefones celulares inteligentes (smartphones) incluem o Symbian e o Android, entre outros. Sistemas Operacionais de Tempo Real Ao contrário da concepção usual, um sistema operacional de tempo real não precisa ser necessariamente ultra-rápido; sua característica essencial é ter um comportamento temporal previsível (ou seja, seu tempo de resposta deve ser conhecido no melhor e pior caso de operação). A estrutura interna de um sistema operacional de tempo real deve ser construída de forma a minimizar esperas e latências imprevisíveis, como tempos de acesso a disco e sincronizações excessivas. Sistemas Operacionais de Tempo Real Existem duas classificações de sistemas de tempo real: Soft real-time systems, nos quais a perda de prazos implica na degradação do serviço prestado. Exemplo: Suporte à gravação de CDs ou à reprodução de músicas. Caso o sistema se atrase, pode ocorrer a perda da mídia em gravação ou falhas na música que está sendo tocada. hard real-time systems a perda de prazos pelo sistema pode perturbar o objeto controlado, com graves consequências humanas, econômicas ou ambientais Exemplo: Sistema responsável pelo controle de funcionamento de uma turbina de avião a jato ou de uma caldeira industrial. Sistemas Operacionais de Tempo Real Exemplos de sistemas de tempo real incluem o QNX, RT-Linux e VxWorks. Muitos sistemas embarcados têm características de tempo real, e vice-versa. Funcionalidades de um Sistema Operacional Para cumprir seus objetivos de abstração e gerência, o sistema operacional deve atuar em várias frentes. Cada um dos recursos do sistema possui suas particularidades, o que impõe exigências específicas para gerenciar e abstrair os mesmos. Sob esta perspectiva, as principais funcionalidades implementadas por um sistema operacional típico são: Funcionalidades de um Sistema Operacional – Gerência de Processador Também conhecida como gerência de processos ou de atividades, esta funcionalidade visa distribuir a capacidade de processamento de forma justa entre as aplicações, evitando que uma aplicação monopolize esse recurso e respeitando as prioridades dos usuários. O sistema operacional provê a ilusão de que existe um processador independente para cada tarefa, o que facilita o trabalho dos programadores de aplicações e permite a construção de sistemas mais interativos. Também faz parte da gerência de atividades fornecer abstrações para sincronizar atividades inter-dependentes e prover formas de comunicação entre elas. Funcionalidades de um Sistema Operacional – Gerência de Memória Tem como objetivo fornecer a cada aplicação uma área de memória própria, independente e isolada das demais aplicações e inclusive do núcleo do sistema. O isolamento das áreas de memória das aplicações melhora a estabilidade e segurança do sistema como um todo, pois impede aplicações com erros (ou aplicações maliciosas) de interferir no funcionamento das demais aplicações. Funcionalidades de um Sistema Operacional – Gerência de Memória Além disso, caso a memória RAM existente seja insuficiente para as aplicações, o sistema operacional pode aumentá-la de forma transparente às aplicações, usando o espaço disponível em um meio de armazenamento secundário (como um disco rígido). Uma importante abstração construída pela gerência de memória é a noção de memória virtual, que desvincula os endereços de memória vistos por cada aplicação dos endereços acessados pelo processador na memória RAM. Com isso, uma aplicação pode ser carregada em qualquer posição livre da memória, sem que seu programador tenha de se preocupar com os endereços de memória onde ela irá executar. Funcionalidades de um Sistema Operacional – Gerência de Dispositivos Cada periférico do computador possui suas peculiaridades; O procedimento de interação com uma placa de rede é completamente diferente da interação com um disco rígido SCSI. Todavia, existem muitos problemas e abordagens em comum para o acesso aos periféricos. Por exemplo, é possível criar uma abstração única para a maioria dos dispositivos de armazenamento como pen-drives, discos SCSI ou IDE, disquetes, etc, na forma de um vetor de blocos de dados. A função da gerência de dispositivos (também conhecida como gerência de entrada/saída) é implementar a interação com cada dispositivo por meio de drivers e criar modelos abstratos que permitam agrupar vários dispositivos distintos sob a mesma interface de acesso. Funcionalidades de um Sistema Operacional – Gerência de Arquivos Esta funcionalidade é construída sobre a gerência de dispositivos e visa criar arquivos e diretórios, definindo sua interface de acesso e as regras para seu uso. É importante observar que os conceitos abstratos de arquivo e diretório são tão importantes e difundidos que muitos sistemas operacionais os usam para permitir o acesso a recursos que nada tem a ver com armazenamento. Exemplos disso são as conexões de rede (nos sistemas UNIX e Windows, cada socket TCP é visto como um descritor de arquivo no qual pode-se ler ou escrever dados) e as informações do núcleo do sistema (como o diretório /proc do UNIX). Funcionalidades de um Sistema Operacional – Gerência de Proteção Com computadores conectados em rede e compartilhados por vários usuários, é importante definir claramente os recursos que cada usuário pode acessar, as formas de acesso permitidas (leitura, escrita, etc) e garantir que essas definições sejam cumpridas. Para proteger os recursos do sistema contra acessos indevidos, é necessário: a) definir usuários e grupos de usuários; b) identificar os usuários que se conectam ao sistema, através de procedimentos de autenticação; c) definir e aplicar regras de controle de acesso aos recursos, relacionando todos os usuários, recursos e formas de acesso e aplicando essas regras através de procedimentos de autorização; d) registrar o uso dos recursos pelos usuários, para fins de auditoria e contabilização. Outras Funcionalidades de um Sistema Operacional Além dessas funcionalidades básicas oferecidaspela maioria dos sistemas operacionais, várias outras vêm se agregar aos sistemas modernos, para cobrir aspectos complementares, como: A interface gráfica, Suporte de rede, Fluxos multimídia, Gerência de energia, etc. As funcionalidades do sistema operacional geralmente são inter-dependentes: por exemplo, a gerência do processador depende de aspectos da gerência de memória, assim como a gerência de memória depende da gerência de dispositivos e da gerência de proteção. Visão Geral das Funcionalidades do Sistema Operacional O núcleo central implementa o acesso de baixo nível ao hardware, enquanto os módulos externos representam as várias funcionalidades do sistema. Estrutura do Sistema Operacional Um sistema operacional não é um bloco único e fechado de software executando sobre o hardware. Na verdade, ele é composto de diversos componentes com objetivos e funcionalidades complementares. Alguns dos componentes mais relevantes de um sistema operacional típico são: Estrutura do Sistema Operacional Núcleo: é o coração do sistema operacional, responsável pela gerência dos recursos do hardware usados pelas aplicações. Ele também implementa as principais abstrações utilizadas pelos programas aplicativos. Drivers: módulos de código específicos para acessar os dispositivos físicos. Existe um driver para cada tipo de dispositivo, como discos rígidos IDE, SCSI, portas USB, placas de vídeo, etc. Muitas vezes o driver é construído pelo próprio fabricante do hardware e fornecido em forma compilada (em linguagem de máquina) para ser acoplado ao restante do sistema operacional. Estrutura do Sistema Operacional Código de inicialização: a inicialização do hardware requer uma série de tarefas complexas, como reconhecer os dispositivos instalados, testá-los e configurá-los adequadamente para seu uso posterior. Outra tarefa importante é carregar o núcleo do sistema operacional em memória e iniciar sua execução. Programas utilitários: são programas que facilitam o uso do sistema computacional, fornecendo funcionalidades complementares ao núcleo, como formatação de discos e mídias, configuração de dispositivos, manipulação de arquivos (mover, copiar, apagar), interpretador de comandos, terminal, interface gráfica, gerência de janelas, etc. Estrutura de um Sistema Operacional Introdução ao ambiente UNIX IF66C – Sistemas Operacionais Carlos N. Silla Jr., Ph.D. carlosjunior@utfpr.edu.br Aula baseada no material desenvolvido pelo Prof. Carlos A. Maziero Avisos Horário de permanência: Segunda – 20:20 até 21:10 Quarta – 13:50 até 15:30 Local de atendimento: Sala K006 Sessão de trabalho O uso de UNIX se baseia na noção de sessão de trabalho. Cada usuário é designado por um nome de login, ou simplesmente login, com uma senha secreta associada. Uma sessão de trabalho típica consiste das seguintes etapas: O usuário identifica-se, fornecendo seu nome de login e sua senha ao sistema. A sessão de trabalho inicia, com o lançamento do shell (modo texto) ou do ambiente (modo gráfico). Uso do sistema (lançamento de comandos e aplicações). Fim da sessão (operação de logout ou logoff). O UNIX pode gerenciar diversas sessões simultâneas de usuários distintos na mesma máquina. Cada um terá uma visão independente e transparente dos recursos disponíveis, sem conflitos ou interferências. O UNIX pode gerenciar diversas sessões simultâneas de usuários distintos na mesma máquina. Cada um terá uma visão independente e transparente dos recursos disponíveis, sem conflitos ou interferências. Interfaces gráficas No UNIX a interface gráfica é completamente separada do núcleo do sistema operacional. Isso permite uma grande versatilidade em relação aos ambientes gráficos disponíveis. A interface gráfica é construída em dois níveis: O servidor gráfico X-Window, que oferece as funcionalidades gráficas básicas, gerencia entidades básicas como regiões de tela e trata eventos relacionados à interface (como operações de mouse e teclado). O ambiente de trabalho, composto por vários processos, que implementam a decoração das janelas, menus, ícones, desktops virtuais, etc. Interfaces Gráficas Interfaces Gráficas Algumas características importantes diferenciam a arquitetura gráfica do UNIX daquela implantada em outros sistemas: O ambiente gráfico é implementado fora do núcleo. Com isso eventuais falhas na interface gráfica não comprometem a estabilidade do sistema. A comunicação entre o servidor gráfico, o ambiente e as aplicações é feita através de sockets TCP/IP, usando um protocolo especial chamado X-Protocol. Com isso é possível estabelecer conexões gráficas entre aplicações e servidores gráficos em máquinas separadas. Os processos que implementam o ambiente de trabalham são executados com o identificador do usuário (UID), com isso várias sessões gráficas distintas podem ser suportadas na mesma máquina, em displays distintos. Existem dezenas de possibilidades de ambientes gráficos distintos, à escolha do usuário. As aplicações gráficas irão executar sobre todos eles, sem necessidade de versões específicas para um ou outro ambiente. Documentação On-line O sistema UNIX implementa um sistema de documentação on- line simples, mas bastante útil e eficiente, chamado páginas de manual (man pages). As páginas de manual estão estruturadas em sessões: Sessão 1: Comandos do usuário. Sessão 2: Chamadas ao sistema operacional (em linguagem C) Sessão 3: Bibliotecas e funções standard (idem) Sessão 4: Descrição de dispositivos e formatos de arquivos de dados Sessão 5: Formato de arquivos de configuração Sessão 6: Jogos Sessão 7: Diversos Sessão 8: Comandos de administração do sistema O acesso às páginas de manual é normalmente efetuado através do comando man. Assim, man ls apresenta a página de manual do comando ls, enquanto man man apresenta a página de manual do próprio comando man. Usuários e grupos Cada usuário registrado possui um nome de login, uma senha e um identificador numérico associado (UID). Os usuários são organizados em grupos. Um usuário sempre pertence a um grupo primário e pode pertencer a outros grupos secundários. Cada grupo é identificado por um nome e um identificador de grupo (GID). O comando id user permite visualizar as informações de usuários e grupos. O comando finger user oferece informações adicionais sobre o usuário. A informação de usuário e grupo é usada pelo sistema para gerenciar o acesso aos recursos (arquivos e diretórios) e para a gerência dos processos de usuários distintos. O usuário root e outros usuários especiais O usuário com UID = 0 é chamado “root” e possui poderes especiais no sistema: Acesso a todos os arquivos e diretórios Reboot/shutdown do sistema Lançamento e cancelamento de qualquer processo Montagem de diretórios de rede e de dispositivos externos Assim, torna-se óbvio que a senha de root é de grande importância para a segurança do sistema. Além do root, outros usuários são definidos para a implantação de serviços específicos. Esse é o caso dos usuários “bin”, “daemon”,“lp”,“mail”, “news”, “ftp” e “nobody”, que não correspondem a seres humanos. Normalmente esses usuários não são acessíveis via login, existindo apenas internamente no sistema. O shell básico O shell é um programa que permite o uso do sistema através de uma interface em linha de comandos. Existem diversos estilos de shell, sendo os mais comuns o Bourne Shell (sh) e o C-Shell (csh). Apesar da interfaceem linha de comandos ser um conceito considerado antiquado, o shell oferece mecanismos para tornar a vida do usuário muito simples e produtiva. Além disso, é uma ferramenta de valor inestimável para operações em máquinas remotas. Características do sistema de arquivos UNIX É estruturado na forma de uma árvore única, iniciando pelo diretório ”/”, que é chamado de “raiz”. Há suporte para arquivos, diretórios e links (atalhos). Os arquivos podem ter qualquer nome, usando quaisquer caracteres, com distinção entre maiúsculas e minúsculas. Os nomes são normalmente limitados a 255 caracteres. O caractere separador de diretórios é o ”/” (barra). Arquivos e diretórios cujos nomes começam com “.” (ponto) são considerados “ocultos” e normalmente não aparecem nas listagens de diretórios. As extensões são normalmente usadas apenas para facilitar a vida do usuário, mas não são importantes para o sistema operacional, que não depende delas para identificar o conteúdo de um arquivo. Os arquivos e diretórios possuem permissões de acesso controláveis por seus proprietários. Principais diretórios Os diretórios de um sistema de arquivos UNIX têm uma estrutura pré-definida, com poucas variações. A seguir ilustramos os principais: /home: raiz dos diretórios home dos usuários. /boot: arquivos de boot (núcleo do sistema, etc) /var: arquivos variáveis, áreas de spool (impressão, e-mail, news), arquivos de log /etc: arquivos de configuração dos serviços /usr: aplicações voltadas aos usuários /tmp: arquivos temporários /mnt: montagem de diretórios compartilhados temporários /bin: aplicações de base para o sistema /dev: arquivos de acesso aos dispositivos físicos e conexões de rede /lib: bibliotecas básicas do sistema O diretório HOME Cada usuário possui um diretório especial, chamado “diretório home” (casa), onde são armazenados: arquivos e diretórios pessoais de trabalho e-mails já lidos (folders pessoais) arquivos de configuração individuais configuração das aplicações usadas O diretório home do usuário é o seu local de início de sessão de trabalho (via shell ou gráfica). O usuário possui plenos poderes de acesso ao seu diretório home (e seus sub- diretórios), e normalmente não pode criar arquivos fora dele. O diretório home de cada usuário é normalmente inacessível aos outros usuários, mas isso pode ser controlado pelo administrador do sistema (root). Comandos básicos Os comandos a seguir implementam operações básicas em arquivos: ls: listar o conteúdo do diretório corrente (ou de um diretório dado). rm: remover arquivos. mv: movimentar arquivos. cp: copiar arquivos. cat: apresentar o conteúdo de arquivos. more: visualizar o conteúdo de arquivos (paginado). ln: criar links (atalhos). Comandos básicos Os comandos usados para navegação na árvore de diretórios são similares aos usados em outros sistemas operacionais: “pwd” : indica qual o diretório corrente do shell. “cd” : troca de diretório: “cd “dir : muda para o diretório dir. “cd ..” : muda para o diretório pai imediatamente superior. “cd -“ : volta para o último diretório visitado. “cd ~user” : vai para o diretório HOME do usuário indicado. “cd” : volta ao diretório HOME. “mkdir” dir : criação do diretório dir. “rmdir” dir : remoção do diretório dir. Comandos avançados Os comandos abaixo são muito úteis na manipulação de arquivos: “grep” : permite procurar strings dentro de arquivos de texto. Exemplos: Procurar todas as linhas contendo 'tcsh' em /etc/passwd grep tcsh /etc/passwd Procurar todas as linhas que não contenham tcsh em /etc/passwd grep -v tcsh /etc/passwd Comandos avançados “find” : permite encontrar arquivos que satisfaçam certas características. Procurar todas as entradas “*txt” dentro do diretório /usr: find /usr -name '*txt' –print Procurar todas as entradas *ab* ou *cd* presentes em /opt: find /opt -iname '*ab*' -or -iname '*cd*„ Procurar todas as entradas acessadas a mais de 3 dias em /etc: find /etc -atime +3 Procurar todas as entradas modificadas a menos de 2 dias em /etc que tenham mais de 5 Kbytes de tamanho: find /etc -mtime -2 -and -size +5k Procurar todos os diretórios dentro de /opt cujo grupo tenha acesso em escrita: find /opt -type d -perm +g+w Comandos avançados “touch”: atualizar a data de um arquivo “diff”: comparar dois arquivos, mostrando as diferenças entre eles. Para maiores informações sobre as opções disponíveis para esses comandos, consulte as páginas de manual do sistema. Compressão de arquivos Tradicionalmente, a compressão de arquivos em UNIX é feita em dois passos: 1. Aglutinação dos arquivos e diretórios em um único grande arquivo, usando o comando tar. 2. Compressão do arquivo único, usando comandos como compress, gzip ou bzip2. O comando tar é bastante antigo, e significa Tape ARchiving (tar também é “piche” em inglês, o que sugere o processo de aglutinação). Ele era muito usado para copiar diretórios em fitas magnéticas. Com as opções adequadas, permite guardar diversos arquivos e diretórios em um único arquivo. Compressão de arquivos Sua sintaxe básica é: Para criar um arquivo ”.tar”: “tar cvf arq.tar dir1 dir2 dir3 …” Para abrir um arquivo ”.tar”: “tar xvf arq.tar” Para listar o conteúdo de um arquivo ”.tar”: “tar tvf arq.tar” Compressão de arquivos As principais opções do comando tar são: “c” : criar um novo arquivo ”.tar” com o nome indicado “x” : extrair dados do arquivo ”.tar” indicado “t” : listar o conteúdo do arquivo ”.tar”indicado “v” : verbose, mostra detalhes na tela sobre o que está sendo feito “f” : indica que o próximo parâmetro é o nome do arquivo ”.tar” a ser usado. Caso não seja indicado, é usado o conteúdo da variável $TAPE, ou o arquivo /dev/rst0 (fita magnética). “z” : para comprimir/expandir os arquivos tratados usando o gzip (ver abaixo). “Z” : para comprimir/expandir os arquivos tratados usando o compress (ver abaixo). Compressão de arquivos Após feita a aglutinação, pode-se compactar o arquivo usando-se um dos comando abaixo: “compress” : compactador standard do UNIX, hoje em dia pouco usado, mas presente em todas as plataformas. Gera arquivos com extensão ”.Z”. “gzip” : GNU-Zip, um compactador extremamente popular, é muito eficiente. Gera arquivos com extensão ”.gz”. “bz2” : De uso recente e ainda pouco difundido, certamente será muito usado nos próximos anos, por ser ainda mais eficiente que o gzip. Gera arquivos com extensão ”.bz2”. Compressão de arquivos Um procedimento muito usado é o uso combinado dos comandos tar e gzip, através das opções “z” e “Z” do comando tar. Assim, para obter um arquivo comprimido “corrente.tar.gz” com todo o conteúdo do diretório corrente, basta executar o seguinte comando: tar czvf corrente.tar.gz . (atenção ao ”.”, que indica o diretório corrente) Os arquivos ”.tar.gz” também costumam ser nomeado como ”.tgz”, e definem o formato da maior parte dos arquivos UNIX encontrados na Internet. Arquivos nesse formato também podem ser abertos pelas versões recentes do compactador WinZip, do Windows. Informações em arquivos Vários comandos permitem obter maiores informações sobre arquivos e sistemas de arquivos. Eis os principais: “stat” : detalhes sobre um arquivo ou diretório (i-nodes). stat /usr/bin/ls “file” : identificar o conteúdo de um arquivo, analisando-o. file /etc/* | more “whereis” : indica onde estão os binários, fontes e páginas de manual de um comando dado.whereis ls “which” : indica o caminho completo para o comando dado. which ls Informações em arquivos “du” : indica o espaço usado em disco pelos arquivos ou diretórios dados. du $HOME “df” : informações sobre os sistemas de arquivos disponíveis na máquina e sua ocupação. df “tree” : apresenta na tela uma estrutura de diretórios, com ou sem os arquivos. tree Permissões de acesso em arquivos O UNIX possui um sistema de controle de acesso ao sistema de arquivos seguindo o paradigma de Listas de Controle de Acesso (ACL - Access Control Lists). A cada arquivo ou diretório são associados: Um usuário proprietário (owner). Normalmente é quem criou o arquivo. Um grupo proprietário. Normalmente é o grupo primário de quem criou o arquivo, mas este pode mudá- lo para outro grupo do qual ele também faça parte. Permissões de acesso definidas para o usuário, o grupo e outros usuários (terceiros). Permissões de acesso em arquivos As permissões definidas para os arquivos são: Leitura, permitindo acesso ao conteúdo do arquivo. Escrita, permitindo modificar o conteúdo do arquivo. Execução, permitindo executar o arquivo (caso seja um executável ou script). As permissões definidas para os diretórios são similares: Leitura, permitindo acesso ao conteúdo do diretório (listar os arquivos presentes). Escrita, permitindo modificar o conteúdo do diretório (criar ou apagar arquivos). Execução, permitindo entrar no diretório, ou atravessá-lo. Pode-se afirmar que um arquivo é protegido contra leituras ou modificações por suas próprias permissões, e contra apagamentos ou renomeações pelas permissões do diretório onde ele se encontra. Consultando permissões As permissões de acesso a arquivos e diretórios podem ser consultadas através de uma listagem de diretório longa, usando o comando ls -l (ou seu alias ll). Permissões As entradas de diretório em um sistema UNIX têm seu tipo indicado pelo primeiro caractere da listagem de diretório longa. Os tipos de entradas mais freqüentes são: - : arquivo normal d : diretório l : link simbólico (atalho) b : dispositivo (mapeado em /dev/) orientado a blocos (como os discos rígidos) c : dispositivo (mapeado em /dev/) orientado a caracteres (como modems e portas seriais) s : socket mapeado em arquivo (para comunicação entre processos) p : FIFO ou Named Pipe (outro meio de comunicação entre processos) Permissões Os demais caracteres representam os direitos de acesso do usuário (user), do grupo (group) e de terceiros (others), em grupos de três caracteres: r : permissão de leitura (read). w : permissão de escrita (write). x : permissão de execução (eXecute). - : indica que o respectivo direito está negado. s : bits SUID e SGID setados (veremos mais tarde). Permissões - Exemplo -rw-r----- 1 silla users 4956 mar 26 20:34 descricao.html A linha de listagem acima indica que: A entrada corresponde a um arquivo normal (o primeiro caractere é -). O proprietário do arquivo descricao.html é o usuário silla. O proprietário possui direito de leitura e escrita sobre o arquivo, mas não de execução. O arquivo também pertence ao grupo users. O grupo possui apenas direito de leitura sobre o arquivo. Outros usuários (terceiros) não possuem nenhum direito de acesso ao arquivo. Exercícios (Entrega: 21/11/2012) 1. O comando ls permite obter listagens de diretórios sob várias formas. Consulte a página de manual do comando e execute-o de forma a obter listagens da seguinte forma: Listagem longa do diretório home, com detalhes. O que significa cada coluna da listagem ? Listagem curta do diretório home, incluindo os arquivos escondidos. Listagem longa de ”/var/spool/mail”, ordenada por tamanho dos arquivos Listagem longa de ”/etc”, ordenada alfabeticamente Listagem longa de ”/home”, ordenada por datas crescentes Listagem curta de ”/usr”, recursiva e ordenada por tamanho Exercícios (Entrega: 21/11/2012) 2. Use o comando find para encontrar todos os links simbólicos presentes em /usr. 3. O arquivo ”/var/log/messages “contém todos os logins recentes efetuados no sistema. Analise a estrutura do arquivo (usando o comando more); a seguir, use o comando grep para localizar os seus acessos. 4. Crie um arquivo .tar, com o conteúdo do seu diretório $HOME. A seguir, compacte-o usando os comando compress, gzip e bzip2, e compare os resultados (tamanho). IF66C - Sistemas Operacionais Introdução a Gerência de Tarefas Carlos N. Silla Jr., Ph.D. Aula baseada no material desenvolvido pelo Prof. Dr. Carlos A. Maziero Gerência de Tarefas Em um sistema de computação, é frequente a necessidade de executar várias tarefas distintas simultaneamente. Por exemplo: O usuário de um computador pessoal pode estar editando uma imagem, imprimindo um relatório, ouvindo música e trazendo da Internet um novo software, tudo ao mesmo tempo. Em um grande servidor de e-mails, centenas de usuários conectados remotamente enviam e recebem e-mails através da rede. Um navegador Web precisa buscar os elementos da página a exibir, analisar e renderizar o código HTML e o gráficos recebidos, animar os elementos da interface e responder aos comandos do usuário. Gerência de Tarefas No entanto, um processador convencional somente trata um fluxo de instruções de cada vez. Até mesmo computadores com vários processadores (máquinas Dual Pentium ou processadores com tecnologia hyper-threading, por exemplo) têm mais atividades a executar que o número de processadores disponíveis. Como fazer para atender simultaneamente as múltiplas necessidades de processamento dos usuários? Gerência de Tarefas Uma solução ingênua seria equipar o sistema com um processador para cada tarefa, mas essa solução ainda é inviável econômica e tecnicamente. Outra solução seria multiplexar o processador entre as várias tarefas que requerem processamento. Por multiplexar entendemos compartilhar o uso do processador entre as várias tarefas, de forma a atendê-las da melhor maneira possível. O Conceito de Tarefa Uma tarefa é definida como sendo a execução de um fluxo sequencial de instruções, construído para atender uma finalidade específica: Realizar um cálculo complexo; A edição de um gráfico; A formatação de um disco; etc; Assim a execução de instruções em linguagem de máquina, normalmente gerada pela compilação de um programa escrito em uma linguagem qualquer, é denominada “tarefa” ou “atividade” (do inglês task). Programa Vs. Tarefa Um programa é um conjunto de uma ou mais sequências de instruções escritas para resolver um problema específico, constituindo assim uma aplicação ou utilitário. O programa representa um conceito estático, sem um estado interno definido (que represente uma situação específica da execução) e sem interações com outras entidades (o usuário ou outros programas). Por exemplo, os arquivos “C:\Windows\notepad.exe” e “/usr/bin/nano” são programas de edição de texto. Programa Vs. Tarefa Uma tarefa é a execução, pelo processador, das sequências de instruções definidas em um programa para realizar seu objetivo. Trata-se de um conceito dinâmico, que possui um estado interno bem definido a cada instante (os valores das variáveis internas e a posição atual da execução) e interage com outras entidades: o usuário, os periféricos e/ou outras tarefas. Tarefas podem ser implementadas de várias formas, como processosou threads. Programa Vs. Tarefa - Analogia Fazendo uma analogia clássica, pode-se dizer que um programa é o equivalente de uma “receita de torta” dentro de um livro de receitas (um diretório) guardado em uma estante (um disco) na cozinha (o computador). Essa receita de torta define os ingredientes necessários e o modo de preparo da torta. Por sua vez, a ação de “executar” a receita, providenciando os ingredientes e seguindo os passos definidos na receita, é a tarefa propriamente dita. A cada momento, a cozinheira (o processador) está seguindo um passo da receita (posição da execução) e tem uma certa disposição dos ingredientes e utensílios em uso (as variáveis internas da tarefa). Programa Vs. Tarefa - Analogia Assim como uma receita de torta pode definir várias atividades inter-dependentes para elaborar a torta (preparar a massa, fazer o recheio, decorar, etc), um programa também pode definir várias sequências de execução inter-dependentes para atingir seus objetivos. Programa Vs. Tarefa - Analogia Programa Vs. Tarefa - Analogia Por exemplo, o programa do navegador Web define várias tarefas que uma janela de navegador deve executar simultaneamente, para que o usuário possa navegar na Internet: 1. Buscar via rede os vários elementos que compõem a página Web; 2. Receber, analisar e renderizar o código HTML e os gráficos recebidos; 3. Animar os diferentes elementos que compõem a interface do navegador; 4. Receber e tratar os eventos do usuário (clicks) nos botões do navegador; Programa Vs. Tarefa - Analogia Dessa forma, as tarefas definem as atividades a serem realizadas dentro do sistema de computação. Como geralmente há muito mais tarefas a realizar que processadores disponíveis, e as tarefas não têm todas a mesma importância, a gerência de tarefas tem uma grande importância dentro de um sistema operacional. Gerência de Tarefas Em um computador, o processador tem executar todas as tarefas submetidas pelos usuários. Essas tarefas geralmente têm comportamento, duração e importância distintas. Cabe ao sistema operacional organizar as tarefas para executá-las e decidir em que ordem fazê-lo. Sistemas Mono-Tarefa Os primeiros sistemas de computação, nos anos 40, executavam apenas uma tarefa de cada vez. Nestes sistemas, cada programa binário era carregado do disco para a memória e executado até sua conclusão. Os dados de entrada da tarefa eram carregados na memória e os resultados obtidos no processamento eram descarregados de volta no disco após a conclusão da tarefa. Sistemas Mono-Tarefa Todas as operações de transferência de código e dados entre o disco e a memória eram coordenados por um operador humano. Esses sistemas primitivos eram usados sobretudo para aplicações de cálculo numérico, muitas vezes com fins militares (problemas de trigonometria, balística, mecânica dos fluidos, etc). Sistemas Mono-Tarefa Sistemas Mono-Tarefa 1. Carga do código na memória, Sistemas Mono-Tarefa 2. Carga dos dados na memória. Sistemas Mono-Tarefa 3. Processamento, consumindo dados e produzindo resultados. Sistemas Mono-Tarefa 4. Ao término da execução, a descarga dos resultados no disco. Diagrama de Estados de Uma Tarefa em um Sistema Mono-Tarefas Sistemas Multi-Tarefa O uso do programa monitor agilizou o uso do processador, mas outros problemas persistiam. Como a velocidade de processamento era muito maior que a velocidade de comunicação com os dispositivos de entrada e saída , o processador ficava ocioso durante os períodos de transferência de informação entre disco e memória. Se a operação de entrada/saída envolvia fitas magnéticas, o processador podia ficar vários minutos parado, esperando. O custo dos computadores era elevado demais (e sua capacidade de processamento muito baixa) para permitir deixá-los ociosos por tanto tempo. Sistemas Multi-Tarefa Essa diferença de velocidades permanece imensa nos sistemas atuais. Por exemplo, em um computador atual a velocidade de acesso à memória é de cerca de 10 nanossegundos (10 X 10-9 s), enquanto a velocidade de acesso a dados em um disco rígido IDE é de cerca de 10 milissegundos (10 X 10-3 s), ou seja, um milhão de vezes mais lento. Sistemas Multi-Tarefa A solução encontrada para resolver esse problema foi permitir ao processador suspender a execução da tarefa que espera dados externos e passar a executar outra tarefa. Mais tarde, quando os dados de que necessita estiverem disponíveis, a tarefa suspensa pode ser retomada no ponto onde parou. Sistemas Multi-Tarefa Para tal, é necessário ter mais memória (para poder carregar mais de um programa ao mesmo tempo) e definir procedimentos para suspender uma tarefa e retomá-la mais tarde. O ato de retirar um recurso de uma tarefa (neste caso o recurso é o processador) é denominado preempção. Sistemas que implementam esse conceito são chamados sistemas preemptivos. Sistemas Multi-Tarefa A adoção da preempção levou a sistemas mais produtivos (e complexos), nos quais várias tarefas podiam estar em andamento simultaneamente: uma estava ativa e as demais suspensas, esperando dados externos ou outras condições. Sistemas que suportavam essa funcionalidade foram denominados monitores multi-tarefas. Sistemas Multi-Tarefa Sistemas de Tempo Compartilhado Solucionado o problema de evitar a ociosidade do processador, restavam no entanto vários outros problemas a resolver. Por exemplo, um programa que contém um laço infinito jamais encerra; como fazer para abortar a tarefa, ou ao menos transferir o controle ao monitor para que ele decida o que fazer? Sistemas de Tempo Compartilhado Situações como essa podem ocorrer a qualquer momento, por erros de programação ou intencionalmente, como mostra o exemplo: Sistemas de Tempo Compartilhado Esse tipo de programa podia inviabilizar o funcionamento do sistema, pois a tarefa em execução nunca termina nem solicita operações de entrada/saída, monopolizando o processador e impedindo a execução das demais tarefas (pois o controle nunca volta ao monitor). Além disso, essa solução não era adequada para a criação de aplicações interativas. Por exemplo, um terminal de comandos pode ser suspenso a cada leitura de teclado, perdendo o processador. Se ele tiver de esperar muito para voltar ao processador, a interatividade com o usuário fica prejudicada. Sistemas de Tempo Compartilhado Para resolver essa questão, foi introduzido no início dos anos 60 um novo conceito: O compartilhamento de tempo, ou time-sharing, através do sistema CTSS – Compatible TimeSharing System [Corbató, 1963]. Nessa solução, cada atividade que detém o processador recebe um limite de tempo de processamento, denominado quantum. Esgotado seu quantum, a tarefa em execução perde o processador e volta para uma fila de tarefas “prontas”, que estão na memória aguardando sua oportunidade de executar. Sistemas de Tempo Compartilhado Em um sistema operacional típico, a implementação da preempção por tempo tem como base as interrupções geradas pelo temporizador programável do hardware. Esse temporizador normalmente é programado para gerar interrupções em intervalos regulares (a cada milissegundo, por exemplo) que são recebidas por um tratador de interrupção (interrupt handler); asativações periódicas do tratador de interrupção são normalmente chamadas de ticks do relógio. Sistemas de Tempo Compartilhado Quando uma tarefa recebe o processador, o núcleo ajusta um contador de ticks que essa tarefa pode usar, ou seja, seu quantum é definido em número de ticks. A cada tick, o contador é decrementado; quando ele chegar a zero, a tarefa perde o processador e volta à fila de tarefas prontas. Diagrama de Estados de uma Tarefa em um Sistema de Tempo Compartilhado Ciclo de Vida das Tarefas O diagrama apresentado no slide anterior é conhecido na literatura da área como diagrama de ciclo de vida das tarefas. Os estados e transições do ciclo de vida têm o seguinte significado: Nova: A tarefa está sendo criada, i.e. seu código está sendo carregado em memória, junto com as bibliotecas necessárias, e as estruturas de dados do núcleo estão sendo atualizadas para permitir sua execução. Ciclo de Vida das Tarefas Pronta: A tarefa está em memória, pronta para executar (ou para continuar sua execução), apenas aguardando a disponibilidade do processador. Todas as tarefas prontas são organizadas em uma fila cuja ordem é determinada por algoritmos de escalonamento. Executando: O processador está dedicado à tarefa, executando suas instruções e fazendo avançar seu estado. Ciclo de Vida das Tarefas Suspensa : A tarefa não pode executar porque depende de dados externos ainda não disponíveis (do disco ou da rede, por exemplo), aguarda algum tipo de sincronização (o fim de outra tarefa ou a liberação de algum recurso compartilhado) ou simplesmente espera o tempo passar (em uma operação sleeping, por exemplo). Terminada : O processamento da tarefa foi encerrado e ela pode ser removida da memória do sistema. Transições entre os estados das tarefas ... Nova: Esta transição ocorre quando uma nova tarefa é admitida no sistema e começa a ser preparada para executar. Nova Pronta: ocorre quando a nova tarefa termina de ser carregada em memória, juntamente com suas bibliotecas e dados, estando pronta para executar. Pronta Executando: esta transição ocorre quando a tarefa é escolhida pelo escalonador para ser executada, dentre as demais tarefas prontas. Transições entre os estados das tarefas Executando Pronta: esta transição ocorre quando se esgota a fatia de tempo destinada à tarefa (ou seja, o fim do quantum); Como nesse momento a tarefa não precisa de outros recursos além do processador, ela volta à fila de tarefas prontas, para esperar novamente o processador. Executando Terminada: ocorre quando a tarefa encerra sua execução ou é abortada em consequência de algum erro (acesso inválido à memória, instrução ilegal, divisão por zero, etc). Na maioria dos sistemas a tarefa que deseja encerrar avisa o sistema operacional através de uma chamada de sistema (no Linux é usada a chamada exit). Transições entre os estados das tarefas Terminada ... : Uma tarefa terminada é removida da memória e seus registros e estruturas de controle no núcleo são apagadas. Executando Suspensa: caso a tarefa em execução solicite acesso a um recurso não disponível, como dados externos ou alguma sincronização, ela abandona o processador e fica suspensa até o recurso ficar disponível. Suspensa Pronta: quando o recurso solicitado pela tarefa se torna disponível, ela pode voltar a executar, portanto volta ao estado de pronta. Gestão de Processos em UNIX IF66C – Sistemas Operacionais Carlos N. Silla Jr., Ph.D. carlosjunior@utfpr.edu.br Aula baseada no material desenvolvido pelo Prof. Carlos A. Maziero Recapitulando Programas são arquivos em disco contendo instruções para execução pelo processador; Processos são as execuções em andamento. Cada processo executando no sistema em um determinado momento é identificado por um número único, o PID - Process IDentifier. Além do PID, cada processo possui outras informações que o caracterizam, como: Usuário proprietário (aquele que lançou o processo) Sessão de shell de onde foi lançado (se foi lançado através de um shell) Estado atual (Running, Suspended, Swapped, …) Linha de comando usada para lançá-lo. Uso de memória e CPU etc. Processos em Unix No UNIX, os seguintes comandos permitem observar a atividade dos processos no sistema: ps : permite listar todos os processos ativos no sistema. pstree : mostra as dependências entre processos. top : mostra a atividade do sistema, atualizando a tela a cada N segundos. Permite interagir com os processos do usuário que está executando o comando (tecle ”?” ou “h” para uma tela de ajuda ). free : apresenta informações gerais sobre uso de CPU e memória. vmstat : gera estatísticas sobre o uso de memória virtual, CPU, etc. renice : permite alterar a prioridade de base dos processos, que vai de -20 (máxima) a +20 (mínima), tendo como prioridade default o valor zero (0). Usuários normais só podem alterar as prioridades dos seus próprios processos, e só podem diminuir as prioridades. O comando ps Podemos visualizar os processos em execução no sistema através do comando ps, cuja execução sem parâmetros gera uma listagem como a seguinte: O comando ps aceita uma série de parâmetros, entre os quais os mais importantes são: a : mostra processos de outros usuários também (all). u : mostra listagem mais detalhada dos processos, com uso de memória e CPU x : mostra processos não conectados a terminais. w : mostra mais detalhes sobre as linhas de comando dos processos. O comando ps Para obter uma listagem completa dos processos em execução no sistema usam-se as opções auxw, que geram uma listagem como a que segue: O comando ps Os principais campos dessa listagem são: USER : o proprietário do processo, que pode ser quem o lançou ou, no caso de executáveis com o bit SUID habilitado, o proprietário do arquivo executável. PID : número do processo. %CPU : porcentagem da CPU usada pelo processo. %MEM : porcentagem da memória usada pelo processo. VSZ : memória total usada pelo processo. RSS : memória física (RAM) usada pelo processo. TTY : terminal ao qual o processo está ligado. STAT : status do processo (rodando, suspenso, …). START : data de lançamento do processo. TIME : tempo total de CPU usado pelo processo. COMMAND : comando usado para lançar o processo. O comando pstree O comando pstree é útil por mostrar a hierarquia existente entre os processos ativos no sistema: O comando top O comando top é uma versão iterativa do comando ps, atualizando a listagem de processos a cada n segundos, e ordenando-os por uso de CPU e memória. Ele é bastante útil para compreender o que está sendo processado pela máquina em um determinado instante. O comando top Background e foreground O shell pemite lançar processos a partir da linha de comando. Normalmente cada comando digitado é executado na forma de um processo, e o shell espera o término do processo lançado para devolver o controle ao usuário. Essa forma de operação é chamada foreground operation, e torna o shell inacessível até que o processo lançado seja terminado. Execução de Processos em Background Uma forma alternativa de lançamento de processos pelo shell é a chamada background operation, que consiste em lançar processos semperder o controle do shell. Para isso bastar adicionar o caractere & ao final da linha do shell. Dessa forma, o processo será lançado em background, e o shell permanecerá disponível ao usuário. Por exemplo, para lançar o mozilla firefox sem perder o controle do shell bastar digitar: O comando jobs O comando jobs permite verificar quais os processos em background lançados pelo shell corrente. Execução de Processos em Foreground As seguintes operações no shell são possíveis durante uma execução de processo em foreground : ^C : interrompe (mata) o processo, encerrando sua execução. ^Z : suspende o processo. um processo suspenso pode ser retornado à operação em foreground, através do comando fg (ou fg %job, quando houverem vários processos suspensos), ou transferido para operação em background, através do comando bg (ou bg %job, idem). O comando kill O comando kill -sinal pid permite enviar sinais aos processos em execução. Somente o proprietário do processo e o usuário root podem enviar sinais. Os sinais mais usados são os seguintes: 15 (TERM): solicita ao processo seu término. 9 (KILL): mata o processo, sem mais delongas. Para eliminar um processo que não responde mais a comandos e recusa-se a terminar, basta executar kill -9 pid onde pid corresponde ao número identificador do processo, obtido através dos comandos ps ou top. O comando at O comando at permite agendar a execução de um comando para uma hora e data definida pelo usuário. Os resultados (via stdout) das execuções agendadas serão enviados ao usuário por e-mail. Vejamos um exemplo: Shell:~$ at 23:59 12/31/2031 at> echo “Feliz 2032 a todo” | mail user@utfpr.edu.br at> who at> ^D O comando batch O comando batch permite agendar uma execução de comandos sem data marcada, assim que a carga do sistema o permitir. Da mesma forma que no comando at, eventuais resultados (stdout) das execuções são enviados ao usuário por e-mail. O sistema crontab Enquanto o comando at permite agendar uma tarefa para uma determinada data, o sistema crontab permite o agendamento de tarefas repetitivas ao longo do dia, semana, mês ou ano. Toda a informação sobre tarefas agendadas via crontab é mantida em um arquivo dentro do diretório /var/spool/cron, que não é diretamente acessível. O sistema crontab O acesso ao arquivo é feito pelo comando crontab: crontab -e : editar o arquivo com as definições de tarefas crontab -l : listar o conteúdo do arquivo atual crontab -r : remover o arquivo. A estrutura do arquivo do crontab é relativamente complexa mas permite muita flexibilidade. Mais informações podem ser obtidas via páginas de manual (man crontab para o comando e man 5 crontab para o arquivo de configuração). Exercícios (Entrega: 28/11/2012) Observações sobre a entrega dos exercícios: Deve ser gerado um relatório individual respondendo as questões deste atividade e explicando a cada etapa quais foram os comandos utilizados. Exercícios (Entrega: 28/11/2012) 1. Quais são os possíveis estados de um processo e como eles são representados na sua distribuição Linux? 2. Inicie o firefox utilizando o comando de background (&). Após o processo ser iniciado utilize ^C. Explique o que acontece com o processo que estava sendo executado. 3. Utilizando o comando & lance uma aplicação no linux. Utilize o comando jobs para verificar que ela esta executando em background. Saia do shell atual. Crie outro shell. Explique o que acontece ao utilizar o comando jobs nesse novo shell. Exercícios (Entrega: 28/11/2012) 4. Invoque o editor de textos nano e em seguida suspenda sua execução. Verifique através do comando jobs que o mesmo se encontra suspendo. Em seguida mude sua execução para background utilizando o comando apropriado. O que aconteceu? Realize o mesmo procedimento para o comando top. 5. Verifique quais os processos em atividade no sistema atualmente, identificando o uso de memória e CPU de cada um. Identifique o significado de cada uma das colunas da listagem obtida (ver a página de manual). Quais os processos que mais consomem recursos do sistema ? Exercícios (Entrega: 28/11/2012) 6. Efetue uma conexão SSH (Secure Shell) em um servidor. Do lado do cliente e do servidor, identifique os processos envolvidos no estabelecimento da conexão SSH e como eles se relacionam. 7. Você é o administrador de um sistema e precisa desconectar imediatamente todos os usuários conectados via SSH. Como você poderia fazer isso? 8. Como você Agendaria uma operação para remoção dos arquivos .bak do seu diretório HOME e sub-diretórios para as 23:55, todas as segundas, quartas e sextas-feiras? IF66C - Sistemas Operacionais Implementação de Tarefas Carlos N. Silla Jr., Ph.D. Aula baseada no material desenvolvido pelo Prof. Dr. Carlos A. Maziero Implementação de Tarefas Conforme apresentado, uma tarefa é uma unidade básica de atividade dentro de um sistema. Tarefas podem ser implementadas de várias formas, como processos, threads, jobs e transações. Nesta aula são descritos os problemas relacionados à implementação do conceito de tarefa em um sistema operacional típico. São descritas as estruturas de dados necessárias para representar uma tarefa e as operações necessárias para que o processador possa comutar de uma tarefa para outra de forma eficiente e transparente. Contextos Como visto anteriormente, uma tarefa possui um estado interno bem definido, que representa sua situação atual: a posição de código que ela está executando, os valores de suas variáveis e os arquivos que ela utiliza, por exemplo. Esse estado se modifica conforme a execução da tarefa evolui. O estado de uma tarefa em um determinado instante é denominado contexto. Contextos Uma parte importante do contexto de uma tarefa diz respeito ao estado interno do processador durante sua execução, como o valor do contador de programa (PC - Program Counter), do apontador de pilha (SP - Stack Pointer) e demais registradores. Além do estado interno do processador, o contexto de uma tarefa também inclui informações sobre os recursos usados por ela, como arquivos abertos, conexões de rede e semáforos. Contextos Cada tarefa presente no sistema possui um descritor associado, ou seja, uma estrutura de dados que a representa no núcleo. Nessa estrutura são armazenadas as informações relativas ao seu contexto e os demais dado necessários à sua gerência. Essa estrutura de dados é geralmente chamada de TCB (do inglês Task Control Block) ou PCB (Process Control Block). Task Control Block Um TCB tipicamente contém as seguintes informações: Identificador da tarefa (pode ser um número inteiro, um apontador, uma referência de objeto ou um identificador opaco); Estado da tarefa (nova, pronta, executando, suspensa, terminada, ...); Informações de contexto do processador (valores contidos nos registradores); Task Control Block Um TCB tipicamente contém as seguintes informações: Lista de áreas de memória usadas pela tarefa; Listas de arquivos abertos, conexões de rede e outros recursos usados pela tarefa (exclusivos ou compartilhados com outras tarefas); Informações de gerência e contabilização (prioridade, usuário proprietário, data de início,tempo de processamento já decorrido, volume de dados lidos/escritos, etc.). Trocas de Contexto A implementação da troca de contexto é uma operação delicada, envolvendo a manipulação de registradores e flags específicos de cada processador, sendo por essa razão geralmente codificada em linguagem de máquina. No Linux as operações de troca de contexto para a plataforma Intel x86 estão definidas através de diretivas em Assembly no arquivo arch/i386/kernel/process.c dos fontes do núcleo. Trocas de Contexto A implementação da troca de contexto é uma operação delicada, envolvendo a manipulação de registradores e flags específicos de cada processador, sendo por essa razão geralmente codificada em linguagem de máquina. No Linux as operações de troca de contexto para a plataforma Intel x86 estão definidas através de diretivas em Assembly no arquivo arch/i386/kernel/process.c dos fontes do núcleo. Trocas de Contexto Durante uma troca de contexto, existem questões de ordem mecânica e de ordem estratégica a serem resolvidas, o que traz à tona a separação entre mecanismos e políticas já discutida anteriormente. Por exemplo, o armazenamento e recuperação do contexto e a atualização das informações contidas no TCB de cada tarefa são aspectos mecânicos, providos por um conjunto de rotinas denominado despachante ou executivo (do inglês dispatcher). Trocas de Contexto Por outro lado, a escolha da próxima tarefa a receber o processador a cada troca de contexto é estratégica, podendo sofrer influências de diversos fatores, como as prioridades, os tempos de vida e os tempos de processamento restante de cada tarefa. Essa decisão fica a cargo de um componente de código denominado escalonador (scheduler). Assim, o despachante implementa os mecanismos da gerência de tarefas, enquanto o escalonador implementa suas políticas. Trocas de Contexto A realização de uma troca de contexto completa, envolvendo a interrupção de uma tarefa, o salvamento de seu contexto, o escalonamento e a reativação da tarefa escolhida, é uma operação relativamente rápida (de dezenas a centenas de micro-segundos, dependendo do hardware e do sistema operacional). A parte potencialmente mais demorada de uma troca de contexto é a execução do escalonador; por esta razão, muitos sistemas operacionais executam o escalonador apenas esporadicamente, quando há necessidade de reordenar a fila de tarefas prontas. Nesse caso, o despachante sempre ativa a primeira tarefa da fila. É importante observar que uma troca de contexto pode ser provocada pelo fim do quantum atual (através de uma interrupção de tempo), por um evento ocorrido em um periférico (também através de uma interrupção do hardware) ou pela execução de uma chamada de sistema pela tarefa corrente (ou seja, por uma interrupção de software) ou até mesmo por algum erro de execução que possa provocar uma exceção no processador. Processos Além de seu próprio código executável, cada tarefa ativa em um sistema de computação necessita de um conjunto de recursos para executar e cumprir seu objetivo. Entre esses recursos estão as áreas de memória usadas pela tarefa para armazenar seu código, dados e pilha, seus arquivos abertos, conexões de rede, etc. O conjunto dos recursos alocados a uma tarefa para sua execução é denominado processo. Processos Os sistemas operacionais convencionais atuais associam por default uma tarefa a cada processo, o que corresponde à execução de um programa sequencial (um único fluxo de instruções dentro do processo). Caso se deseje associar mais tarefas ao mesmo contexto (para construir o navegador Internet da figura 1, por exemplo), cabe ao desenvolvedor escrever o código necessário para tal. Processo como unidade de contexto Hoje em dia o processo deve ser visto como uma unidade de contexto, ou seja, um contêiner de recursos utilizados por uma ou mais tarefas para sua execução. Os processos são isolados entre si pelos mecanismos de proteção providos pelo hardware (isolamento de áreas de memória, níveis de operação e chamadas de sistema) e pela própria gerência de tarefas, que atribui os recursos aos processos (e não às tarefas), impedindo que uma tarefa em execução no processo pa acesse um recurso atribuído ao processo pb. Processos Processos O núcleo do sistema operacional mantém descritores de processos, denominados PCBs (Process Control Blocks), para armazenar as informações referentes aos processos ativos. Cada processo possui um identificador único no sistema, o PID – Process IDentifier. Associando-se tarefas a processos, o descritor (TCB) de cada tarefa pode ser bastante simplificado: para cada tarefa, basta armazenar seu identificador, os registradores do processador e uma referência ao processo ao qual a tarefa está vinculada. Disto observa-se também que a troca de contexto entre tarefas vinculadas ao mesmo processo é muito mais simples e rápida que entre tarefas vinculadas a processos distintos, pois somente os registradores do processador precisam ser salvos/restaurados (as áreas de memória e demais recursos são comuns às duas tarefas). Criação de Processos Durante a vida do sistema, processos são criados e destruídos. Essas operações são disponibilizadas às aplicações através de chamadas de sistema; cada sistema operacional tem suas próprias chamadas para a criação e remoção de processos. No caso do UNIX, processos são criados através da chamada de sistema fork, que cria uma réplica do processo solicitante: todo o espaço de memória do processo é replicado, incluindo o código da(s) tarefa(s) associada(s) e os descritores dos arquivos e demais recursos associados ao mesmo. Criação de Processos com Fork Criação de Processos com Fork A chamada de sistema fork é invocada por um processo (o pai), mas dois processos recebem seu retorno: o processo pai, que a invocou, e o processo filho, recém- criado, que possui o mesmo estado interno que o pai (ele também está aguardando o retorno da chamada de sistema). Ambos os processos têm os mesmos recursos associados, embora em áreas de memória distintas. Caso o processo filho deseje abandonar o fluxo de execução herdado do processo pai e executar outro código, poderá fazê-lo através da chamada de sistema execve. Essa chamada substitui o código do processo que a invoca pelo código executável contido em um arquivo informado como parâmetro. Processos A chamada de sistema exit usada no exemplo acima serve para informar ao núcleo do sistema operacional que o processo em questão não é mais necessário e pode ser destruído, liberando todos os recursos a ele associados (arquivos abertos, conexões de rede, áreas de memória, etc). Processos podem solicitar ao núcleo o encerramento de outros processos, mas essa operação só é aplicável a processos do mesmo usuário, ou se o processo solicitante pertencer ao administrador do sistema. Processos Na operação de criação de processos do UNIX aparece de maneira bastante clara a noção de hierarquia entre processos. À medida em que processos são criados, forma-se uma árvore de processos no sistema, que pode ser usada para gerenciar de forma coletiva os processos ligados à mesma aplicação ou à mesma sessão de trabalho de um usuário, pois irão constituir uma sub-árvore de processos. Processos Por exemplo, quando um processo encerra, seus filhos são informados sobreisso, e podem decidir se também encerram ou se continuam a executar. Por outro, nos sistemas Windows, todos os processos têm o mesmo nível hierárquico, não havendo distinção entre pais e filhos. O comando pstree do Linux permite visualizar a árvore de processos do sistema. Threads Conforme visto na Seção 4.3, os primeiros sistemas operacionais suportavam apenas uma tarefa por processo. À medida em que as aplicações se tornavam mais complexas, essa limitação se tornou um claro inconveniente. Por exemplo, um editor de textos geralmente executa tarefas simultâneas de edição, formatação, paginação e verificação ortográfica sobre a mesma massa de dados (o texto sob edição). Threads Da mesma forma, processos que implementam servidores de rede (de arquivos, bancos de dados, etc) devem gerenciar as conexões de vários usuários simultaneamente, que muitas vezes requisitam as mesmas informações. Essas demandas evidenciaram a necessidade de suportar mais de uma tarefa operando no mesmo contexto, ou seja, dentro do mesmo processo. Threads De forma geral, cada fluxo de execução do sistema, seja associado a um processo ou no interior do núcleo, é denominado thread. Threads executando dentro de um processo são chamados de threads de usuário (user-level threads ou simplesmente user threads). Cada thread de usuário corresponde a uma tarefa a ser executada dentro de um processo. Threads Por sua vez, os fluxos de execução reconhecidos e gerenciados pelo núcleo do sistema operacional são chamados de threads de núcleo (kernel-level threads ou kernel threads). Os threads de núcleo representam tarefas que o núcleo deve realizar. Essas tarefas podem corresponder à execução dos processos no espaço de usuário, ou a atividades internas do próprio núcleo, como drivers de dispositivos ou tarefas de gerência. Modelo de Threads N:1 Os sistemas operacionais mais antigos não ofereciam suporte a threads para a construção de aplicações. Sem poder contar com o sistema operacional, os desenvolvedores de aplicações contornaram o problema construindo bibliotecas que permitiam criar e gerenciar threads dentro de cada processo, sem o envolvimento do núcleo do sistema. Usando essas bibliotecas, uma aplicação pode lançar vários threads conforme sua necessidade, mas o núcleo do sistema irá sempre perceber (e gerenciar) apenas um fluxode execução dentro de cada processo. Por essa razão, esta forma de implementação de threads é nomeada Modelo de Threads N:1: N threads no processo, mapeados em um único thread de núcleo. Modelo de Threads N:1 O Modelo de Threads N:1 É muito utilizado, por ser leve e de fácil implementação. Como o núcleo somente considera uma thread, a carga de gerência imposta ao núcleo é pequena e não depende do número de threads dentro da aplicação. Essa característica este modelo torna útil na construção de aplicações que exijam muitos threads, como jogos ou simulações de grandes sistemas (a simulação detalhada do tráfego viário de uma cidade grande, por exemplo, pode exigir um thread para cada veículo, resultando em centenas de milhares ou mesmo milhões de threads). Um exemplo de implementação desse modelo é a biblioteca GNU Portable Threads [Engeschall, 2005]. O Modelo de Threads N:1 Entretanto, o modelo de threads N:1 apresenta problemas em algumas situações, sendo o mais grave deles relacionado às operações de entrada/saída. Como essas operações são intermediadas pelo núcleo, se um thread de usuário solicitar uma operação de E/S (recepção de um pacote de rede, por exemplo) o thread de núcleo correspondente será suspenso até a conclusão da operação, fazendo com que todos os threads de usuário associados ao processo parem de executar enquanto a operação não for concluída. O Modelo de Threads N:1 Outro problema desse modelo diz respeito à divisão de recursos entre as tarefas. O núcleo do sistema divide o tempo do processador entre os fluxos de execução que ele conhece e gerencia: as threads de núcleo. Assim, uma aplicação com 100 threads de usuário irá receber o mesmo tempo de processador que outra aplicação com apenas um thread (considerando que ambas as aplicações têm a mesma prioridade). Cada thread da primeira aplicação irá portanto receber 1/100 do tempo que recebe o thread único da segunda aplicação, o que não pode ser considerado uma divisão justa desse recurso. O Modelo de Threads 1:1 A necessidade de suportar aplicações com vários threads (multithreaded) levou os desenvolvedores de sistemas operacionais a incorporar a gerência dos threads de usuário ao núcleo do sistema. Para cada thread de usuário foi então definido um thread correspondente dentro do núcleo, suprimindo com isso a necessidade de bibliotecas de threads. Caso um thread de usuário solicite uma operação bloqueante (leitura de disco ou recepção de pacote de rede, por exemplo), somente seu respectivo thread de núcleo será suspenso, sem afetar os demais threads. O Modelo de Threads 1:1 Além disso, caso o hardware tenha mais de um processador, mais threads da mesma aplicação podem executar ao mesmo tempo, o que não era possível no modelo anterior. Essa forma de implementação, denominada Modelo de Threads 1:1, é a mais frequente nos sistemas operacionais atuais, incluindo o Windows NT e seus descendentes, além da maioria dos UNIXes. O Modelo de Threads 1:1 O Modelo de Threads 1:1 O modelo de threads 1:1 é adequado para a maioria da situações e atende bem às necessidades das aplicações interativas e servidores de rede. No entanto, é pouco escalável: a criação de um grande número de threads impõe um carga significativa ao núcleo do sistema, inviabilizando aplicações com muitas tarefas (como grandes servidores Web e simulações de grande porte). O Modelo de Threads N:M Para resolver o problema da escalabilidade, alguns sistemas operacionais implementam um modelo híbrido, que agrega características dos modelos anteriores. Nesse novo modelo, uma biblioteca gerencia um conjunto de threads de usuário (dentro do processo), que é mapeado em um ou mais threads do núcleo. O conjunto de threads de núcleo associados a um processo é geralmente composto de um thread para cada tarefa bloqueada e mais um thread para cada processador disponível, podendo ser ajustado dinamicamente conforme a necessidade da aplicação. Essa abordagem híbrida é denominada Modelo de Threads N:M, onde N threads de usuário são mapeados em M <= N threads de núcleo. O Modelo de Threads N:M O Modelo de Threads N:M O modelo N:M é implementado pelo Solaris e também pelo projeto KSE (KernelScheduled Entities) do FreeBSD [Evans and Elischer, 2003] baseado nas ideias apresentadas em [Anderson et al., 1992]. Ele alia as vantagens de maior interatividade do modelo 1:1 à maior escalabilidade do modelo N:1. Como desvantagens desta abordagem podem ser citadas sua complexidade de implementação e maior custo de gerência dos threads de núcleo, quando comparado ao modelo 1:1. A tabela 1 resume os principais aspectos dos três modelos de implementação de threads e faz um comparativo entre eles. Comparativo dos Modelos de Threads Threads No passado, cada sistema operacional definia sua própria interface para a criação de threads, o que levou a problemas de portabilidade das aplicações. Em 1995 foi definido o padrão IEEE POSIX 1003.1c,
Compartilhar