This repository has been archived by the owner on Aug 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
02.01-Arquitetura_computador
501 lines (434 loc) · 22.7 KB
/
02.01-Arquitetura_computador
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
ARQUITETURA COMPUTADOR
* O computador moderno é composto de várias partes
- Barramento: Canal de comunicação entre componentes do computador
- CPU: Processamento e controle entre componentes
- Memória: Memória secundária não durável
- Controlador de Vídeo: Faz a interface com o monitor (foi
introduzido pela Xerox na década de 1980)
- Controlador de Teclado: Componente para entrada
- Controlador do HD: Disco Rígido durável
* A velocidade de acesso entre memórias é bem diferente. A memória
interna (cache), muito rápido e em vários níveis, a memória RAM e
o disco rígido (muito lento)
* Barramento
- Trilhas comunicando um ou mais dispositivos, apenas uma mensagem
de cada vez
* Processador
- Contador, pilha, PSW (prog. Status word), modo usuário e
privilegiado (algumas instruções só podem ser executadas no
modo de supervisão), multicore x singlecore (um core apenas
será usado para a maioria dos algoritmos)
- Trap (interrupção): sinal eletrônico que faz o processador entrar
em modo privilegiado e muda o programa para um endereço pré-
especificado. Cada interrupção faz com que seja realizada alguma
ação, sendo que elas estão armazenadas em um vetor de
interrupções. Essas rotinas e o vetor são carregados assim
que acontece o boot do SO.
* Memória
- Proteção e troca de contexto: memória virtual, código realocável
- A memória virtual é uma abstração: ela é, de fato, separada usando
partes. Porém, existe um hardware específico que permite mudar a
memória.
- O hardware tem um registro das regiões que cada programa pode
acessar. Se ele sair da região, é dado um sinal específico que
"mata" o programa (falha de segmentação)
* Discos
- Prato, superfície, cilindros, trilhas, setores, cabeças.
.------ cabeça para
.----------------------. '------ gravação
/ .--- trilha ---------. \ --.
/ / \ \ | cilindro
/ '------------------------' \ --'
'------------------------------' --.
'------------------------------' | pratos
'------------------------------' |
'------------------------------' --'
Setor: mínimo de bytes que podem ser escritos na memória
- A taxa de transferência para o disco é muito lenta, porque
a rotação do disco demora em taxa de milissegundos
* Outros dispositivos de I/O:
- Discos, vídeo, teclado, mouse, interfaces de rede, etc.
- CPU não se comunica com dispositos (em geral, analódigos), mas
com o circuíto didital de controle (controlador)
- Controladores são conectados ao barramento, via alguns
registradores mapenados na CPU
- Cada controlador está associado a um "device driver" (interfaces
padrão para acesso aos sistemas, convertidos via programas
específicos em assembly)
- Quando acabou? "bus waiting" ou interrupção.
* Processos
- Um programa sendo executado
- Linha de processamento, registradores (pilha, etc.) e estado da
memória.
- 5 estados possíveis: rodando, pronto, bloqueado, suspenso
(bloqueado e pronto)
.-------.
|Running| ---> Terminate
'-------'
preempt / ^ \ block
^ / Run ^
.-----. .-------.
Create --->|Ready|<-------|blocked|
'-----' '-------'
| ^ unblock | ^
| | | |
Suspend | | Resume | | Resume
| | Suspend| |
^ | ^ |
.---------. .---------.
| Ready | <------- | Blocked |
|Suspended| unblock |Suspended|
'---------' '---------'
- Estados:
- Blocked: Esperando pelo resultado de uma chamada ao sistema
- Ready: Pronto para rodar, mas não necessariamente rodando
(outro programa de maior prioridade pode estar
ocupando a CPU. Nesse estado, ele só precisa ocupar
a CPU)
- Blocked Suspended: Se muitos programas estão rodando ao
mesmo tempo, um programa pode ser
suspenso, e ficar aguardando até que
o sistema se desocupe. Nesse estado,
ele ainda está aguardando por alguma
chamada ao sistema.
- Ready Suspended: Quando o programa recebe sua requisição
ao SO, fica Ready, mas ainda estará
suspenso.
- Running: O programa ocupando a CPU.
* Multiprogramação
- CPU deve ser otimizada com relação à execução (geralmente,
programas com muito IO tem prioridade, porque eles usam a
CPU e ficam bloqueados enquanto esperam as (demoradas) ações
de IO).
- O sistema mostrado acima é o pseudo-paralelismo da CPU.
- Paralelismo real nos periféricos.
- NÃO é tempo real.
- Threads (processos leves): linha de processamento distinta,no
contexto de registradores, com mesmo estado de memória. Usar
threads é diferente de criar processos filhos, porque neste
caso cada um tem seu espaço de memória, e naquele, a memória
é compartilhada dentro do processo.
- Diferença entre processo e threads: thread compartilha os recursos
(tem problema de sincronização), processos são exclusivos.
- Tabela de processos: guarda quais processos estão rodando, e a
ordem em que são trocados.
- Processos não podem assumir nada em relação a tempo real (porque
estão ou não executando).
* Minix
- Anos 80: A AT&T fecha o código do sistema Unix (S7) e proíbe seu
ensino em universidades (para lucrar)
- Dificuldade de construção de SO leva muitos cursos a se tornarem
teóricas ou a propor apenas pequenas simulações.
- Tanembaum se propõe a construir Minix:
- Compatível com a versão 7 do Unix (mesmas chamadas de sistema
e escrito para ser lido, com fácil modificação):
- Código C
- Extremamente modularizado
- Forte uso de comentários (original com 11.000 linhas de
código e 3.000 linhas de comentários)
- Fácil modificação
- Fontes disponíveis
- SO "de verdade"
* Processos (Minix)
- Processos podem se comunicar
- Todos os processos são organizados em árvore (mata os pais -> mata os filhos;
exceto usando "nohup", que faz o processo deixar de ser filho da sessão)
- Organização hierárquiva (Minix/Unix/Linux)
- UID (User ID)
- Obs: instrução 'fork' cria novo processo (clonado a partir do
processo-pai, com registradores, processos, pilha, etc.
todos iguais). O retorno do UID é 0 para o filho e o UID
do filho para o pai.
- Os filhos só podem saber quem são seus pais usando os meios
de comunicação:
- Mensagens: Entre processos
- Arquivos: Escrevendo entre um e outro
- Pipes (|): Muito mais rápido que usar os arquivos, porque
cria-se um buffer na memória, em vez de um arquivo no
disco. Pipe é um pseudo arquivo implementado na memória contectando
dois processos (um escreve e outro lê)
- Sinais (signal): espécie de sinal assíncrono que faz com
que o receptor tenha código desviado para endereço
pré-determinado.
Os sinais fazem com que o outro programa tenha alguma ação
parecida com uma interrupção. O destinatário pode ou não
tratá-lo. Se tratar, a ação é parecida com a de
interrupção. Porém, em vez de ir para um local
pré-determinado no hardware, pode ir para outro.
* Arquivos Minix
- Organização hierárquica
- Diretório root (começando com /)
- Caminhos absolutos e relativos (o diretório atual é guardado
na tabela de processos)
- Proteção 8 bits (rwx)
- Arquivo especial:
- Acesso transparente ao I/O
- Bloco (disco): lê no apontador, e permite acesso aleatório.
Eles pode ser alterado usando "seek" (para mudar o local)
ou ler (com "read").
Caractere (teclado, tela, etc.): só podem ser usados para ler
ou escrever diretamente (read/write), pois não é possível
"voltar" para o passado.
- Todos os arquivos têm um DESCRITOR DE ARQUIVO.
- Standard input/output: descritores de arquivo 0 e 1
(geralmente, são o teclado e a tela)
- Montar/desmontar (mount/umount): utilizado para acesso a
periféricos de maneira modular (criando os diretórios
de dentro desse arquivo especial em algum subdiretório).
A pasta padrão é /dev (device)
- Major device number (tipo)/minor device number
/dev/hda0, /dev/hda1
^^^'- minor device number
'--- major device number
* Estrutura do Minix
.--------------------------------------------------------------.
4| User process | User process | User process | ... | }User
|--------------'--.-----------'-.------------'.----------------| }
3| Process manager | File system | Info server | Network server | }space
|-------------.---'--------.----'------------.'----------------| }
2| Disk driver | TTY driver | Ethernet driver | ... | }
|-------------'------------'.----------------'.----------------|
1| Kernel | System task | Clock task | Kernel
'--------------------------------------------------------------' space
- Cada layer se comunica somente com uma camada abaixo dele.
O espaço do kernel tem o gerenciado básico do sistema e o relógio,
usado para os sistemas básicos (camada do Kernel).
- A segunda camada (drivers) são os programas que servem de
interface para os componentes eletrônicos.
- A terceira camada (servidores) são os que se comunicam com os
programas, e são todos são os que podem se comunicar com os que
estão abaixo.
- A quarta camada são os processos normais do usuário, se
comunicando com servidores de cada camada.
- 4 camadas: kernel (escalonamento de processos, tempo, tabelas,
sistema de mensagens), drivers (abstração dos dispositivos),
estratégias de escalonamento, sistema de arquivo e comunicação
(apresentam "máquina virtual"), processos de usuário.
- Apenas 1 camada em "espaço de kernel".
- Outras camadas possuem processos sem compartilhamento de memória:
comunicação por mensagens. As mensagens são implementadas usando uma
chamada de sistemas específica. Essas mensagens têm uma estrutura
específica, em que é guardada um ponteiro para o texto e o processo
que enviou. A pessoa que enviou é bloqueada quando ocorre a
mensagem. O recebedor terá a mensagem COPIADA dentro do outro
processo, para ser lida. Quem implementa esse envio é o SO, fazendo
a parte do baixo nível. O processo que ENVIA manda uma mensagem
com a chamada 'send'. O processo que recebe fica com um 'receive',
aguardando até receber algo. O 'send-receive' faz uma chamada e
espera por ela. Esse processo é síncrono.
- A mensagem é um processo síncrono, e é bem diferentes de sinais.
Os sinais são processos ASSÍNCRONOS, em que o programa é
interrompido no meio de qualquer ação.
- O envio de mensagens é feito nas camadas inferiores, ABAIXO de
servidores. Para as aplicações, existe a biblioteca de programas de
chamadas ao sistema, que fazem por si próprias mensagens para os
componentes corretos.
- Sinais são tratados pelo Kernel, ao receber alguma transmissão,
via o barramento, de um componente do hardware. Ele gera uma
mensagem e envia para o Kernel correspondente.
- Essa arquitetura é a arquitetura de microkernel.
* Chamadas de sistema no Minix
- Para os programas, se comunicar com o SO são funções em C
armazenadas em uma biblioteca.
- Cada chamada de sistema manda um sinal que gera uma interrupção, e
o SO, ao vê-lo, desempacota a rotina correspondente. O programa do
usuário manda a requisição aos servidores, e estes comunicam-se
com o driver.
- Chamadas de sistema do Minix
- fork (única maneira de criar novos processos)
- Gera duas cópias idênticas nas memórias separadas
- Chamada volta zero para processo filho, e pid para
o processo pai
- wait()
- Processo pai aguarda o final de execução de um dos filhos
- execve(name,argv,envp)
- A imagem do processo é substituída pelo conteúdo de um
arquivo, passados argumentos e ambientes (que descreve o
terminal, etc).
- Essa é a maneira de um programa "mutar", e deixar de ser
igual ao processo pai. A imagem vem de algum arquivo
executável, que deve ser passado como argumento.
- exit()
- Termina o processo e retorna o parâmetro como código de
saída (o zero representa OK). O código único (0) é bom
porque todos os outros podem ser usados como erro.
- brk()
- Altera o tamanho da área de dados do parâmetro
Estrutura do programa
--------- .----------.
| | Símbolos | Símbolos de #define do programa
| |----------|
| | Data | Dados de entrada do programa
| |----------|
| | Text | Programa de fato
| |----------|
| | Header | Área do programa com informações
--------- '----------' dos campos acima
.---------------.
Se, ao dar um : stack : Empilhamento
"push" na pilha : | : (aumentado via push)
e ele invadir : ^ :
o brk, haverá : :
um sinal de erro : ^ :
um erro. : | : Memória dinâmica
: heap : (aumenta/diminui via brk)
O malloc tenta :---------------:
ver se áreas da : : área para dados
heap liberadas : bss : estáticos não
podem ser usadas : : inicializados
para novas :---------------:
alocações. Caso : data : Dados pré-definidos
não possa, tenta :---------------:
brk. Se não der, : text : Programa em si
retorna que não '---------------'
há mais espaço
para alocação
Quando há acesso FORA do frame, o sistema operacional
MATA o programa.
- getpid()
- Pede o ID do processo (para poder comunicar via fork).
- signal(sig,func)
- Determina captura de um sinal pela função func (em geral,
se não der para tratar, o processo é morto).
Os sinais são, para o software, o mesmo que uma
interrupção para o hardware.
.---------------.
.----. .-- | Pilha |
| PC | empilha | |---------------|
'----' o PC '-> | PC |
|---------------|
Pula para | |
o sinal... | |
'---------------'
- kill(pid,signal)
- Manda um sinal a um processo. Existe um sinal KILL
que realmente mata um processo - mas, de forma geral,
ele só funciona para processos filhos.
- alarm(seconds)
- Agenda um envio do sinal SIGALARM, para que o processo
seja avaliado depois de certo tempo. Usando signal,
é possível dar tratamentos depois.
- pause()
- Suspende p processo ae queeste rebeba o próximo sinal.
- creat(name,mode)
- Cria um novo arquivo e acre, ou abre e seta o tamanho para
zero, retornando o descritor (como 'touch')
- mknod(nome,mode,addr)
- Cria um i-node regular, especial ou de diretório, retorna
um descritor. "Addr" é major + minor device number.
- open(file,how)
- Abre um arquivo considerando o nome dele e se terá
leitura/escrita. Devolve um descritor de arquivo.
- close(fd)
- Fecha um arquivo aberto.
- É importante para que os i-nodes sejam salvos, o que
não ocorre se morrer.
- read(fd,buffer,nbytes)
- Lê dados em um buffer, retorna bytes lidos.
- Lê até nbytes, ou menos. Retorna o número de bytes
realmente gravados.
- write(fd,buffer,nbytes)
- Grava dados de um buffer e retorna o número de bytes
gravados (porque poderia dar problemas).
- lseek(fd,offset,whence)
- Muda o poteiro do arquivo, retona a nova posição para
posição. Whente indica se o offset relativo à posição
atual, início ou fim.
- stat(name,&buf),fstat(fd,&buf)
- Lê e retorna o estado do arquivo
- dup(fd1)
- Aloca um novo descritor de arquivos (número que descreve
qual é o i-node que representa o arquivo) para o arquivo
aberto. Dup cria um novo número para o mesmo i-node.
- Dup costuma ser útil para SUBSTITUIR o arquivo apontado
por aquele descritor específico, e depois retornar. É
útil principalmente para redirecionar stdin e stdout.
- Ex:
fd = dup(1);
close(1); // LIBERA o descritor '1'
open(name); // Pega o MENOR descritor o possível: no
... // caso, será o 1
...
close(1);
dup(fd); // Agora, dup pegará o menor fd disponível.
// Ele será, novamente, 1
- pipe(&fd[0])
- Cria um pipe, retorna fd de leitura e escrita no vetor.
- Ex:
Pipeline(process1, process2)
char *process1, *process2; // nomes dos programas
{
int fd[2];
pipe(&fd[0]);
if(fork() != 0)
{
/* Processo pai, escreve no filho */
close(fd[0]); // este processo não lerá
// do pipe. Pode fechá-lo
close(stdout); // Fechamos stdout para
// para liberar o fd
dup(fd[1]); // Pega a saída do pipe e
// a associa ao menor fd
// disponível: stdout.
close(fd[1]); // Não precisa mais do pipe,
// e libera esse descritor.
execl(process1,process1,0);
// Roda o processo e os outros
}
else
{
/* Processo filho, lê do pipe */
close(fd[1]); // este processo não escreverá
// no pipe. Pode fechá-lo
close(stdin); // Fechamos stdin para
// liberar o fd
dup(fd[0]) // Pega a saída do pipe a
// a associa ao menor fd
// disponível: stdin
close(fd[0]); // Não precisa mais do pipe,
// e libera esse descritor.
execl(process2,process2,0);
// Roda o processo e os outros
}
}
- ioctl(fd,request,argp)
- Executa operações em arquivos especiais (em geral
terminais)
- link(name1,name2)
- Faz entrada name2 ser o mesmo i-node que name1
- unlink(name)
- Remove uma entrada do diretório corrente
- mount(special,name,rwflag)
- Monta um sistema de arquivos
- unmount(special)
- Desmonta um sistema de arquivos
- sync()
- Sincroniza todos os blocos de disco do cache
- chdir(name)
- Muda o diretório corrente
- O cd, do Bash, usa esse programa
- chroot(dirname)
- Muda o diretório raiz (cuidado)
- Funciona APENAS para a shell correspondente
- Ela é perigosa porque os comandos dentro daquele contexto
usarão comandos em outros lugares - e, nesse caso, pode-se
dar problemas. Por esse motivo, chroot só funciona como
superusuário.
- chmod(name,mode)
- Muda os bits de proteção do arquivo
- uid = getuid()
- Retorna o UID do usuário
- gid = getgid()
- Retorna o GID do usuário.
- setuid()
- Muda o UID do usuário.
- setgid()
- Muda o GID do usuário.
- time(&seconds)
- Retorna o tempo em segundos desde 1/1/1970.
- stime(tp)
- Reinicializa o tempo desde 1/1/1970.
- utime(file,timep)
- Seta o valor do último acesso do arquivo.
- times(bufer)
- Retorna o tempo do usuário e de sistema.