Prof. Armando Luiz N. Delgado
Um processo é um programa em execução. Toda vez que o usuário digita um comando que executa um programa, o sistema UNIX cria um novo processo.
Mesmo que o usuário não esteja fazendo nada em particular, haverá pelo menos 1 (um) processo em execução: aquele associado ao shell iniciado quando o usuário logout no sistema.
Para a maioria dos processos, a entrada e saída está associada ao terminal:
Quando um programa utiliza a entrada e saída padrão, o usuário deve esperar pelo seu término antes de estar habilitado a executar outro comando ou programa por um dado terminal.
No entanto, alguns programas podem não usar ou necessitar de interação com o usuário. Por exemplo:
sort -k2 clientes >clientes_por_fone
Outros programas interagem com o usuário através de uma janela gráfica dedicada e distinta do emulador de terminal de onde foram iniciados. Exemplo disto é o gedit(1) quando executado em um ambiente X Windows.
Em ambos os cenários, não é necessário que o usuário espere pelo término do programa. Seria interessante que, enquanto o programa acima é executado, o usuário pudesse continuar a executar outras tarefas pelo mesmo terminal. Para fazer isto em UNIX, basta colocar o caracter & (ampersand) ao final da linha de comando (após quaisquer redirecionamentos, se houver):
sort -k2 clientes >clientes_por_fone & gedit fones.txt &
Quando o shell espera pelo término de um programa antes de habilitar ao usuário a execução de um novo comando, dizemos que o programa está sendo executado em foreground.
Quando o shell inicia o programa, mas o deixa executar por si, retornando o controle do terminal ao usuário (o que acontece colocando-se & ao final da linha de comando), dizemos que o programa está sendo executado em background.
Um programa é candidato a ser executado em background quando ele não necessita entrada de dados do usuário através da entrada padrão (e.g., um editor como o vi(1)).
Pode-se executar vários programas em seqüência e em foreground usando-se apenas uma linha de comando. Basta separar cada comando por ; (ponto e vírgula). Assim, a linha de comando
ls ~ ; cd ~ci066 ; wc -l LabNum7/fones.txt
é equivalente à
ls ~ cd ~ci066 wc -l LabNum7/fones.txt
Da mesma forma, é possível executar vários programas em seqüência e em background usando-se apenas uma linha de comando. Basta separar cada comando por &. Assim, a linha de comando
sort -k2 clientes >clientes_por_fone & wc -l fones.txt >num_fones &
é equivalente a:
sort -k2 clientes >clientes_por_fone & wc -l fones.txt >num_fones &
A todo processo o sistema UNIX associa um número, denominado process ID ou simplesmente PID. Este identificador é usado pelo sistema operacional para controlar o acesso do programa aos recursos do computador, ou pelo usuário para controlar a execução do processo (e.g., abortar um processo caso se observe que ele não está trabalhando como devia).
Um comando pode disparar a execução de um único programa ou de um conjunto de 2 ou mais programas. Assim, usa-se o termo job para se referir a um comando executado pelo shell em background. A cada job (que pode gerar um ou mais processos) o shell associa um número denominado Job ID ou simplesmente JID.
Tanto o PID quanto o JID são exibidos pelo shell no momento em que se inicia a execução de um comando em background. Eles são exibidos em uma única linha na forma [JID] PID. Por exemplo:
sort -k2 clientes >clientes_por_fone & [1] 1345
Quando um processo é iniciado em background termina, o shell exibe uma pequena mensagem na tela de onde o programa foi iniciado, indicando o JID e o comando:
[1] Done sort -k2 clientes >clientes_por_fone
Quando um processo que necessita da entrada padrão é iniciado em background termina, o shell pára a execução do processo e exibe uma pequena mensagem na tela de onde o programa foi iniciado, indicando o JID, a condição de parada e o comando:
vi teste.txt & [1]+ Stopped vi
Os principais comandos para monitoração de processos e jobs são:
Os principais comandos para controle de processos e jobs são:
Quando um programa é iniciado em foreground, o usuário pode SUSPENDER (parar sem terminar) a execução digitando ^Z (Control-Z) pelo teclado. A mensagem [1] Stopped <comando> será exibida pelo shell. A partir deste momento, o usuário pode digitar qualquer comando pelo terminal, pois o programa está parado. Para retomar a execução do programa (em inglês, resume), dois comandos podem ser executados:
Para obter uma lista de todos os jobs em execução em uma determinada sessão de shell, basta usar o comando jobs, que mostra uma lista do tipo abaixo:
[1] Running emacs & [2]- Running netscape & [3]+ Stopped vi
O sinal indica o JOB CORRENTE. O sinal
indica
o JOB ANTERIOR. Caso os comandos fg e bg sejam
executados sem argumentos, eles são aplicados ao JOB CORRENTE.
Executando-se jobs -l, também será exibido o PID do processo principal do job:
[1] 1245 Running emacs & [2]- 1247 Running netscape & [3]+ 1256 Stopped (tty output) vi
Caso se queira aplicar fg e bg em algum job
que não o corrente (aquele com o sinal na lista de jobs), usa-se
como argumento o número do job precedido por %
(porcentagem):
fg %1 ^Z bg %1
Os argumentos para fg e bg podem ser na forma da tabela 1.
O comando ps(1) exibe na tela informação a respeito dos processos atualmente sendo executados no sistema. Conforme a opção, são mostrados apenas os processos do usuário ou de todos os usuários. A principal informação é o PID, o programa em execução e o nome do usuário.
O comando top(1) mostra os processos em ordem reversa de uso de CPU: os processos que mais usam a CPU aparecem no início da lista, juntamente com o proprietário do processo e com o PID, entre outras informações.
O comando kill(1) termina (mata) um processo. Seus argumentos são o PID ou JID, podendo haver mais que um ID na mesma linha de comando. Por exemplo:
kill 1245 kill 345 %3 kill 2345 567 3456
Quando se executa um programa, ele pode ser interrompido com um ^C (Control-C). No entanto, isto pode não funcionar, sendo necessário então lançar mão de kill(1).
Quando se termina um processo com kill(1), o shell exibe uma mensagem do tipo
[1] Terminated emacs
O efeito de um kill é fazer com que o programa seja terminado de forma suave e ordenada, sem prejuízo de eventuais arquivos que estejam sendo usados pelo processo.
Geralmente uma simples execução de kill é o suficiente para terminar um programa, mas há exceções. Neste caso, deve-se indicar um argumento opcional -9 que indica ao sistema que o processo deve ser terminado de modo forçado, sem dó nem piedade. Isto pode, eventualmente gerar problemas em arquivos usados pelo programa morto.
kill -9 1245 kill -KILL 345
Um usuário somente pode matar apenas os processos do qual ele é proprietário, isto é, processos que foram iniciados por ele mesmo.
Cada processo tem direito a utilizar os recursos do sistema. No entanto, Um processo pode ter associado uma prioridade mais alta ou mais baixa na utilização destes recursos.
Esta prioridade é definida com nice(1): nice -AJUSTE COMANDO, onde AJUSTE varia de -20 (maior prioridade) até 19 (menor prioridade).
nice -15 ls --> define prioridade mais baixa nice --12 netscape --> aumenta a prioridade do processo
Somente o usuário root pode aumentar a prioridade de processos. Outros usuários podem apenas DIMINUIR a prioridade, usando para isto renice(1):
renice 12 345 --> muda a prioridade do process com PID=345
UNIX diferencia dois tipos de USUÁRIO e GRUPO, para efeitos de definição de permissões de acesso a arquivos por um programa:
As permissões de acesso a arquivos por um processo são verificadas de acordo com a identificação EFETIVA de usuário e grupo.
No momento, nesta disciplina, o usuário e grupo efetivos são iguais aos usuário e grupo real, isto é, ao usuário que inicia o programa.