sábado, 18 de junho de 2011

Mulher dá flores à prefeita e bombas a jovens

Mulher que entregou flores à prefeita de Natal, Micarla de Sousa, em manifestação pró-Micarla em frente à prefeitura é a mesma que aparece em manifestação do Coletivo #ForaMicarla, supostamente coordenando jovens de menor idade para sabotarem uma das manifestações do povo com uso de bombas e faca.


Segundo relatam os populares a mesma é servidora em cargo comissionado na FUNCARTE e coordenou o polo Redinha do carnaval natalense de 2010.

segunda-feira, 13 de junho de 2011

Criação de triggers (gatilhos) com PL/SQL

Um DATABASE TRIGGER é um programa PL/SQL armazenado em um banco ORACLE, associado com uma tabela específica. O ORACLE irá disparar a execução do DATABASE TRIGGER automaticamente quando uma determinada operação SQL afeta a tabela.

Deste forma, pode-se usar um DATABASE TRIGGER para:

- Logar modificações
- garantir críticas complexas
- Gerar o valor de colunas
- Implementar níveis de segurança mais complexos
- Manter tabelas duplicadas

Pode-se associar até 12 DATABASE TRIGGERS a cada tabela, um de cada tipo (BEFORE UPDATE <row>, BEFORE DELETE <row>, BEFORE INSERT <row>, BEFORE INSERT <comando>, BEFORE UPDATE <comando>, BEFORE DELETE <comando> e as mesmas sintaxes para AFTER). Um DATABASE TRIGGER é composto de 3 partes:

- evento
- constraint (opcional)
- ação

Quando o evento ocorre, o trigger é disparado e um bloco PL/SQL "anônimo" executa a ação.

Deve-se observar que os DATABASE TRIGGERS executam com os privilégios do OWNER e não do usuário corrente.

sintaxe:

