Você está na página 1de 28

Modelo computacional do UNIX

Evoluo histrica

Organizao do UNIX
User Interface

Conceitos fundamentais

Processos

Elementos activos com estrutura interna simplificada Permite utilizao dinmica sem comprometer o desempenho Sistema de arquivo hierrquico simples, mas coerente Constitui o suporte para a comunicao entre processos e E/S Interface flexvel com o utilizador Facilmente extensvel Permite redireccionar E/S

Sistema de ficheiros

Interpretador de comandos

Processos

Processo executa uma imagem


Do ponto de vista do utilizador, a imagem constituda por um conjunto de 3 segmentos: Texto: Cdigo do programa Dados: Variveis do utilizador Pilha: Armazenamento temporrio de argumentos de funes e endereos de retorno Segmentos so partilhveis PID (identificador do processo) Processos integram-se em grupos (hierarquias) Grupo identificado pelo pid do processo de topo
5

Identificadores

Proteco

Verso simples de listas de controlo de acesso (ACL)


Para um recurso (ficheiro, dispositivo E/S, processo...) define-se proteco em 3 categorias Dono (owner) Grupo (group) Outros (other, world) Atribudos na criao do processo, geralmente por herana UID (user id) GID (group id) Utilizador e superutilizador Acessos aos recursos em modo utilizador so validados
6

Identificadores associados a um processo


Classes de privilgio

Implementao de processos

Process table

Reside permanentemente em memria Informao essencial que o ncleo deve conhecer sobre qualquer processo Escalonamento: Prioridade, tCPU, tsleep Imagem: Ponteiros para text, data, stack (ou onde encontrar, se swapped) Signals: Mscara, pendentes Vrios: Estado, evento pelo qual espera, talarm, PID, PID do pai, UID, GID Informao necessria apenas quando o processo pode correr
7

User structure

Implementao de processos

User structure

Campos Registos do CPU Estado da chamada ao sistema: Parmetros e resultados Tabela de descritores de ficheiro Contabilidade: tCPU em modo utilizador e ncleo, quotas de tCPU, stack, pginas Stack em modo ncleo: Utilizado quando em modo ncleo

Criao de processos

fork

pid = fork()

Duplica o processo pai, criando uma cpia que difere no pid Mecanismo eficiente, amplamente utilizado (ex, pela shell)

Partilhado

Copy-on-write

Fork e exec

fork

exec

Carregar nova imagem Mltiplas variantes (execl, execv)

10

Terminao de um processo

exit

Termina a execuo, retorna um cdigo ao pai Bloqueia espera da concluso de um processo filho

wait/waitpid

11

Estrutura da shell

Estrutura bsica de uma shell

&

12

Execuo de um comando na shell

13

Funes para gesto de processos

14

Threads em Unix

Adio recente ao SO

Inicialmente, existiam diversas verses incompatveis

Actualmente a interface para as chamadas de sistema faz parte da especificao POSIX (P1003.1c)

POSIX: Portable Operating System Interface (tipo Unix) Kernel threads (System V, Solaris, Linux) ou biblioteca do utilizador (4BSD)

POSIX especifica a interface, mas no a implementao


15

Kernel vs user threads

16

Kernel vs user threads


Rapidez de comutao Flexibilidade vs transparncia no escalonamento Efeito das chamadas bloqueantes ao SO


fork deve replicar a estrutura

de threads?

Leitura/escrita, semforos Reescrita das bibliotecas Page faults Bloqueios frequentes so tpicos em aplicaes multithreaded

Se sim, que sucede com thread bloqueada na leitura de stdin? Se no, que sucede se uma das threads no criadas detm mutex?

read vs close/lseek em threads distintas

Signals devem afectar threads ou processos?


SIGFPE, SIGINT

17

Threads em Linux

Linux cria processos/threads ou nuances intermdias


clone(function, stack_ptr, sharing_flags, arg)

18

Gesto de threads POSIX

Sincronizao (tambm sem_wait, sem_post) e comunicao no pode ser usada entre processos
19

Signals

Interrupes por software


