Você está na página 1de 3

Bing

1. Multiprocessamento e Multi-programação são dois conceitos


fundamentais em sistemas operativos, mas são distintos. O
multiprocessamento refere-se a um sistema de computador que tem
mais de um processador. Isso permite que o sistema execute vários
processos simultaneamente, melhorando o desempenho geral do
sistema. Por outro lado, a multi-programação é uma técnica de
programação que permite que vários programas residam
simultaneamente na memória principal e sejam executados de forma
concorrente para maximizar a utilização da CPU. É possível ter
multiprocessamento sem multi-programação se cada processador
estiver executando apenas um processo de cada vez. No entanto, isso
não seria eficiente, pois a CPU pode ficar ociosa durante as operações
de E/S.
2. O ciclo de vida de um processo consiste em vários estados: Novo,
Pronto, Executando, Bloqueado e Terminado. Um processo é
inicialmente colocado no estado Novo quando é criado. Ele então se
move para o estado Pronto, onde está esperando para ser atribuído à
CPU. Uma vez que a CPU está disponível, o processo é movido para o
estado Executando. Se o processo precisa esperar por um evento (como
uma operação de E/S), ele é movido para o estado Bloqueado. Uma vez
que o evento ocorre, o processo volta ao estado Pronto. Quando o
processo termina sua execução, ele é movido para o estado Terminado.
A Tabela de Controle de Processos (PCB) é necessária para rastrear
todas as informações relevantes sobre cada processo, como o estado do
processo, o contador de programa, os registradores da CPU, a
prioridade do processo, etc.
3. As políticas de scheduling determinam a ordem em que os processos
são selecionados para execução. As principais políticas de scheduling
incluem First-Come, First-Served (FCFS), Shortest Job Next (SJN),
Round Robin (RR), e Prioridade. Cada política tem suas próprias
vantagens e desvantagens, e a escolha da política depende do tipo de
sistema operativo. Por exemplo, o FCFS é simples e fácil de
implementar, mas pode levar à condição conhecida como "starvation".
O SJN é ótimo para minimizar o tempo de espera, mas é difícil de
implementar na prática porque não conhecemos o tempo de execução
dos processos com antecedência. O RR é excelente para
compartilhamento de tempo, mas pode ter um alto overhead devido à
troca frequente de contextos. A política de Prioridade permite a
execução de processos importantes primeiro, mas pode levar ao
"starvation" de processos de baixa prioridade.
4. O algoritmo de scheduling usando prioridade estática atribui uma
prioridade fixa a cada processo, e o processo com a maior prioridade é
selecionado para execução. Se dois processos têm a mesma prioridade,
então o FCFS é usado. Este algoritmo pode levar ao adiamento
indefinido (também conhecido como "starvation"), onde um processo
de baixa prioridade pode nunca ser executado se houver sempre algum
processo de alta prioridade na fila de prontos.
5. A região crítica é uma seção de código que acessa recursos
compartilhados que não devem ser acessados simultaneamente por
vários processos ou threads. As primitivas de acesso com exclusão
mútua a uma região crítica devem garantir as seguintes propriedades:
exclusão mútua (apenas um processo pode estar na região crítica de
cada vez), progresso (se nenhum processo está na região crítica, e
alguns processos querem entrar, apenas esses processos participam na
decisão de quem vai entrar, e essa decisão não pode ser adiada
indefinidamente), e espera limitada (existe um limite para o número de
vezes que outros processos são permitidos entrar na região crítica após
um processo ter feito um pedido para entrar e antes que esse pedido
seja concedido).
6. A solução encontrada para os problemas decorrentes dos processos
aguardarem a entrada na região crítica no estado ativo é o uso de
semáforos ou variáveis de condição que permitem que um processo
seja bloqueado e desbloqueado. a. Os problemas que surgem quando
os processos aguardam a entrada na região crítica no estado ativo
incluem o uso ineficiente da CPU (pois o processo está consumindo
tempo de CPU, mas não está fazendo nenhum trabalho útil) e o risco
de deadlock (se todos os processos estiverem ocupados esperando
para entrar na região crítica, então nenhum processo pode avançar). b.
Para garantir a exclusão mútua no acesso aos recursos compartilhados,
devemos usar primitivas de sincronização como semáforos, locks ou
monitores que garantem que apenas um processo pode acessar o
recurso de cada vez.
Para a Parte II, aqui está um exemplo de solução para o problema dos
produtores/consumidores usando semáforos em C:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

#define BUFFER_SIZE 10

int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;

sem_t empty;
sem_t full;
pthread_mutex_t mutex;

void *producer(void *arg) {


int i;
for (i = 0; i < 20; i++) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);

buffer[in] = i;
printf("Producer produced %d\n", i);
in = (in + 1) % BUFFER_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
}

void *consumer(void *arg) {


int i, item;
for (i = 0; i < 20; i++) {
sem_wait(&full);
pthread_mutex_lock(&mutex);

item = buffer[out];
printf("Consumer consumed %d\n", item);
out = (out + 1) % BUFFER_SIZE;

pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}

int main() {
pthread_t producer_thread, consumer_thread;

sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
pthread_mutex_init(&mutex, NULL);

pthread_create(&producer_thread, NULL, producer, NULL);


pthread_create(&consumer_thread, NULL, consumer, NULL);

pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);

sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);

return 0;
}
Este código cria um produtor e um consumidor que compartilham um buffer
comum. Os semáforos empty e full são usados para garantir que o produtor
não produza quando o buffer estiver cheio, e que o consumidor não consuma
quando o buffer estiver vazio. O mutex é usado para garantir a exclusão
mútua quando o produtor e o consumidor acessam o buffer.

Você também pode gostar