Professional Documents
Culture Documents
Segundo Fernando Krahe1, as raízes do UNIX datam dos meados dos anos 60, quando a
AT&T, Honeywell, GE e o MIT embarcaram em um massivo projeto para desenvolvimento de um
utilitário de informação, chamado Multics (Multiplexed Information and Computing Service). O
sistema deveria ser multiusuário, com um sistema de arquivos de alta confiança, suporte a vários
tipos de aplicações, e a vários ambientes de programação e interfaces de usuário.
Em 1969, o projeto estava muito atrasado em relação ao seu cronograma e a AT&T resolveu
abandona-lo. O projeto continuou no MIT. Neste mesmo ano, Ken Thompson e Dennis Ritchie
decidiram desenvolver algumas idéias do Multics, eles reescreveram todo o sistema operacional
para um computador bem menos potente, um DEC PDP-7, de 4 kbytes de memória. Thompson
terminou o trabalho no verão de 1969, foi utilizada a linguagem BCPL (conhecida popularmente
como Linguagem B “assembly”), que contava com funções básicas: editor de texto, montador (ou
assembler, que transforma linguagem assembly em linguagem de máquina) e interpretador de
comandos (um Shell) neste período o sistema era chamado de Unics (UNiplexed Information and
Computing Service), numa alusão ao Multics, e foi logo rebatizado como Unix.
A primeira versão do sistema “BELL LABs PDP-11” foi lançada em 1º Janeiro de 1970, data
considerada como a de nascimento do sistema Unix, o que explica porque todos os relógios dos
sistemas de exploração Unix começam a partir desta data.
Em 1973 o UNIX foi reescrito em C, talvez o fato mais importante da história deste sistema
operacional. Isto significava que o UNIX poderia ser portado para novo hardware em meses, e que
mudanças eram fáceis. A linguagem C foi projetada para o sistema operacional UNIX, e portanto
há uma grande sinergia entre C e UNIX.
Como a lei impedia a empresa AT&T, e a Bell Labs, de comercializar outra coisa que não
equipamentos telefônicos ou telegráficos, tomo-se a decisão de distribuir os fontes de UNIX para
as universidades para fins educativos em 1973.
Em 1975 foi lançada a V6, que foi a primeira versão de UNIX amplamente disponível fora
dos domínios do Bell Labs, especialmente em universidades. Este foi o início da diversidade e
popularidade do UNIX. Nesta época na Universidade de Berkley os alunos começaram a fazer
modificações ao sistema.
Começaram a surgir novas versões, além da original da AT&T (rebatizada como System V);
a primeira foi desenvolvida na Universidade de Berkeley, denominado BSD (Berkeley Software
Distribution), liberada publicamente no final de 1977, precursor dos atuais e bem-sucedidos
BSD’s, (alguns anos depois com base no sistemas BSD surgiram novas “versões”, como o
freeBSD, netBSD e openBSD, que tinham o kernel baseado no sistema BSD).
Em 1979 saiu a V7 e o Unix foi portado para o novo VAX da Digital. Esta versão incluia C
K&R completo, uucp, Bourne Shell. O kernel tinha meramente 40 bytes! Esta foi a primeira versão
vendida comercialmente do sistema, mas usada principalmente por universidades. Em sua versão
7 de 1979, a evolução foi acompanhada de numerosas modificações notáveis como:
a supressão do bridage ligado à dimensão dos arquivos,
uma melhor mobilidade do sistema (funcionamento sobre numerosas plataformas
materiais),
a adição de numerosos utilitários.
Em 1983 é lançado o System V da AT&T e o 4.2 BSD. O SV incluía o pacote IPC (shm, msg,
sem) para comunicação entre processos. Surgiram outras versões do SV com a inclusão de novas
características como sharedlibs no SVR4. O 4.2BSD foi talvez uma das mais importantes versões
do UNIX. O seu software de conexão de redes tornava muito fácil a tarefa de conectar
computadores UNIX a redes locais. Nessa versão é que foram integrados os softwares que
implementam TCP/IP e sockets.
Tantas variedades de Unix surgindo a todo momento, com as mesmas características, mas
com tendências a se divergirem fez surgir então em 1985 o padrão POSIX (Portable Operating
System Interface for UniX), um conjunto de padrões definidos pelo IEEE(Institute of Electrical and
Electronics Engineers). POSIX assim é conhecido igualmente sob o nome IEEE P1003.
O POSIX não permitiu compatibilidade de rodar programas binários entre os vários Unix,
mas sim facilidade de portar um programa de um Unix para outros, através de compilação de
códigos-fonte em C.
Em 1988 foi lançado o SVR4. Este sistema era um merge de releazes anteriores do SV,
BSD e SunOs, uma implementação descendente de BSD. O 4.4BSD foi lançado em 1992 para
várias plataformas: HP 9000/300, Sparc, 386, DEC e outras, mas não em VAX. Entre as novas
características estão:
Novo sistema de memória virtual baseado em Mach 2.5
Suporte ISO/OSI (baseado em ISODE)
5
A Sun Microsystem também lançou a sua versão do UNIX a partir do BSD. Isto ocorreu até a
versão SunOs 4.x. A nova versão, SunOs 5.x está baseada no SVR4, embora tenha herdado
algumas características do SunOs 4.x. O novo sistema operacional da Sun, Solaris 2.x, é um SO
que engloba SunOs 5.x, Open Network Computing e Open Windows. É o solaris que provê o
pacote de compatibilidade entre os BSD/SunOs e o SVR4/SunOs 5.x.
A Microsoft também lançou uma versão do UNIX, chamada XENIX, que rodava em PCs.
Este sistema era inicialmente baseado na Versão 7, depois herdou características dos SIII e
depois do SV.
No início da década de 1990, a AT&T vendeu o código UNIX para a Novell. Em 1995, a
Novell vendeu parcialmente alguns dos direitos do código UNIX à Santa Cruz Operation. Em
2000, a Santa Cruz Operation vendeu o código UNIX para a Caldera Systems, que mudou seu
nome para SCO.
Atualmente, Unix (ou *nix) é o nome dado a uma grande família de Sistemas Operacionais
que partilham muitos dos conceitos dos Sistemas Unix originais, todos desenvolvidos sob a
plataforma de padrões como o POSIX e outros. Alguns dos Sistemas derivados do Unix são: BSD
(FreeBSD, OpenBSD e NetBSD), Solaris (anteriormente conhecido por SunOS), IRIX, AIX, HP-
UX, Tru64, Linux (nas suas centenas de distribuições), e até o Mac OS X (baseado em um kernel
Mach BSD chamado Darwin). Existem mais de quarenta sistemas operacionais *nix, rodando
desde celulares a supercomputadores, de relógios de pulso a sistemas de grande porte.
6
2. O Que é o UNIX?
Hoje em dia, os sistemas Unix estão presentes nos meios profissionais e universitários
graças à sua grande estabilidade, ao seu nível de segurança elevado e ao respeito dos grandes
padrões, nomeadamente em matéria de rede.
O Unix apresenta também como característica o seu sistema de arquivos. Tudo neste
sistema operacional é considerado um arquivo, até mesmo os dispositivos de I/O são tratados
como arquivo pelo sistema. Além do conceito de arquivos, outros conceitos presentes no sistema
são: processos, shell, diretórios e path.
2.1 Modularidade
O UNIX é único em seu desenho modular, que permite usuários adicionar ou remover partes
para adaptá-lo às suas necessidades específicas. Os módulos se encaixam com conexões-
padrão. É possível tirar um módulo e substituí-lo por um outro ou expandir o sistema
acrescentando vários módulos. De uma certa maneira, o sistema UNIX de cada pessoa é único.
Muitos usários acrescentam ou eliminam módulos sempre que precisam, adaptando suas
implementações às suas necessidades. Geralmente, é possível remover um módulo, sem
prejudicar a operação do resto do sistema. Esta característica é muito útil nas implementações em
microcomputadores, onde as unidades de disco têm capacidade limitada. A remoção de arquivos
desnecessários abre espaço para mais arquivos de dados.
A capacidade de multitasking do UNIX permite que mais de uma tarefa seja realizada
simultaneamente. Esta é uma das principais características do UNIX. As tarefas que estão em
execução concorrem pelos recursos da máquina que são controlados pelo sistema. É possível,
7
portanto, que um programa que atualize um banco de dados seja rodando ao mesmo tempo que a
impressão de um relatório esteja sendo realizada e uma tela de terminal esteja sendo enviada.
Em uma interface gráfica com um ambiente de janelas pode-se disparar cada tarefa em uma
janela shell. Já em um ambiente não gráfico, as tarefas que podem ser executadas sem a
intervenção do usuário são colocadas em background. Em foreground deixa-se as tarefas que
necessitam da intervenção do usuário, como a edição de um arquivo.
O Unix gerencia os pedidos que os usuários fazem, evitando a interferência de uns nos
outros. Cada usuário possui direitos de propriedade e permissões exclusivas sobre arquivos.
Quaisquer arquivos modificados pelo usuário conservarão esses direitos. Programas executados
por um usuário comum estarão limitados em termos de quais arquivos poderão acessar.
O sistema Unix possui dois tipos de usuários: o usuário root (também conhecido como
super-usuário), semelhante ao administrador do Windows, que possui a missão de administrar o
sistema, podendo manipular todos os recursos do sistema operacional; e os usuários comuns, que
possuem direitos limitados.
2.4 Portabilidade
O Unix Possui vários interpretadores de comandos (Shell) bem como um grande número de
comandos e numerosos utilitários (compiladores para numerosas linguagens, tratamentos de
texto, serviço de mensagens eletrônicas,etc). Também possui uma grande mobilidade, o que
permite sua instalação em quase todas as plataformas materiais.
No UNIX temos dois tipos de comunicações, quais sejam, comunicação entre programas e
comunicação entre usuários. A comunicação entre programas é realizada através de mensagens,
semáforos ou memória compartilhada. Estes mecanismos, também conhecidos por IPC,
interprocess comunications, são extensões do System V.
A comunicação entre usuários pode se realizar de diversas maneiras, entre elas há o Mail,
que é um programa para enviar e receber mensagens eletrônicas, o Write, que escreve uma
mensagem no terminal de outra pessoa logada no sistema, o Wall, que escreve mensagens nos
9
terminais de todas as pessoas logadas no sistema, o Talk, que permite uma conversa em tempo
real.
Há também a comunicação entre os sistemas, tais como UUCP (UNIX to UNIX Copy
Protocol).
10
3. Estrutura do UNIX
Aplicativos: são programas que podem ser invocados pelo Shell para realizar diversas
tarefas
2
Fonte da ilustração: http://www.cenapad.unicamp.br/servicos/treinamentos/tutorial_unix/unix_tutor-4.html
12
4. Shell
SHELL possui variáveis que armazenam informações sobre o sistema. Elas devem ser
inicializadas logo no início da sessão. Algumas variáveis são:
Cada utilizador possui um shell por padrão, que será lançado quando da abertura de uma
janela de comando. Por padrão, o Shell está no ficheiro de configuração /etc/passwd no último
campo da linha que corresponde ao utilizador. É possível alterar o shell numa sessão, executando
muito simplesmente o ficheiro executável correspondente, por exemplo:
/bin/bash
Por padrão, na maior parte dos shells, o prompt é composto pelo nome da máquina, seguido de
dois pontos (:), do directório corrente, seguidamente de um carácter que indica o tipo de utilizador
conectado :
Uma linha de comando é uma cadeia de caracteres constituída por uma comando,
correspondente a um arquivo executável do sistema ou um comando Shell, bem como os
argumentos (parâmetros) opcionais:
ls -al /home/jf/
No comando acima, ls é o nome do comando, - Al e /home/jf/ são argumentos. Os
argumentos que começam por “-“ designam-se opções. Para cada comando existem geralmente
diversas opções que podem ser detalhadas escrevendo um dos comandos seguintes:
commande --help
commande -?
man commande
No UNIX temos alguns arquivos que são executados todas as vezes que abrimos uma Shell,
ou quando inicializamos uma nova sessão. Estes arquivos são chamados de arquivos de
inicialização. Através deles, o usuário pode personalizar alguns comandos que mais utiliza,
colocando alguns 'apelidos' referentes a estes comandos, e/ou alterar o ambiente de trabalho da
sua própria conta.
Os arquivos, .login e .bash_profile são executados pelo Shell somente ao iniciar a sessão.
Estes arquivos devem conter comandos que precisam ser executados somente uma vez durante o
login. Os arquivos .cshrc e .bashrc são executados toda vez que uma nova cópia do Shell for
chamada.
Para exemplificar abaixo temos um arquivo .cshrc que contém 'apelidos' para alguns dos
comandos do UNIX. O usuário 'apelidou' o comando history de h. Assim, ao invés dele digitar
history, basta digitar h. Como esta alteração foi feita no arquivo .cshrc, este 'apelido' será válido
todas as vezes que ele abrir uma nova cópia do Shell.
# /etc/cshrc
# csh configuration for all shell invocations.
limit coredumpsize 0k
alias h history
alias l ls -lF
alias psa 'ps xua | more'
set history = 100
save history = 100
Após modificar os arquivos de inicialização, deve-se usar o comando source, para que as
modificações comecem a funcionar. Neste exemplo, temos:
% source .cshrc
7. Gerenciamento de arquivos
16
/var contém os arquivos de informação variável, que são alterados com freqüência.
Conforme texto do IME-USP3, no UNIX cada arquivo (inclusive diretórios, que são
casos particulares de arquivos), conta com um conjunto de atributos de leitura, escrita e
execução, que são setáveis através do comando chmod, e podem ser exibidos pelo
comando:
s-I:
$ Is –I /Bin/cat
-rwxr-xr-x 1root root 16584 Dec 16 20:09 /bin/cat
19
3
Unix: Conceitos e Comandos Básicos
Note que no UNIX não existem os atributos de arquivos ocultos(“hidden”) e do sistema
(“system”), suportados no MS-DOS. Não obstante, arquivos cujo primeiro caractere é ponto
(“.”) normalmente são omitidos pelo Is, a não ser que se utilize a opção –a (de “all”),
conforme comentamos no início.
No UNIX via de regra são suportados nomes “longos” (até 64 ou às vezes até 256
caracteres), e o “.” Não é um separador entre o nome e a extensão do arquivo, mas um
caractere como os outros. Não obstante, a noção de “sufixo” é utilizada informalmente para
facilitar a identificação de alguns formatos de arquivos, por exemplo:
.tar Archive produzido com tar
.zip Archive comprimido produzido com zip
.Z Archive comprimido com compress
.gz Archive comprimido com gzip
Por ser multitarefa, o Unix utiliza uma estrutura chamada tabela de processos, que
contém informações sobre cada processo, tais como: identificação do processo (PID), dono,
área de memória utilizada, estado (status).
Existem quatro chamadas de sistema principais associadas a processos: fork, exec, exit e
wait;
Fork é usada para criar um novo processo, que irá executar o mesmo código (programa)
do programa chamador (processo-pai);
Exec irá determinar o código a ser executado pelo processo chamado (processo-filho);
Exit termina o processo;
Wait faz a sincronização entre a finalização do processo-filho e o processo-pai.
Todo processo tem uma fase de usuário e uma fase de sistema. Boa parte do trabalho
é feito no modo usuário, mas, quando uma chamada ao sistema é feita, ela é realizada no
modo de sistema. As fases nunca executam ao mesmo tempo.
Quando um processo está executando em modo sistema, uma pilha de kernel para
esse processo é usada, em vez da pilha de usuário que pertence a esse processo. A pilha
de kernel e a estrutura de usuário juntas compõem o segmento de dados do sistema para o
processo.
A chamada ao sistema fork aloca uma nova estrutura de processo (com novo
identificador de processo) para o processo filho, e copia a estrutura de usuário. Não há a
necessidade de uma nova estrutura de texto, os processos compartilham seu texto.
Contadores e listas apropriados são simples segmentos de dados e de pilha do processo
filho. Já a chamada ao sistema vfork não copia os dados e a pilha para o novo processo, em
vez disso, o novo processo simplesmente compartilha a tabela de página do processo
anterior. Uma nova estrutura de usuário e de processo são criadas.
Quando o processo pai é grande, vfork pode gerar economias substanciais de tempo
de CPU do sistema. No entanto, é uma chamada ao sistema consideravelmente perigosa, já
que qualquer mudança na memória ocorre nos dois processos até que execve ocorra. A
chamada ao sistema execve não cria um novo processo ou uma nova estrutura de usuário.
23
O texto e os dados do processo são substituídos. Os arquivos abertos são preservados,
bem como a maioria das propriedades de tratamento de sinais.
Quanto mais tempo de CPU um processo acumula, menor (ou mais positiva) se torna
a sua prioridade, e vice-versa. Assim, existe um feedback negativo no escalonamento de
CPU e é difícil para um único processo usar todo o tempo da CPU. O envelhecimento de
processos é usado para evitar paralisação.
Não existe preempção de um processo por outro dentro do kernel. Um processo pode
abandonar a CPU porque está esperando por I/O ou porque sua fatia de tempo expirou.
Quando um processo escolhe abandonar a CPU, ele é suspenso em um evento. A
experiência sugere que o escalonador UNIX tem melhor desempenho com jobs limitados por
I/O, como pode ser observado quando existem vários Jobs limitados por CPU em execução.
9. MEMÓRIA E GERENCIAMENTO
O sistema implementa uma variação do algoritmo FIFO (First In First Out) circular
como política de substituição de páginas. Esse algoritmo, conhecido como Two-Handed
Clock, utiliza dois ponteiros, ao contrário do FIFO circular, que implementa apenas um. O
primeiro ponteiro fica à frente do segundo um certo número de frames na lista de páginas
em uso. Enquanto o primeiro ponteiro desliga o bit de referência das páginas, o segundo
verifica o seu estado. Se o bit de referencia continuar desligado, significa que a página não
25
foi referenciada desde o momento em que o primeiro ponteiro desligou o bit, fazendo com
que essa página seja selecionada.
10. Deadlocks
Deadlock é "Uma ocorrência em que cada processo do conjunto esta esperando por
um evento que somente outro processo pertencente ao conjunto poderá fazer acontecer."
Ressalta que a maior parte das situações de deadlock envolve a espera por recursos e que,
pela definição, nenhum processo do conjunto poderá evitar que todos os processos do
conjunto fiquem eternamente bloqueados.
Condição de posse e espera, basta requerer que todos os processos solicitem os seus
recursos antes de iniciar a execução. No entanto, um processo nunca tem que esperar
por aquilo que precisa. Um dos problemas é não poder não saber quantos e quais
recursos vão precisar no início da execução e também reter recursos que outros
processos poderiam estar usando.
Nenhuma preempção, seria tomar o recurso a força, contudo é uma solução pouco
promissora, de certa forma inviável.
Espera circular, pode ser eliminado de várias maneiras, uma delas é ter uma regra que
diz que um processo é intitulado somente para um único recurso em qualquer momento,
ou atribuir uma ordem para chamada para aquele recurso. 1.2.6. Impedimento do
Impasse. Anteriormente o deadlock não foi evitado pela imposição de regras arbitrárias
aos processos, mas pela análise cuidadosa de cada solicitação de recurso para ver se
ele poderia ser concedido seguramente.
27
Para evitar dinamicamente o deadlock podem-se adotar algumas soluções:
Alocação individual de recursos - à medida que processo necessita;
Escalonamento cuidadoso – impões um alto custo e conhecimento prévio dos
recursos que serão utilizados;
Algoritmos:
3
Fonte da Ilustração: http://www.inf.ufrgs.br/gppd/disc/inf01151/trabalhos/sem2000-2/deadlock/deadlock.htm
28
Vantagens e desvantagens do algoritmo do banqueiro: - Pouco utilizado, pois é
difícil saber quais recursos serão necessários; - O número de processos é dinâmico e
pode variar constantemente, tornando o algoritmo custoso; - Na teoria o algoritmo é
ótimo.
Detectar e recuperar.
Recuperar a situação:
preempção de recursos;
roll-back de processos;
terminação de processos.
29
Cada novo thread é representado por um identificador (thread identifier ou tid) de tipo
pthread_t. É necessário passar o endereço de uma variável desse tipo, como primeiro
parâmetro de pthread_create(), para receber o respectivo tid. O segundo parâmetro serve
para indicar uma série de atributos e propriedades que o novo thread deverá ter, se fornecer
o valor NULL, o novo thread terá as propriedades por padrão, adequadas na maior parte dos
casos. O terceiro parâmetro informa a função de início do thread. É uma função que deve
existir com o seguinte protótipo:
4
Fonte: Miguel Pimenta Monteiro - Sistemas Operativos
30
void * nome_da_função(void *arg).
A função aceita um apontador genérico como parâmetro, que serve para passar
qualquer informação, e retorna também um apontador genérico, em vez de um simples
código de terminação. Se o valor de retorno for usado, é necessário que aponte para algo
que não deixe de existir quando o thread termina. Finalmente o quarto parâmetro é o valor
do apontador a ser passado à função de inicio, como seu parâmetro. Uma vez criado o novo
thread ele passa a executar concorrentemente com o principal e com outros que porventura
sejam criados.
Quando um thread termina pode retornar um apontador para uma área de memória
que contenha qualquer tipo de resultado. Essa área de memória deve sobreviver o thread,
ou seja, não pode ser nenhuma variável local, porque essas deixam de existir quando o
thread termina.
Por padrão, quando um thread termina, o seu valor de retorno (o apontador genérico)
não é destruído, ficando retido em memória até que algum outro thread execute um
pthread_join() sobre ele. É possível criar threads que não são joinable e que por isso,
quando terminam, libertam todos os seus recursos, incluindo o valor de retorno. No entanto
não é possível esperar por esses threads com pthread_join().
5
Fonte da ilustração: https://computing.llnl.gov/tutorials/pthreads/
31
12. Kernel
É por isso que a adição de hardware novo a uma máquina pode requerer a
substituição ou ao menos a reconfiguração do Kernel. Os Kernels mais recentes do Linux
oferecem vários mecanismos de configuração que os tornam sobremaneira flexíveis, a
ponto de ser rara a necessidade de substituição do Kernel. Os dois mecanismos
fundamentais de se configurar a operação do Kernel são a passagem de parâmetros no
momento do boot (realizada pelo LILO) e a carga de módulos, feita manualmente ou por
mecanismos automáticos como o Kerneld.
6
Fonte: Unix: Conceitos e Comandos Básicos
32
Usuários de MS-DOS talvez já tenham feito coisas como C>DIR>PRN, para imprimir a
saída de um comando. Essa sintaxe foi herdada do UNIX daí a semelhança $ Is –I>dev/lp1.
Naturalmente tanto no MS-DOS quanto no Unix existem formas mais apropriadas para se
imprimir algo, mas no momento esse exemplo convém. Shell do estilo “Bourne” (sh,
ksh,bash) permitem redirecionamento da saída de erros através da seguinte sintaxe:
$ rm /bin/Is 2>/tmp/error
O “2” deve-se a que, internamente, a saída de erros corresponde ao descritor 2 (o 0 é
a entrada padrão e o 1 é a saída padrão). A entrada pode ser redirecionada de forma
semelhante:
$ wc </tmp/error
Os shells Unix oferecem um recurso para a ligação da saída padrão de um processo
com a entrada padrão de outro, chamado pipe:
$ Is|wc
No exemplo a saída do Is está sendo usada como entrada do wc. Note que o shell
dispara os dois processos ao mesmo tempo. Se o primeiro estiver produzindo saída numa
taxa superior à que o segundo lê, o sistema operacional paralizará o primeiro sempre que o
buffer que armazena o tráfego estiver cheio. Isso significa, por exemplo, que um pipe pode
ser usado mesmo quando o volume total da saída do primeiro processo é
extraordinariamente grande, por exemplo quando se tenta localizar informações de arquivos
deletados através de um dump de todos os setores do disco.
34
14. Comunicação Serial e Paralela
Em PCs, os conectores externos das portas seriais são conectores DB-9 ou DB-25
macho, e os das paralelas são DB-25 fêmea.
35
15. Configuração do TCP/IP
Numa rede TCP/IP, a cada máquina está associado um número IP, que é um inteiro de
32 bits, normalmente escrito na forma de octetos, como 192.168.0.5. A cada máquina está
associado em um nome, como por exemplo marte ou pimenta.
O passo seguinte é a configuração das rotas. Através delas a máquina sabe por onde
enviar datagramas a fim de que eles cheguem em seus destinos. Equivale de certa forma à
sinalização do tráfego urbano, com placas indicativas da direção a tomar para atingir cada
destino (Ponte do Limão à esquerda, ou Avenida dos Bandeirantes em frente, etc).
Cada rota envolve um destino, uma máscara, um gateway e uma interface. Pode-se
exibir todas elas através do comando netstat: $ netstat –r
/
.Miguel Pimenta Monteiro6, somente ha pouco tempo a especificação POSIX da API do
Unix definiu uma interface standard para a criação e terminação de threads. Esta interface é
geralmente implementada como uma biblioteca (libpthreads.a), podendo ou não ser
diretamente suportada pelo kernel do sistema operacional. Existem versões do Unix em que
os threads são diretamente implementados no kernel e escalonados independentemente
são os (kernel level threads), enquanto que em outras versões o que o kernel vê são apenas
processos, “existindo” os threads unicamente na biblioteca de suporte, e escalonados para
execução apenas na “fatia de tempo” dos respectivos processos são os (user level threads).
6
Fonte: Miguel Pimenta Monteiro - Sistemas Operativos
38