Tratamento de excepes e acontecimentos assncronos Comunicao e controlo da execuo de processos Aces: Ignorar, processar, ou morrer (aco por omisso) Utilizvel dentro de uma hierarquia de processos POSIX

20

10

Tratamento de signals

Associar um signal handler


Rotina de servio de interrupo Interface tradicional (simples) ou POSIX

Rearmar signal Handlers standard: SIG_IGN, SIG_DFL


21

Tratamento de signals

Tratamento de signals herdado pelo processo filho aps fork Envio explcito de signals com kill(pid,signal)

Se pid = 0 o signal enviado aos processos do mesmo grupo Usado pelo gestor de terminal para enviar SIGINT e SIGQUIT

Quando um processo bloqueado num semforo, mecanismo de comunicao ou leitura de ficheiro recebe um signal desbloqueado

Primitivas retornam cdigo de erro (EINTR) Obriga a testar sistematicamente valores de retorno e reiniciar chamadas interrompidas
sleep = alarm + pause
22

Envio temporizado de SIGALARM com alarm(segundos)


11

Pipes

Mecanismo inicial para comunicao entre processos Unix


Essencial na operao do interpretador de comandos Interface (read/write) idntica dos ficheiros Sincronizao clssica dos mecanismos de comunicao

Canal unidireccional ligando dois processos


23

Redireco com pipes

24

12

Fifos

Fifo pipe com nome


Criao: mknod(nome, S_IFIFO | proteccao) Associao: open Remoo: unlink Estruturas de dados residentes no ncleo do SO

Descritores criados no sistema de ficheiros


Comunicao (unidireccional) entre processos no relacionados hierarquicamente

25

Sincronizao e comunicao no sistema V (IPC)


Mltiplos mecanismos

Semforos, memria partilhada, mailboxes, sockets Criao/associao: get Chave de acesso pblica ou privada (IPC_PRIVATE) Parametrizao/consulta: ctl Id global do objecto ndice para tabela do ncleo

Interface uniforme

Internamente, ncleo gere os objectos de forma semelhante


26

13

Semforos

Criao/associao: semid = semget(semkey,nsem,semflag)



Cria grupo de nsem semforos, que podem ser manipulados conjuntamente semkey: Identificador pblico para o grupo IPC_PRIVATE se forem semforos privados do processo Permite operaes simultneas sobre vrios semforos Operaes executadas em bloco Resolve de forma simples o jantar dos filsofos

Operao: semop(semid,sops,nsops)

Inicializao/controlo/consulta: semctl Signals interrompem operaes bloqueantes


Testar valor de retorno das primitivas


27

Operaes sobre semforos


semkey semid semop 0 1 2 nsem = 6 3 4 assinalar 5
28

pid

esperar esperar esperar 0

0 1

sops[nsops]

nsops = 4 2 3

14

Operaes sobre semforos


struct Sembuf sops 0 1 2 3 SemNum SemOp SemFlg ndice para semforo individual (2) Nmero de unidades a adicionar <0 esperar >0 assinalar =0 esperar zero Opes (SEM_UNDO)

29

Utilizao de semforos
#include #include #include #include #include #include #include <stdio.h> <sys/types.h> <unistd.h> <stdlib.h> <sys/ipc.h> <sys/sem.h> <errno.h>

int main() { int semid; union semun { int val; struct semid_ds *buf; unsigned short *array; } arg; struct sembuf sops[1];

Parametrizao de semctl (usar campo val para SETVAL)

if ((semid=semget(IPC_PRIVATE, 1, 0666|IPC_CREAT)) < 0) { perror("Erro a criar semaforo"); exit(-1); }

Proteco

arg.val = 0; if (semctl(semid, 0, SETVAL, arg) < 0) { perror("Erro a inicializar semaforo"); exit(-1); }

30

15

Utilizao de semforos
if (fork()==0) { /* filho */ printf("Ola', eu sou o filho, pid=%d\n", getpid()); sops[0].sem_num = 0; sops[0].sem_op = -1; sops[0].sem_flg = 0; printf("Filho vai bloquear\n"); if (semop(semid, sops, 1) < 0) perror("Erro a esperar semaforo"); printf("Filho desbloqueado\n");

Identificador ainda vlido no filho

} else { /* pai */ printf("Ola', eu sou o pai, pid=%d\n", getpid()); sops[0].sem_num = 0; sops[0].sem_op = 1; sops[0].sem_flg = 0; sleep(5); printf("Pai vai desbloquear filho\n"); if (semop(semid, sops, 1) < 0) perror("Erro a assinalar semaforo\n"); printf("Pai continua. Vai dormir.\n"); sleep(5); if (semctl(semid, 0, IPC_RMID) < 0) perror("Erro a eliminar semaforo\n"); } } 31