CREATE [OR REPLACE] TRIGGER <nome trigger>
{BEFORE | AFTER}
{DELETE | INSERT | UPDATE [OF <coluna>[,<coluna>]
          [OR DELETE | INSERT | UPDATE [OF <coluna>[,<coluna>]…}
ON <tabela>
[REFERENCING {OLD [AS] <nome> | NEW [AS] <nome> 
          [OLD [AS] <nome> | NEW [AS] <nome>]}
FOR EACH ROW [WHEN (<condição>)]] <bloco PL/SQL/>

Ex.:

CREATE TRIGGER checa_salario
          BEFORE UPDATE OF vl_sal, nr_git ON FUNC 
          FOR EACH ROW WHEN (NEW.nr_git < 56)
          DECLARE
                    salario_minimo NUMBER(5) := 0;
                    salario_maximo NUMBER(5) := 0;
                    faixa EXCEPTION;
                    negativo EXCEPTION;
                    excede EXCEPTION;
          BEGIN
                    SELECT MIN(vl_sal), MAX(vl_sal)
                    INTO salario_minimo, salario_maximo
                    FROM folha
                    WHERE nr_git = :new.nr_git;
                    IF (:NEW.vl_sal < salario_minimo OR
                    :NEW.vl_sal > salario_maximo)
                    THEN
                    RAISE faixa
                    ELSIF (:NEW.vl_sal < OLD.vl_sal)
                    THEN
                    RAISE negativo;
                    ELSIF (:New.vl_sal > 1.1 * :OLD.vl_sal)
                    THEN
                    RAISE excede;
                    END IF;
          EXCEPTION
          WHEN faixa THEN
                    RAISE_APPLICATION_ERROR(-20225, ‗Salário fora da faixa‘);
          WHEN negativo THEN
                    RAISE_APPLICATION_ERROR(-20230, ‗Incremento negativo‘);
          WHEN excede THEN
                    RAISE_APPLICATION_ERROR(-20235, ‗Incremento excede 10%‘);
          WHEN OTHERS THEN
                    RAISE_APPLICATION_ERROR(-20999, SQLERRM(SQLCODE));
          END;

quinta-feira, 9 de junho de 2011

Conceitos do SQL

Introdução

Uma linguagem de consulta é uma linguagem por meio da qual os usuários obtém informações do banco de dados. Essas linguagens são, tipicamente, de nível mais alto que as linguagens de programação tradicionais. As linguagens de consulta podem ser categorizadas como procedurais ou não-procedurais. Em uma  linguagem procedural,  o usuário deve "ensinar" ao sistema a realização de uma sequência de operações no banco de dados para obter o resultado desejado. Em uma linguagem não-procedural, o usuário descreve a informação desejada sem fornecer um procedimento específico para a obtenção dessas informações.

Os sistemas de banco de dados comerciais oferecem uma linguagem de consulta que incorpora elementos de ambos os enfoques: procedurais e não-procedurais.

Linguagens "puras": a álgebra relacional é procedural, enquanto o cálculo relacional de uma tupla e o cálculo relacional de um domínio são não-procedurais. Essas linguagens de consulta são concisas e formais, sem "o açúcar sintático" das linguagens comercias, mas ilustram as técnicas fundamentais para a extração de dados do banco de dados. 

A linguagem SQL

O nome "SQL" significa "Structured Query Language" - Linguagem Estruturada de Pesquisa. Essa linguagem, de grande utilização, teve seus fundamentos no modelo relacional de Codd (1970). Sua primeira versão recebeu o nome de SEQUEL ("Structured English Query Language"), sendo definida por D. D. Chamberlin, entre outros, em 1974, nos laboratórios de pesquisa da IBM (Califórnia). Em 1975, foi implementado um protótipo de aplicação dessa nova linguagem. Entre 1976 e 1977, o SEQUEL foi revisado e ampliado, e teve seu nome alterado para "SQL" por razões jurídicas.

Com esta revisão foi posto em prática um projeto ambicioso da IBM chamado System R. Novas alterações foram introduzidas na SQL, graças às idéias apresentadas pelos diversos usuários do ambiente.

Devido ao sucesso dessa nova forma de consulta e manipulação de dados dentro de um ambiente de banco de dados, a utilização da SQL foi se tornando cada vez maior. Com isso uma grande quantidade de SGBDs foi tendo como linguagem básica a SQL - SQL/DS e DB2 da IBM, PL/SQL da Oracle Corporation, RDB da Digital, SYBASE da Sybase INC, e Microsoft® SQL ServerTM, entre outros.

A SQL se tornou um padrão de fato no mundo dos ambientes de banco de dados relacionais. Bastava agora se tornar de direito. Então, em 1982, o American National Standard Institute (ANSI) tornou a SQL padrão oficial de linguagem em ambiente relacional.

Infelizmente, como todo padrão que se preze, existem hoje vários dialetos SQL, cada um, evidentemente, tentando ser mais padronizado que o outro.

O modelo relacional é constituído basicamente de tabelas, cada qual contendo linhas (registros, tuplas) e colunas. Os registros na tabela não são ordenados e sua localização se faz por meio de um campo-chave, ou seja, um campo que assume o papel de chave primária da tabela. É por intermédio dessa chave que se identifica uma, e somente uma, ocorrência do valor contido no campo.

Uma das razões da popularidade dos sistemas relacionais é a sua facilidade de manipulação e entendimento.

A linguagem SQL foi desenvolvida especialmente para o ambiente relacional, podendo ser adaptada a qualquer ambiente não relacional.


A idéia original da SQL só previa seu uso de forma interativa. Após sofrer alguns acréscimos, ela passou também a ter capacidade de ser utilizada em linguagens hospedeiras, tais como: COBOL, FORTRAN, "C", etc.

Atualmente, a linguagem SQL assume um papel muito importante nos sistemas de gerenciamento de bancos de dados, podendo ter muitos enfoques, como apresenta a figura: 
     • linguagem interativa de consulta (query AdHoc) - por meio de comandos SQL, os usuários podem montar consultas poderosas sem a necessidade da criação de um programa, podendo utilizar Forms ou ferramentas de montagem de relatório;
     • linguagem de programação para acesso a banco de dados - comandos SQL embutidos em programas de aplicação que acessam os dados armazenados;
     • linguagem de administração de banco de dados - o responsável pela administração do banco de dados (DBA) pode utilizar comandos SQL para realizar suas tarefas;
     • linguagem cliente/servidor - os programas (cliente) dos computadores pessoais usam comandos SQL para se comunicarem por meio de uma rede local, compartilhando os dados armazenados em um único local (servidor). A arquitetura cliente/servidor minimiza o tráfego de dados pela rede;
     • linguagem para banco de dados distribuído - a SQL auxilia na distribuição dos dados por meio de vários nós conectados ao sistema de computação. Auxilia também na comunicação de dados com outros sistemas;
     • caminho de acesso a outros bancos de dados em diferentes máquinas - a SQL auxilia na conversão entre diferentes produtos de banco de dados colocados em diferentes máquinas (de micro até mainframe).

Por ser uma linguagem de numerosas aplicações, a SQL pode manipular objetos de diferentes classes entre as funções de um SGBD:
     • definição de dados (DDL) - permite ao usuário a definição da estrutura e organização dos dados armazenados, e as relações que existem entre eles;
     • manipulação de dados (DML) - permite ao usuário, ou a um programa de aplicação, a inclusão, a remoção, a seleção e a atualização de dados previamente armazenados no banco;
     • controle de acesso - protege os dados de manipulações não autorizadas;
     • compartilhamento de dados - coordena o compartilhamento dos dados por usuários concorrentes, sem contudo interferir na ação de cada um deles;
     • integridade dos dados - auxilia no processo de definição da integridade dos dados, protegendo contra corrupções, inconsistências e falhas do sistema de computação.

Vantagens e desvantagens da linguagem SQL 

Com o uso e a padronização da SQL, algumas vantagens são diretas: 
     • independência de fabricante - a SQL é oferecida em praticamente todos os SGBDs, e os que ainda não a oferecem estão se encaminhando para fazê-lo. Com isso posso mudar de SGBD sem me preocupar com o novo que vai chegar;
     • portabilidade entre computadores - a SQL pode ser utilizada tanto em um computador pessoal, quanto em uma estação de trabalho ou até em um computador de grande porte;
     • redução dos custos com treinamento - baseado no item anterior, as aplicações podem se movimentar de um ambiente para o outro sem que seja necessária uma reciclagem da equipe de desenvolvimento;
     •  Inglês estruturado de alto nível - a SQL é formada por um conjunto bem simples de sentenças em Inglês, oferecendo um rápido e fácil entendimento;
     • consulta interativa - a SQL provê um acesso rápido aos dados, fornecendo respostas ao usuário de questões complexas, em minutos ou segundos; 
     • múltiplas visões dos dados - a SQL permite ao criador do banco de dados levar diferentes visões dos dados a diferentes usuários;
     • definição dinâmica dos dados - por meio da SQL, podem-se alterar, expandir ou incluir, dinamicamente, as estruturas dos dados armazenados com a máxima flexibilidade.

Apesar de todas essas vantagens, algumas críticas são dirigidas à SQL:
     • a padronização leva a uma, natural, inibição da criatividade, pois quem desenvolve aplicações fica preso a soluções padronizadas, não podendo aplicar melhorias ou alterações.

Mesmo enfrentando alguns problemas e algumas críticas, a linguagem SQL veio para ficar, auxiliando de forma bastante profunda a vida dos usuários e dos analistas no trabalho de manipulação dos dados armazenados em um banco de dados relacional.

      - Tabelas referentes ao modelo de dados;

Oracle – PL/SQL

Stored Procedures

Grupo de comandos SQL e PL/SQL que executam uma determinada tarefa. Uma stored procedure precisa ser chamada a partir de um programa ou ser executada manualmente pelo usuário. Uma stored procedure é totalmente portátil dentro das plataformas nas quais o Oracle é executado.

Uma stored procedure pode ser executada através das seguintes formas:
1- Através de uma ferramenta Oracle, como o SQL*PLUS;
2- Através de uma chamada explícita no código de uma aplicação de banco de dados, como o Oracle Forms;
3- Através de uma chamada explícita a partir de uma outra procedure ou trigger.

Uma stored procedure possui duas partes:
- Seção de especificação;
- Corpo da procedure.
Exemplo:
CREATE OR REPLACE PROCEDURE aumenta_sal (p_cod_fun number) IS
BEGIN
   UPDATE func SET vl_sal = vl_sal * 1.10 WHERE cod_fun = p_cod_fun;
   commit;
END aumenta_sal;

Cursor

Quando o Oracle processa um comando SQL, ele abre uma área de memória chamada Private SQL Area, que armazena informações responsáveis pela execução do comando. Um identificador para essa área – Chamado Cursor – é criado. No SQL*Plus para selecionar registros do banco de dados, basta um comando SELECT para que as linhas das tabelas ou visualizações que satisfaçam os critérios especificados sejam exibidas na tela.

Quando você usa o PL/SQL, um comando SELECT que retorna mais de uma linha, o Oracle exibe uma mensagem de erro que invoca a exceção TOO_MANY_ROWS. Para resolver esse problema, o Oracle usa um mecanismo chamado CURSOR.

Tipos de Cursor
Implícitos: O Oracle declara implicitamente um cursor para todos os comandos DDL e DML que retornam apenas uma linha.
Explícito: Para consultas que retornam múltiplas linhas e que são criados pelos usuários.

O conjunto de linhas retornadas por um cursor se chama result set (Conjunto de resultado). A linha que está sendo processada em um determinado momento é chamada current row(linha atual). Um cursor identifica a linha atual dentro do result set e permite o processamento individual de cada uma delas.

O Oracle usa quatro comandos para definir, abrir, acessar linhas e fechar um cursor. São eles: DECLARE, OPEN, FETCH E CLOSE. Um cursor pode ser visto como um arquivo temporário que armazena e controla as linhas retornadas por um comando SELECT. O SQL*PLUS gera automaticamente cursores para as consultas executadas. Já o PL/SQL, é necessário que o usuário crie cursores explícitos.

Criando um cursor

A criação de um cursor envolve quatro etapas:
1- Declaração do cursor. Nesta etapa, é criado um nome para o cursor e atribuído um comando SELECT a ele.
2- Abertura do cursor. Nessa etapa, a consulta é executada e é determinado o número de linhas que será retornado.
3- FETCHING. Na terceira etapa, as linhas encontradas são enviadas para o programa PL/SQL.
4- Fechamento do cursor. A última etapa libera os recursos do Oracle alocados para o cursor.
Exemplo prático:
create or replace procedure niva is
   c_nome_fun func.nome_fun%type;
   c_cod_fun func.cod_fun%type;
   c_vl_sal func.vl_sal%type;
   cursor teste1 is
      select nome_fun, cod_fun, vl_sal from func where vl_sal between 500 and 900 order by vl_sal;
      begin
         dbms_output.enable;
         open teste1;
         loop
            fetch teste1 into c_nome_fun,c_cod_fun,c_vl_sal;
            exit when teste1%notfound;
            dbms_output.put_line (c_nome_fun || '-' || to_char(c_cod_fun) || '-' || to_char(c_vl_sal));
         end loop;
   close teste1;
end;

Triggers

São rotinas ou procedures que são utilizados quando um comando INSERT, UPDATE ou DELETE é executado em uma tabela ou até mesmo numa visão. Um trigger é executado automaticamente sem a interferência do usuário. A principal aplicação de um trigger é a criação de consistências e restrições de acesso ao banco de dados, assim como rotinas de segurança.

Algumas Aplicações:
Criar o conteúdo de uma coluna derivada de outras colunas.
Criar mecanismos de validação que envolvam pesquisas em múltiplas tabelas.
Criar LOGS para registrar a utilização de uma tabela.
Atualizar outras tabelas em função de inclusão ou alteração da tabela atual.

Um trigger pode executar comandos contidos em seu bloco ou acionar as stored procedures para executar determinadas tarefas. Ele está associado a uma tabela, e em alguns casos, a uma visão. Quando uma visão é utilizada, os triggers da tabela base são normalmente acionados. Se uma tarefa puder ser feita tanto com triggers como com constraints, use a constraint como primeira opção.

Restrição de uso
Uma trigger não pode executar comandos COMMIT, ROLLBACK ou SAVEPOINT, nem tampouco chamar procedures ou funções que executam essas tarefas.
O comando SELECT pode ser usado apenas com a cláusula INTO.
Um trigger do tipo row-level não pode ler ou modificar o conteúdo de uma tabela em mutação.

Uma tabela mutante é aquela na qual seu conteúdo está sendo alterado por um comando INSERT, DELETE ou UPDATE e o comando não foi concluído, ou seja, ainda não foram gravados com COMMIT. O tamanho do trigger, ou seja, o texto dos comandos, não pode exceder 32 Kb. 
 
Tipos de trigger
1- Triggers de tabela aplicados aos comandos do tipo DML.
2- INSTEAD-OFF aplicados à visões.
3- SYSTEM EVENT aplicados no banco de dados nas operações de startup, shutdown e erro.
4- USER EVENT aplicado a um usuário ou objeto de esquema.
5- BEFORE e AFTER triggers.

Componentes de um trigger- Comando SQL que aciona o trigger: o disparo do trigger pode ser ocasionado pelo comando SQL ou por um evento do usuário.
- Limitador de Ação do Trigger: representado pela cláusula WHEN, especifica qual condição deve ser verdadeira para que o trigger seja disparado.
- Ação Executada pelo Trigger: é o bloco PL/SQL, Java ou rotina C que é executado pelo trigger.

Trigger de Tabela
Existem dois tipos distintos de triggers que podem ser usados em uma tabela. Um é executado apenas uma vez quando ocorre o evento de disparo e o outro é para cada linha da tabela processada pelo comando SQL.
- Statement-level Trigger: esse trigger é disparado apenas uma vez.
Por exemplo: Se um comando UPDATE atualizar 15 linhas, os comandos contidos no trigger serão executados uma única vez, e não em cada linha processada.
- Row-Level Trigger: esse trigger tem os seus comandos executados para todas as linhas que sejam afetadas pelo comando que gerou o acionamento do trigger.

Trigger do tipo INSTEAD-OFF
Oferecem uma maneira clara de alterar visões que não podem ser alteradas diretamente através de instruções SQL DML(INSERT, DELETE e UPDATE). 

Trigger de Eventos de Sistema
São disparados durante o startup ou shutdown do banco de dados e também por mensagens de erro.
Podem ser:
Startup – Disparados quando o banco de dados abre uma instância.
Shutdown – Disparados imediatamente antes do banco de dados iniciar o processo de shutdown.
Servererror – Disparados quando um erro específico ou um erro qualquer ocorre. 

Trigger de Eventos de Usuário
Os triggers de evento de usuário ocorrem quando o usuário faz seu logon, logoff ou executa comandos DML ou DDL.
LOGON – Dispara após a conexão do usuário.
LOGOFF – Dispara quando o usuário inicia sua desconexão.

Referências a Colunas
Dentro de um trigger do tipo row-level é possível acessar o valor de um campo de uma linha. Dependendo da operação que está sendo executada, é necessário preceder o nome da coluna com o sufixo :new ou :old, pois em um determinado instante pode-se obter tanto o valor antigo como o novo valor do campo.
Para um comando INSERT, os valores dos campos que  serão gravados devem ser precedidos pelo sufixo new.
Para um comando DELETE, os valores dos campos da linha que  está  processada devem ser precedidos pelo sufixo old.
Para um comando UPDATE, o valor original que está gravado é acessado com sufixo old. Os novos valores que serão gravados devem ser precedidos do sufixo new.
Os valores old e new estão disponíveis nos triggers do tipo BEFORE e AFTER.
Exemplos:
CREATE OR REPLACE TRIGGER t_pedidos BEFORE INSERT ON pedidos
Declare t_val char(30);
BEGIN
   t_val:= 'Parabéns Pelo Pedido';
   dbms_output.enable;
   dbms_output.put_line(t_val);
END;

CREATE OR REPLACE TRIGGER t_reduz_sal BEFORE UPDATE OF vl_sal ON func FOR EACH ROW when (new.vl_sal < old.vl_sal * 0.75)
BEGIN
   dbms_output.put_line('id = ' || :old.cod_fun);
   dbms_output.put_line('Old vl_sal = ' || :old.vl_sal);
   dbms_output.put_line('New vl_sal = ' || :new.vl_sal);
   dbms_output.put_line('A redução salarial é maior 25%');
   INSERT INTO auditoria (cod_fun, vl_sal_a, vl_sal_b) VALUES (:old.cod_fun, :old.vl_sal, :new.vl_sal);
END;

Packages
Um package é uma coleção  de objetos de banco de dados, como stored procedures, funções, variáveis, constantes e cursores. Ele contém subprogramas que podem ser chamados a partir de um trigger, uma procedure ou uma função. É um aliado do desenvolvedor, pois permite organizar melhor os componentes de um sistema em módulos. Além disso, a administração de privilégios é facilitada. Um package também melhora o desempenho da máquina, já que ele transfere para a memória diversos objetos de uma só vez.
Um package possui duas seções:
Especificação – Funciona como uma espécie de sumário do conteúdo do corpo do package. Nessa seção, são declarados os nomes de funções e stored procedures juntamente com os nomes de variáveis e constantes, incluindo  nesse último sua inicialização. A seção de especificação é criada com o comando CREATE PACKAGE.
Corpo – Nesta seção são declarados os objetos que farão parte do package e é criada com o comando CREATE PACKAGE BODY
Exemplo:
create package pk_teste is
   procedure aumenta_sal (p_cod_fun number);
   function f_func(f_vl_sal func.vl_sal%type) return number;
end;

create or replace package body pk_teste is
   PROCEDURE aumenta_sal (p_cod_fun number) IS
   BEGIN
      UPDATE func SET vl_sal = vl_sal * 1.10 WHERE cod_fun = p_cod_fun;
      commit;
   END aumenta_sal;
   function f_func (f_vl_sal func.vl_sal%type) return number is
      tot_ped number;
   begin
      select count(*) into tot_ped from func where vl_sal = f_vl_sal;
      return tot_ped; 
   end; 
end;

quarta-feira, 8 de junho de 2011

Abaixo assinado #ForaMicarla


IMPRIMA SUA PÁGINA AQUI E COMECE A RECOLHER AS ASSINATURAS AGORA MESMO.

ou assine/divulgue esse aqui! 

Segundo as instruções, precisamos apenas de 15 mil assinaturas para entrarmos com uma ação popular de impeachment da prefeita Micarla de Sousa.

O abaixo assinado foi reformulado hoje (08/06/2011).

quinta-feira, 26 de maio de 2011

Gerência de memória

Memória lógica e memória física

A memória lógica de um processo é aquela que o processo enxerga, ou seja, aquela que o processo é capaz de endereçar e acessar usando as suas instruções. Os endereços manipulados pelo process são endereços lógicos. Em outras palavras, as instruções de máquina de um processo especificam endereços lógicos. Por exemplo, um processo executando um programa escrito na linguagem C manipula variáveis tipo pointer. Essas variáveis contém endereços lógicos. Em geral, cada processo possui a sua memória lógica, que é independente da memória lógica dos outros processos.

A memória física é aquela implementada pelos circuitos integrados de memória, pela eletrônica do computador. O endereço físico é aquele que vai para a memória física, ou seja, é usado para endereçar os circuitos integrados de memória.

O espaço de endereçamento lógico de um processo é formado por todos os endereços lógicos que esse processo pode gerar. Existe um espaço de endereçamento lógico por processo. Já o espaço de endereçamento físico é formado por todos os endereços aceitos pelos circuitos integrados de memória.

A unidade de gerência de memória (Memory Management Unit, MMU) é o componente do hardware responsável por prover os mecanismos básicos que serão usados pelo sistema operacional para gerenciar a memória. Entre outras coisas, é a MMU que vai mapear os endereços lógicos gerados pelos processos nos correspondentes endereços físicos que serão enviados para a memória. Na verdade, o processador e a MMU formam, na maioria das vezes, um único circuito integrado. Podemos considerar os dois registradores de limite como uma MMU muito simples. 

  
Existe uma outra forma de MMU simples, onde o endereço lógico gerado pelo processo é primeiro comparado com um limite superior. Caso seja menor ou igual, ele então é somado ao valor do registrador de base. O resultado da soma é o endereço físico que vai para a memória. Nesse esquema, o endereço lógico é transformado em endereço físico através da soma do valor da base. Temos então o endereço lógico diferente do respectivo endereço físico.


Nesse esquema de MMU, o espaço de endereçamento lógico vai de zero até o valor limite. Esses são os endereços de memória manipulados pelo processo. O processo pode gerar endereços lógicos entre zero e 200. Qualquer valor fora desse intervalo será considerado ilegal. Os endereços lógicos são mapeados pela MMU para uma área do espaço de endereçamento físico. Essa área da memória física inicia no valor indicado pelo registrador de base e tem o mesmo tamanho da memória lógica do processo. A proteção de memória é conseguida, pois o processo de usuário está restrito a essa área da memória física.Tanto os registradores de limite inferior e superior quanto os registradores de base e limite devem ser protegidos. Eles não podem ser acessados em modo usuário. Obviamente, eles podem ser acessados em modo supervisor. Quando ocorre um chaveamento de processo, os valores são copiados do DP para os registradores da MMU.

Uma diferença entre as soluções apresentadas está na carga dos programas. No esquema que emprega apenas registradores de limite, os programas são gerados para o endereço zero da memória. Dessa forma, no momento da carga, os endereços dop programa devem ser corrigidos para que o programa execute corretamente no lugar onde foi colocado. Esse processo de correção de endereços é chamado relocação. Um carregador que efetua uma relocação do programa em tempo de carga é chamado de carregador relocador.

No esquema que emprega registradores de base e limite, todos os programas são também gerados para o endereço zero da memória. Entretanto, eles podem ser carregados em qualquer lugar da memória física.

Um carregador de programas que não precisa corrigir os endereços durante a carga é chamado de carregador absoluto. Nesse esquema, podemos considerar que ocorre uma relocação em tempo de execução, pois cada endereço sofre uma correção automática ao ser somado com o conteúdo do registrador de base.

Partições Fixas

Partições fixas são a forma mais simples de gerência de memória para multiprogramação. A memória é primeiramente dividida em uma parte para uso do SO e uma parte para uso dos processos de usuários. A seguir, a parte dos usuários é dividida em várias partições de tamanhos diferentes porém fixos.Quando um programa deve ser carregado, é escolhida uma partição ainda livre. Obviamente a partição deve ter um tamanho igual ou maior que o programa.

Existem, porém, dois problemas com esse tipo de gerência de memória. Dificilmente o programa a ser carregado terá o tamanho exato de uma partição. Ele será carregado em uma partição que é um pouco maior que o necessário. Isso resulta em um desperdício de memória que é chamado de fragmentação interna, isto é, memória perdida dentro da área alocada para um processo. Outra possibilidade é termos duas partições livres, digamos, de 25 e 100 kbytes. Nesse momento é criado um processo para executar um programa de 110 kbytes. Observe que a memória total livre no momento é de 125 Kbytes, mas ela não é contígua. O programa não pode ser executado devido à forma como a memória é gerenciada. Esse tipo de problema é chamado de fragmentação externa, isto é, memória perdida fora da área ocupada por um processo.

Partições variáveis

Quando variáveis são empregadas, o tamanho das partições é ajustado dinâmicamente às necessidades exatas dos processos. Essa é uma técnica de gerência de memória mais flexível que partições fixas.

O SO mantém uma lista de lacunas, ou seja, espaços livres na memória física que são percorridos quando um processo é criado.

Existem 4 formas básicas de percorrer a lista de lacunas atrás de uma lacuna de tamanho suficiente. Os algoritmos first-fit e circular fit são os mais usados.

• First-fit – utiliza a primeira lacuna que encontrar com tamanho suficiente
• Best-fit – utiliza a lacuna que resultar na menor sobra
• Worst-fit – utiliza a lacuna que resultar na maior sobra
• Circular-fit – Igual ao first-fit, mas inicia a procura na lacuna seguinte à última sobra.

Quando um processo termina, a memória que ele ocupava é liberada. Isso corresponde à criação de uma nova lacuna. Caso a nova lacuna criada seja adjacente a outras lacunas, elas são unificadas. 


Alguns sistemas organizam a memória por blocos de, por exemplo, 32 bytes. Esses blocos são muitas vezes chamados de parágrafos. A unidade de alocação passa a ser o parágrafo e o tamanho da área alocada por um processo deve ser um número inteiro de parágrafos, ou seja, um múltiplo exato de 32 bytes. Dessa forma, a menor lacuna possível terá o tamanho de um parágrafo ou 32 bytes. Nesse caso, poderemos ter uma fragmentação interna de até 31 bytes por processo. Em algumas arquiteturas, as variáveis do tipo inteiro devem ficar alinhadas corretamente na memória.

Partições variáveis são tipicamente implementadas através de uma lista encadeada de lacunas. Cada lacuna é representada por um descritor de lacuna, que contém basicamente o seu endereço, tamanho e apontadores para as colunas adjacentes. Como cada lacuna tem o tamanho mínimo de um parágrafo, ela pode hospedar o seu próprio descritor.

Com partições variáveis a fragmentação externa é um problema grave. Á medida que áreas de memória são alocadas e liberadas, muitos fragmentos são gerados. A memória adquire uma aparência de “queijo suíço”. É possível tentar usar compactação de memória para eliminar esse problema, mas em geral não é um processo muito usado.

Swapping

Existem situações nas quais não é possível manter todos os processos simultâneamente na memória.

Uma solução para essas situações é o mecanismo de swapping. Em determinadas situações, um processo é completamente copiado da memória para o disco. Sua execução é suspensa, ou seja, seu descritor de processo é removido da fila do processador e colocado em uma fila de processos suspensos. É dito que esse processo sofreu um swap-out. Mais tarde, ele sofrerá um swap-in, ou seja, será copiado novamente para a memória. Seu descritor de processo volta então para a fila do processador, e sua execução será retomada. O resultado desse revezamento no disco é que o SO consegue executar mais processos do que caberia em um mesmo instante na memória.

Em sistemas nos quais uma pessoa interage com o programa durante a sua execução, o mecanismo de swapping somente é utilizado em último caso, quando não é possível manter todos os processos na memória. A queda no desempenho do sistema é imediatamente sentida pelo usuário no terminal.

Paginação

A técnica de partições fixas gera muita perda de memória e não é mais utilizada na prática. Se essa restrição for eliminada, ou seja, permitir que um programa ocupasse áreas não contíguas de memória, não haveria fragmentação externa. A técnica da paginação possibilita exatamente isso.

O espaço de endereçamento lógico de um processo é dividido em páginas lógicas de tamanho fixo. O endereço lógico também é dividido em duas partes: um número de página lógica e um deslocamento dentro dessa página.

A memória física também é dividida em páginas físicas com tamanho fixo, idêntico ao tamanho da página lógica. Os endereços de memória física também podem ser vistos como compostos de duas partes. Os 3 primeiros bits indicam um número de página física. Os 2 últimos bits indicam um deslocamento dentro dessa página física.

Um programa é carregado página a página. Cada página lógica do processo ocupa exatamente uma página física da memória física. Entretanto, a área ocupada pelo processo na memória física não precisa ser contígua. Mais do que isso, a ordem em que as páginas lógicas aparecem na memória física pode ser qualquer, não precisa ser a mesma da memória lógica.

Durante a carga é montada uma tabela de páginas para o processo. Essa tabela informa, para cada página lógica, qual a página física correspondente. No exemplo, a tabela é formada por 3 entradas, uma vez que o processo possui 3 páginas lógicas.

Quando um processo executa, ele manipula endereços lógicos. O programa é escrito com a suposição que ele vai ocupar uma área contígua de memória, que inicia no endereço zero, ou seja, vai ocupar a memória lógica do processo. Para que o programa execute corretamente, é necessário transformar o endereço lógico especificado em cada instrução executada, no endereço físico correspondente. Isso é feito com o auxílio da tabela de páginas. 

  
O endereço lógico gerado é inicialmente dividido em duas partes: um número de página lógica e um deslocamento dentro da página. O número da página lógica é usado como índice no acesso à tabela de páginas. Cada entrada da tabela de páginas possui o mapeamento de página lógica para página física. Dessa forma, é obtido o número de página física correspondente. Já o deslocamento do byte dentro da página física será o mesmo deslocamento desse byte dentro da página lógica, pois cada página lógica é carregada exatamente em uma página física.

Na prática, os tamanhos de página variam entre 1K e 8Kbytes. Espaços de endereçamento lógico variam de 64K para sistemas antigos e muitos Gbytes nas máquinas atuais. Espaços de endereçamento físico também ficam, em geral, na ordem de Gbytes. Note que o espaço de endereçamento físico denota a capacidade de endereçamento do processador, e não a quantidade de memória realmente instalada na máquina.

Na paginação, uma página lógica pode ser carregada em qualquer página física que esteja livre, dessa forma não existe fragmentação externa.

Existem vantagens e desvantagens em utilizar páginas grandes. Páginas maiores significam que um processo terá menos páginas, a tabela de páginas será menor, a leitura do disco será mais eficiente. Em geral, páginas maiores resultam em um custo menor imposto pelo mecanismo de gerência de memória, ou seja, um overhead menor. Por outro lado, páginas maiores resultam em uma fragmentação interna maior. Normalmente não é o sistema operacional que escolhe o tamanho das páginas. Esse valor é fixado pelo hardware que suporta a gerência de memória, ou seja, pela MMU do computador em questão.

Quando a tabela de páginas é pequena, ela pode ser completamente colocada em registradores de acesso rápido.

Quando a tabela de páginas é muito grande, não é possível mantê-la em registradores. Uma outra solução é manter a tabela de páginas na própria memória. A MMU possui então dois registradores para localizar a tabela na memória. O registrador de base da tabela de páginas (page table base register, PTBR) indica o endereço físico de memória onde a tabela está colocada. O registrador de limite da tabela de páginas (page Table Limit Register, PTLR) indica o número de entradas da tabela. O problema desse mecanismo é que agora cada acesso que um processo faz à memória lógica transforma-se em dois acessos à memória física. No primeiro acesso, a tabela de páginas é consultada, e o endereço lógico é transformado em endereço físico. No segundo acesso, a memória do processo é lida ou escrita.

Uma forma de reduzir o tempo de acesso à memória no esquema anterior é adicionar uma memória cache especial que vai manter as entradas da tabela de páginas mais recentemente utilizadas. Essa memória cache interna à MMU é chamada normalmente de Translation Lookaside Buffer (TLB).

Normalmente, a memória cache é implementada através de um componente de hardware conhecido como memória associativa, que inclui algumas células de memória e toda eletrônica necessária para fazer uma pesquisa paralela, incluindo as células. O problema aí é o preço do hardware.

Quando a memória cache é usada e ocorre um chaveamento de processos, novamente os valores do PTBR e do PTLR para a tabela de páginas de processo que recebe o processador devem ser copiados do DP para os registradores na MMU. Além disso, a memória cache deve ser esvaziada (flushed).

É importante observar que a proteção entre processos é facilmente conseguida com uma MMU que suporte paginação. Em primeiro lugar, o mecanismo de paginação garante que cada processo somente tenha acesso às páginas físicas que constam em sua tabela de páginas. Essa tabela de páginas é construída pelo SO e fica em uma região da memória à qual apenas o SO tem acesso. O acesso aos registradores PTBR e PTLR é privilegiado, isto é, restrito ao código do SO, que executa em modo supervisor.

Em sistemas atuaias, a tabela de páginas pode ser muito grande. Assim sendo, é muito raro vê-la sendo totalmente usada. Na prática, as tabelas de páginas possuem um tamanho variável, ajustado à necessidade de cada processo. Ocorre que, se as tabelas puderem ter qualquer tamanho, então teremos fragmentação externa novamente (e a maior razão para usar paginação foi a eliminação da fragmentação externa).

Para evitar isso, são usadas tabelas com dois níveis. As tabelas de páginas crescem de pedaço em pedaço, e uma tabela auxiliar chamada diretório mantém o endereço de cada pedaço. Para evitar a fragmetação externa, cada pedaço da tabela de páginas deve ter um número inteiro de páginas físicas, mantendo assim toda alocação de memória física em termos de páginas, não importando a sua finalidade. Entradas desnecessárias em cada pedaço são marcadas como inválidas.

Segmentação

Programadores e compiladores não enxergam a memória lógica dividida em páginas, mas sim em segmentos. Uma divisão típica descreve um programa em termos de 4 segmentos: Código, dados alocados estaticamente, dados alocados dinamicamente e pilha e execução.

É possível orientar a gerência de memória para suportar diretamente o conceito de segmento. Nesse caso, a memória lógica do processo passa a ser organizada em termos de segmentos. Uma posição da memória lógica passa a ser endereçada por um número de segmento e um deslocamento em relação ao início do seu segmento. Em tempo de carga, cada segmento é copiado para a memória física, e uma tabela de segmentos é construída. Essa tabela informa, para cada segmento, qual o endereço da memória física onde ele foi colocado e qual seu tamanho. 


Os processos geram endereços lógicos compostos por um número de segmento e um deslocamento dentro do segmento. A MMU inicialmente utiliza o número de segmento fornecido para indexar a tabela de segmentos.

O grande atrativo da segmentação está na facilildade para compartilhar memória. Cada segmento representa uma parte específica do programa, podendo ou não ser compartilhado.

Por exemplo, suponha que o código das rotinas de biblioteca de uma linguagem de programação é compilado como sendo um segmento único. Esse segmento é marcado como “para apeas execução”, ou seja, não pode ser lido nem escrito. Todos os programas escritos nessa linguagem utilizam esse segmento. Entretanto, apenas uma cópia dele é necessária na memória física. Todos os processos executando programas escritos nessa linguagem terão em sua em sua respectiva tabela de segmentos uma referência à posição desse segmento na memória física.

Segmentação Paginada

Na segmentação paginada o espaço lógico é formado por segmentos, e cada segmento é dividido em páginas lógicas. Cada segmento possui uma tabela de páginas associada. No momento de endereçar a memória, a tabela de segmentos indica, para cada segmento, onde a respectiva tabela de páginas está. Essa tabela de páginas é usada para transformar o endereço de página lógica de determinado segmento em endereço de página física, como é feito normalmente na paginação. Sempre lembrando que este não é o único meio de trabalhar a segmentação paginada. Abaixo, vemos o esquema clássico de segmentação paginada. 


Servidores de redes de computadores

Em informática, um servidor é um sistema de computação que fornece serviços a uma rede de computadores. Esses serviços podem ser de diversa natureza, por exemplo, arquivos e correio eletrônico. Os computadores que acessam os serviços de um servidor são chamados clientes. As redes que utilizam servidores são do tipo cliente-servidor, utilizadas em redes de médio e grande porte (com muitas máquinas) e em redes onde a questão da segurança desempenha um papel de grande importância. O termo servidor é largamente aplicado a computadores completos, embora um servidor possa equivaler a um software ou a partes de um sistema computacional, ou até mesmo a uma máquina que não seja necessariamente um computador.

A história dos servidores tem, obviamente, a ver com as redes de computadores. Redes permitiam a comunicação entre diversos computadores, e, com o crescimento destas, surgiu a idéia de dedicar alguns computadores para prestar algum serviço à rede, enquanto outros se utilizariam destes serviços. Os servidores ficariam responsáveis pela primeira função.

Com o crescimento e desenvolvimento das redes, foi crescendo a necessidade das redes terem servidores e minicomputadores, o que acabou contribuindo para a diminuição do uso dos mainframes.

O crescimento das empresas de redes e o crescimento do uso da Internet entre profissionais e usuários comuns foi o grande impulso para o desenvolvimento e aperfeiçoamento de tecnologias para servidores.

Tipos de Servidores

Existem diversos tipos de servidores. Os mais conhecidos são:

Servidor de arquivos: Servidor que armazena arquivos de diversos usuários.

Servidor web: Servidor responsável pelo armazenamento de páginas de um determinado site, requisitados pelos clientes através de browsers.

Servidor de e-mail: Servidor responsável pelo armazenamento, envio e recebimento de mensagens de correio eletrônico.

Servidor de impressão: Servidor responsável por controlar pedidos de impressão de arquivos dos diversos clientes.

Servidor de banco de dados: Servidor que possui e manipula informações contidas em um banco de dados, como, por exemplo, um cadastro de usuários.

Servidor DNS: Servidores responsáveis pela conversão de endereços de sites em endereços IP e vice-versa. DNS é um acrônimo de Domain Name System, ou sistema de nomes de domínios.

Servidor proxy: Servidor que atua como um cache, armazenando páginas da internet recém-visitadas, aumentando a velocidade de carregamento destas páginas ao chamá-las novamente.

Servidor de imagens: Tipo especial de servidor de banco de dados, especializado em armazenar imagens digitais.

Os clientes e os servidores se comunicam através de protocolos, assim como dois ou mais computadores de redes.

Um computador, de repente, pode atuar em mais de um tipo diferente de servidor. Por exemplo, pode existir em uma rede, um computador que atue como um servidor web e servidor de banco de dados, por exemplo; ou um computador pode atuar como servidor de arquivos, de correio eletrônico e proxy ao mesmo tempo. Computadores que atuem como um único tipo de servidor é chamado de servidor dedicado. Os servidores dedicados possuem a vantagem de atender a uma requisição de um cliente mais rapidamente.

Com exceção do servidor de banco de dados (um tipo de servidor de aplicação), os demais servidores apenas armazenam informações, ficando por conta do cliente o processamento das informações. No servidor de aplicações, os papéis se invertem, com o cliente recebendo o resultado do processamento de dados da máquina servidora.

Em uma rede heterogênea (com diversos hardwares, softwares) um cliente também pode ser um servidor e assim um outro servidor pode ser cliente do mesmo. Por exemplo uma rede tem um servidor de impressão e um de arquivos, supondo que você está no servidor de arquivos e necessita imprimir uma folha de um documento que você está escrevendo, quando você mandar imprimir a folha o serviço do servidor de impressão será utilizado, e assim a máquina que você está usando, que é o servidor de arquivos, está sendo cliente do servidor de impressão, pois está utilizando de seu serviço.

Hardware e software de servidores

Hardware

Servidores dedicados, que possuem uma alta requisição de dados por partes dos clientes e que atuam em aplicações críticas utilizam hardware específico para servidores.

Já servidores que não possuam essas atuações podem utilizar hardware de um computador comum, não necessitando ser, de repente, um supercomputador.

Para começar, muitos servidores baseiam-se em entradas e saídas de informações (principalmente gravações e deleções de arquivos), o que implica em interfaces de entrada e saída e discos rígidos de alto desempenho e confiabilidade. O tipo de disco rígido mais utilizado possui o padrão SCSI, que permite a interligação de vários periféricos, dispostos em arranjos RAID.

Devido a operar com muitas entradas e saídas de informações, os servidores necessitam de processadores de alta velocidade, algumas vezes alguns servidores são multi-processados, ou seja, possuem mais de um processador.

Por ter de operar por muito tempo (as vezes de maneira ininterrupta), alguns servidores são ligados a geradores elétricos. Outros utilizam sistemas de alimentação (por exemplo, o UPS) que continuam a alimentar o servidor caso haja alguma queda de tensão.

E, por operar durante longos intervalos de tempos, e devido à existência de um ou mais processadores de alta velocidade, os servidores precisam de um eficiente sistema de dissipação de calor. O que implica em coolers mais caros, mais barulhentos, porém de maior eficiência e confiabilidade.

Existem outros hardware específicos para servidor, especialmente placas, do tipo hot swapping, que permite a troca destes enquanto o computador está ligado, o que é primordial para que a rede continue a operar.

PPPoE

PPPoE (Point-to-Point Protocol over Ethernet) é um protocolo para conexão de usuários em uma rede Ethernet a Internet. Seu uso é típico nas conexões de um ou múltiplos usuários em uma rede LAN à Internet através de uma linha DSL, de um dispositivo wireless (sem fio) ou de um modem de cabo broadband comum. O protocolo PPPoE deriva do protocolo PPP. O PPPoE estabelece a sessão e realiza a autenticação com o provedor de acesso a Internet.