A multi programação consiste na execução em pseudoparalelismo de vários programas
na mesma máquina, onde os vários fluxos de execução são multiplexados no tempo,
cada fluxo é designado por processo.
Os
elementos principais que constituem um processo são um espaço de endereçamento,
que normalmente se divide numa região para o código, outra para a pilha e outra
para os dados globais e alocados dinamicamente (heap). Cada processo tem um
estado que pode ser salvaguardado e posteriormente reposto, de forma a permitir
a comutação entre processos. Um processo tem ao seu dispor um reportório de operações,
que consiste nas instruções máquina do processador e nas operações exportadas
pelo sistema operativo (chamadas de sistema).
O
modelo de segurança baseia-se no isolamento entre processos, o que significa
que os processos não podem interferir uns com os outros e na existência de um
utilizador que é o dono do processo, em função do qual são definidas as acções que o processo pode executar sobre os restantes recursos do sistema operativo,
uma vez que estes acessos são sempre mediados pelo núcleo.
Os
processos organizam-se normalmente de forma hierárquica, em que um processo ao
criar outro estabelece uma relação de pai-filho nessa hierarquia. Algumas
informações são herdadas do processo pai para os processos filhos.
pid_t fork(void)- chamada ao sistema para a criação de um novo processo
1- Quando um processo
invoca a chamada ao sistema fork() o sistema operativo vai executa-la em modo
protegido (modo sem restrições de execução)
2- O Sistema Operativo
verifica se o processo que invoca o fork() ainda não esgotou o número máximo de
processos filhos e em caso afirmativo executa o fork()
3- O processo inicial é
duplicado (estruturas de dados do núcleo, zonas de memória, etc..) e ao novo
processo é atribuído um novo PID
4- O novo processo integra
a lista de processos candidatos a usar o CPU
5- O Sistema Operativo
retorna o PID do filho ao Pai e zero ao filho. A execução de cada um destes
processos é retornada na instrução seguinte ao fork()
Um
processo pode ser visto como objecto, com propriedades e operações. As
propriedades fundamentais são um identificador, o ficheiro com o programa
executável, o seu espaço de endereçamento, prioridade, estado de execução,
processo pau, canais de E/S, ficheiros abertos quotas de utilização de
recursos, contexto de segurança e ambiente utilizador
As
operações definem a interface do sistema operativo para manipular processos e
incluem operações para criar um novo processo auto – terminar, para eliminar
outro processo, para esperar pela terminação de outro processo, para suspender
a execução de um processo, ou auto suspender-se e para ler o estado do
processo.
A operação sobre processos que se desvia mais do
modelo computacional genérico é a operação de criação de processos Unix (fork),
que cria um novo processo absolutamente idêntico ao processo pai. Para o
processo filho executar um programa diferente do pai, é necessário que este
invoque uma segunda função (exec) que altera o programa a ser executado.
exec():
Quando um processo invoca a chamada ao sistema execxx o núcleo do Sistema Operativo vai reescrever as zonas de memória associadas ao processo (filho zona estática e dinâmica de dados e código) com a informação existente no ficheiro executável indicado como parâmetro. A execução do processo é iniciado no main() do novo código.
Quando um processo invoca a chamada ao sistema execxx o núcleo do Sistema Operativo vai reescrever as zonas de memória associadas ao processo (filho zona estática e dinâmica de dados e código) com a informação existente no ficheiro executável indicado como parâmetro. A execução do processo é iniciado no main() do novo código.
Em
Unix, o tratamento das excepções e de acontecimentos assíncronos tem particular importância. Os signals são muito
semelhantes ao modelo de rotinas assíncronas e foram a ideia original desta
extensão ao modelo de programação estruturado. Os acontecimentos assíncronos podem
ser analisados a um processo em execução através da activação de um signal. Os acontecimentos susceptíveis de
gerarem um signal tem origens muitos diversas,
e são referenciados num ficheiro de texto (signal.h) que indica o respectivo nome lógico e o valor inteiro que é usado para codifica-lo internamente no
núcleo.