Memria partilhada

Mapeamento de pores de espaos de endereos distintos na mesma regio de memria fsica Criao/associao: shmid = shmget(shmkey,shmsize,shmflag) Mapeamento (attach): shmat(shmid,...) Remoo do mapeamento (detach): shmdt(shmid,...) Controlo/consulta: shmctl

32

16

Memria partilhada
Memria P1 Espao end. shmid P2 Espao end. shmid

shmget
(IPC_CREAT)

shmat

shmget

shmat
33

Utilizao de memria partilhada

34

17

Utilizao de memria partilhada

No tem de coincidir com produtor (obter dimenso: shmctl + IPC_STAT)

35

Mailboxes

Comunicao com modelo de caixa de correio Criao/associao: msgid = msgget(msgkey,msgflag) Envio: msgsnd(msgid,msgp,msgsz,...)

Bloqueante se cheia (excepto se IPC_NOWAIT) Bloqueante se vazia Mensagens filtradas por tipo (mtype) FIFO se mtype = 0 Por prioridades se mtype < 0

Recepo: msgrcv(msgid,msgp,msgsz,mtype,...)

Controlo/consulta: msgctl Bloqueio interrompido por signals


36

18

Formato das mensagens


Mensagem

Mensagens com formato flexvel


mtype Contedo livre (contguo)

Prembulo long mtype

struct { long mtype; char mtext[TXTSIZE]; } msg;

struct { long mtype; int ident; float vec[VECSIZE]; } msg;


struct { long mtype; char *mtext; } msg;

Formato incorrecto!

No contguo Apontador invlido no destino


37

Utilizao de mailboxes
#include #include #include #include #include #include #include <stdio.h> <sys/types.h> <unistd.h> <stdlib.h> <sys/ipc.h> <sys/msg.h> <errno.h>

#define TXTSIZE 10 int main() { int msqid; struct { long mtype; char mtext[TXTSIZE]; } msg; int i;

/* message type */ /* message text */

if ((msqid=msgget(IPC_PRIVATE, 0666|IPC_CREAT)) < 0) { perror("Erro a criar queue"); exit(-1); }

38

19

Utilizao de mailboxes
msg.mtype = 1; if (fork()==0) { /* filho */ printf("Filho vai receber\n"); if (msgrcv(msqid, &msg, sizeof(msg.mtext), 0, 0) < 0) perror("Filho: erro a receber mensagem"); for (i=0; i<TXTSIZE; i++) printf("%c", msg.mtext[i]); printf("Filho vai enviar\n"); for (i=0; i<TXTSIZE; i++) msg.mtext[i] = 'F'; if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) < 0) perror("Filho: erro a enviar mensagem"); }

39

Utilizao de mailboxes
else { /* pai */ printf("Ola', eu sou o pai, pid=%d\n", getpid()); printf("Pai vai enviar\n"); for (i=0; i<TXTSIZE; i++) msg.mtext[i] = 'P'; if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) < 0) perror("Pai: erro a enviar mensagem"); printf("Pai continua. Vai dormir.\n"); sleep(5); printf("Pai vai receber\n"); if (msgrcv(msqid, &msg, sizeof(msg.mtext), 0, 0) < 0) perror("Pai: erro a receber mensagem"); for (i=0; i<TXTSIZE; i++) printf("%c", msg.mtext[i]); if (msgctl(msqid, IPC_RMID, 0) < 0) perror("Erro a eliminar queue"); } } 40

20

Sockets

Pipes bidireccionais

Compatibilidade Interface baseada em descritores de ficheiros e read/write Transparncia Pequenas variaes na programao permitem suportar comunicao local ou remota (em rede), com diversos protocolos Unix/Local (entre processos numa unica mquina) Internet Sequencialidade, fiabilidade (ausncia de duplicaes e omisses)
41

Sockets operam num domnio especificado na sua criao


Propriedades da comunicao dependentes do tipo de socket


Tipos de socket

Stream

Interface semelhante dos pipes Comunicao fivel e sequencial No domnio internet, implementado sobre TCP Interface tipo caixa de correio No h garantia de sequencialidade ou fiabilidade No domnio internet, implementado sobre UDP Sobre redes locais a fiabilidade adequada a muitas aplicaes Fivel no domnio unix

Datagram

42

21

Criao de sockets

Criao: sid = socket(dominio,tipo,protocolo)


Devolve descritor de ficheiro No domnio unix os nomes so paths normais Descritor do socket ficheiro especial Usado sobretudo em sockets connection oriented listen+accept (servidor), connect (cliente) Servidor cria novo (sub)socket para servir cada ligao Desnecessrio em sockets datagram (connectionless) Com connect pode usar-se read, write, send, recv Se no, usar sendto, recvfrom com destino ou origem
43

Atribuio de nome: bind(sid,addr,addrsz)


Estabelecimento da ligao

Protocolo connection-oriented

44

22

Endereos
struct sockaddr sa_family sa_data[14] (template) cast struct sockaddr_in sin_family sin_port sin_addr sin_zero (internet)
45

connect(sid, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) Porque no union?

struct sockaddr_ns sns_family sns_addr sns_zero (XNS)

struct sockaddr_un sun_family sun_path[108] (unix/local)

Servidor socket stream


#include #include #include #include #include #include #include #include <stdio.h> <unistd.h> <sys/types.h> <sys/socket.h> <sys/un.h> <string.h> <stdlib.h> <errno.h>

#define SERVNAME "/tmp/SERV" #define MSG "Servidor responde!!!" int main() { int sd, s; struct sockaddr_un my_addr; socklen_t addrlen; struct sockaddr_un from; socklen_t fromlen; char buf[100]; if ((sd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) { perror("Erro a criar socket"); exit(-1); }

46

23

Servidor socket stream


my_addr.sun_family = AF_UNIX; memset(my_addr.sun_path, 0, sizeof(my_addr.sun_path)); strcpy(my_addr.sun_path, SERVNAME); addrlen = sizeof(my_addr.sun_family) + strlen(my_addr.sun_path); if (bind(sd, (struct sockaddr *)&my_addr, addrlen) < 0 ) { perror("Erro no bind"); exit(-1); } if (listen(sd, 1) < 0 ) { perror("Erro no listen"); exit(-1); } fromlen = sizeof(from); if ((s=accept(sd, (struct sockaddr *)&from, &fromlen)) < 0 ) { perror("Erro no accept"); exit(-1); } if (read(s, buf, sizeof(buf)) < 0) perror("Erro no read"); else { printf("SERV: Recebi: %s\n", buf); if (write(s, MSG, strlen(MSG)+1) < 0) perror("Erro no write"); } close(s); close(sd); unlink(SERVNAME); }

fork pthread_create

Podem ser truncados

47

Cliente socket stream


#include #include #include #include #include #include #include #include <stdio.h> <unistd.h> <sys/types.h> <sys/socket.h> <sys/un.h> <string.h> <stdlib.h> <errno.h>

#define SERVNAME "/tmp/SERV" #define MSG "Cliente pergunta?!" int main() { int sd; struct sockaddr_un srv_addr; socklen_t addrlen; char buf[100]; if ((sd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) { perror("Erro a criar socket"); exit(-1); }

48

24

Cliente socket stream


srv_addr.sun_family = AF_UNIX; memset(srv_addr.sun_path, 0, sizeof(srv_addr.sun_path)); strcpy(srv_addr.sun_path, SERVNAME); addrlen = sizeof(srv_addr.sun_family) + strlen(srv_addr.sun_path); if (connect(sd, (struct sockaddr *)&srv_addr, addrlen) < 0 ) { perror("Erro no connect"); exit(-1); } if (write(sd, MSG, strlen(MSG)+1) < 0) { perror("CLI: Erro no write"); } else { if (read(sd, buf, sizeof(buf)) < 0) { perror("CLI: Erro no read"); } else { printf("CLI: Recebi: %s\n", buf); } } close(sd); }

49

Protocolo connectionless

connect filtra endereos

50

25

Peer socket datagram (servidor)


#include #include #include #include #include #include #include #include <stdio.h> <unistd.h> <sys/types.h> <sys/socket.h> <sys/un.h> <string.h> <stdlib.h> <errno.h>

#define SERVNAME "/tmp/SERV" #define MSG "Servidor responde!!!" int main() { int sd; struct sockaddr_un my_addr; socklen_t addrlen; struct sockaddr_un from; socklen_t fromlen; char buf[100]; if ((sd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0 ) { perror("Erro a criar socket"); exit(-1); }

51

Peer socket datagram (servidor)


my_addr.sun_family = AF_UNIX; memset(my_addr.sun_path, 0, sizeof(my_addr.sun_path)); strcpy(my_addr.sun_path, SERVNAME); addrlen = sizeof(my_addr.sun_family) + strlen(my_addr.sun_path); if (bind(sd, (struct sockaddr *)&my_addr, addrlen) < 0 ) { perror("Erro no bind"); exit(-1); } fromlen = sizeof(from); if (recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen) < 0) { perror("Erro no recvfrom"); } else { printf("SERV: Recebi: %s\n", buf); if (sendto(sd, MSG, strlen(MSG)+1, 0, (struct sockaddr *)&from, fromlen) < 0) { perror("Erro no sendto"); } } close(sd); unlink(SERVNAME); }

recvfrom/sendto devolvem nmero de bytes lidos/escritos


52

26

Peer socket datagram (cliente)


#include #include #include #include #include #include #include #include <stdio.h> <unistd.h> <sys/types.h> <sys/socket.h> <sys/un.h> <string.h> <stdlib.h> <errno.h>

#define SERVNAME "/tmp/SERV" #define CLINAME "/tmp/CLI" #define MSG "Cliente pergunta?!" int main() { int sd; struct sockaddr_un my_addr; socklen_t addrlen; struct sockaddr_un to; socklen_t tolen; char buf[100]; if ((sd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0 ) { perror("Erro a criar socket"); exit(-1); } 53

Peer socket datagram (cliente)


my_addr.sun_family = AF_UNIX; memset(my_addr.sun_path, 0, sizeof(my_addr.sun_path)); strcpy(my_addr.sun_path, CLINAME); addrlen = sizeof(my_addr.sun_family) + strlen(my_addr.sun_path); if (bind(sd, (struct sockaddr *)&my_addr, addrlen) < 0 ) { perror("Erro no bind"); exit(-1); } to.sun_family = AF_UNIX; memset(to.sun_path, 0, sizeof(to.sun_path)); strcpy(to.sun_path, SERVNAME); tolen = sizeof(my_addr.sun_family) + strlen(to.sun_path); if (sendto(sd, MSG, strlen(MSG)+1, 0, (struct sockaddr *)&to, tolen) < 0) perror("CLI: Erro no sendto"); else { if (recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&to, &tolen) < 0) perror("CLI: Erro no recvfrom"); else printf("CLI: Recebi: %s\n", buf); } close(sd); unlink(CLINAME); } 54

27

Referncias

J. A. Marques, P. Guedes, Fundamento de Sistemas Operativos, 3 edio, Editorial Presena, 1994. W. Richard Stevens, UNIX Network Programming, PrenticeHall, 1990.

55

28

Você também pode gostar