$ dormir 100 e[1] 9298
usar
pidofVocê pode visualizar o ID do processo do nome do programa especificado:
$pidof sleep9298
$ cat /proc/9298/maps08048000-0804b000 r-xp 00000000 08:01 977399 /bin/sleep0804b000-0804c000 rw -p 00003000 08:01 977399 /bin/sleep0804c000-0806d000 rw-p 0804c000 00:00 0 [heap]b7c8b000-b7cca000 r--p 00000000 08:01 443354...bfbd8000-bfbed000 rw-p bfbd8000 00:00 0 [pilha]ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
Após a execução do programa, ele é carregado na memória e se torna um processo. A imagem acima mostra a imagem da memória (memória virtual) do processo, incluindo instruções do programa, dados e algum espaço de pilha usado para armazenar parâmetros de linha de comando do programa e variáveis de ambiente. O espaço de heap usado para aplicação de memória dinâmica foi alocado.
Para obter detalhes sobre o processo de execução do programa na linha de comando, consulte "O momento da execução do programa na linha de comando do Linux".
Na verdade, existem outras maneiras de criar um processo, ou seja, deixar o programa rodar. Por exemplo, através de algumas configurações, você pode iniciar automaticamente o programa quando o sistema for iniciado (para detalhes, consulte.
homem iniciar) ou configurando
Crond(ou
no) para permitir que ele inicie o programa regularmente. Além disso, existe outra maneira, que é escrever um script Shell e gravar o programa em um arquivo de script. Quando o arquivo de script for executado, o programa no arquivo será executado e se tornará um processo. Os detalhes desses métodos não serão apresentados. Vamos aprender como visualizar as propriedades do processo.
Uma coisa que precisa ser adicionada é: para executar o programa na linha de comando, você pode passar
limiteComandos integrados são usados para definir os recursos que um processo pode utilizar, como o número máximo de descritores de arquivo que um processo pode abrir, o espaço máximo de pilha, espaço de memória virtual, etc. Para uso específico, consulte
ajudalimite.
pode passar
PSUse o comando para visualizar atributos e status relacionados ao processo. Essas informações incluem o usuário ao qual o processo pertence, o programa correspondente ao processo e o.
CPUe uso de memória e outras informações. A familiaridade com a forma de visualizá-los pode ajudar na análise estatística relevante e em outras operações.
Visualize as propriedades de todos os processos atuais no sistema:
$ ps -ef
Visualize o processo correspondente ao programa que contém um determinado caractere no comando, processo
EU IAé 1.
TTYpara? Indica que não está relacionado ao terminal:
$ ps -C inicialização PID TTY TIME CMD 1 ?
Selecione processos iniciados por um usuário específico:
$ ps -U falcão
Produza o conteúdo especificado de acordo com o formato especificado.
CPUTaxa de uso:
$ ps -e -o %C %c
Imprimir
CPUOs 4 programas mais usados:
$ ps -e -o %C %c | classificar -u -k1 -r | cabeça -5 7,5 firefox-bin 1.1 Xorg 0.8 scim-panel-gtk 0.2 scim-bridge
Obtenha os cinco processos usando a maior memória virtual:
$ ps -e -o %z %c | classificar -n -k1 -r | head -5349588 firefox-bin 96612 xfce4-terminal 88840 xfdesktop 76332 gedit 58920 scim-panel-gtk
Existe uma relação de “parentesco” entre todos os processos do sistema, que pode ser
pstreeConfira esta relação:
$pstree
A árvore de chamadas do processo do sistema será impressa acima e você poderá ver claramente o relacionamento de chamada entre todos os processos ativos no sistema atual.
$ superior
A maior característica deste comando é que ele pode visualizar dinamicamente as informações do processo. Claro, ele também fornece alguns outros parâmetros, como.
-SVocê pode classificá-lo e visualizá-lo de acordo com o tempo de execução cumulativo ou pode usar
-vocêVisualize processos iniciados por um usuário especificado, etc.
Reabastecer:
principalO comando suporta interativo, por exemplo, suporta
vocêO comando exibe todos os processos do usuário e suporta passagem
kComando para encerrar um processo se estiver usando;
-n 1opção para ativar o modo de processamento em lote, o uso específico é:
$ topo -n 1 -b
Vamos discutir um problema interessante: como fazer apenas um programa rodar ao mesmo tempo.
Isto significa que enquanto um programa estiver sendo executado, ele não poderá ser iniciado novamente. Então, o que fazer?
Se o mesmo programa for copiado em muitas cópias e tiver nomes de arquivo diferentes e for colocado em locais diferentes, isso será pior, então considere o caso mais simples, ou seja, este programa é único em todo o sistema, e o nome também é único . Nesse caso, quais são algumas maneiras de responder às perguntas acima?
O mecanismo geral é: verificar no início do programa se ele foi executado. Se for executado, pare, caso contrário continue a executar o código subsequente.
As estratégias são diversas, pois a suposição anterior garantiu a exclusividade do nome e do código do arquivo do programa.
PSO comando encontra os nomes dos programas correspondentes a todos os processos atuais e os compara com o seu próprio nome de programa, um por um. Se já existir, significa que já foi executado.
ps -e -o %c | tr -d | grep -q ^init$ #Verifica se o programa atual foi executado [ $? -eq 0 ] && exit #Se for, então exit, $? foi executado com sucesso
Cada vez que for executado, primeiro verifique se existe um processo que se salva no local especificado.
EU IAarquivo, se não existir, então continue a execução, se existir, então visualize o processo
EU IAEle está em execução? Em caso afirmativo, saia; caso contrário, reescreva o novo processo no arquivo.
EU IAe continue.
pidfile=/tmp/$0.pidif [ -f $pidfile ]; então OLDPID=$(cat $pidfile) ps -e -o %p | tr -d | grep -q ^$OLDPID$ [ $? && exitfiecho $$ > $pidfile#... Código body# Define a ação do sinal 0. Quando o programa termina, o sinal é acionado para excluir o arquivo temporário trap rm $pidfile 0
Sinta-se à vontade para usar você mesmo mais estratégias de implementação!
Além de garantir que cada processo possa ser executado sem problemas, a fim de permitir que certas tarefas sejam concluídas primeiro, o sistema usará certos métodos de agendamento ao agendar processos, como o algoritmo de agendamento comum de rotação de intervalo de tempo de acordo com a prioridade. Neste caso, você pode passar
ReniceAjuste a prioridade de um programa em execução, por exemplo: `
$ ps -e -o %p %c %n |
$ renice 1 -p 5089renice: 5089: setpriority: Operação não permitida$ sudo renice 1 -p 5089 #Permissões são necessárias [sudo] senha para falcon:5089: prioridade antiga 0, nova prioridade 1$ ps -e -o %p % c %n | grep xfs #Olha novamente, a prioridade foi ajustada 5089 xfs 1
Como você pode executar um programa e criar um processo por meio da linha de comando, também existe uma maneira de encerrá-lo. pode passar
matarO comando envia um sinal ao processo iniciado pelo usuário para encerrar o processo. Claro, é "universal".
raizquase
matarTodos os processos (exceto
iniciarfora). Por exemplo,
$ sleep 50 & #Iniciar um processo [1] 11347$ kill 11347
matarO comando enviará um sinal de encerramento por padrão (
SIGTERM) para o programa e deixar o programa sair, mas
matarOutros sinais também podem ser enviados e estes podem ser definidos via
homem 7 sinalVocê também pode visualizá-lo através
matar -lListe-o.
$ man 7 sinal $ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR213) SIGPIPE 14) SIGALRM 15 ) SIGTERMO 16) SIGSTKFLT17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+439) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+843) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+1247) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-1451) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-1055) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-659) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-263) SIGRTMAX-1 64) SIGRTMAX
Por exemplo, use
matarcomando para enviar
SIGSTOPSinalize um programa para pausar e depois enviar
SIGCONTO sinal o mantém funcionando.
$ sleep 50 &[1] 11441$ jobs[1]+ Executando sleep 50 &$ kill -s SIGSTOP 11441 #Isso é equivalente a executarmos a operação CTRL+Z em um processo em primeiro plano $ jobs[1]+ Stopped sleep 50$ kill - s SIGCONT 11441 #Isso é equivalente à operação bg %1 anterior que usamos para executar um processo em segundo plano $ jobs[1]+ Running sleep 50 &$ kill %1 #Na sessão atual, você também pode controlar o processo através do número do trabalho $ jobs[1]+ Terminated sleep 50
visível
matarO comando oferece funções muito boas, mas só pode ser baseado no processo
EU IAou trabalho para controlar o processo, enquanto
matare
matar todosSão fornecidas mais opções que ampliam as maneiras de controlar um processo pelo nome do programa ou até mesmo pelo nome de usuário. Consulte seus manuais para obter mais informações sobre uso.
Quando o programa é encerrado, como determinar se o programa foi encerrado normalmente ou de forma anormal? Ainda se lembra daquele clássico do Linux?
olá mundoPrograma? No final do código sempre há uma linha
retornar 0declaração. esse
retornar 0Na verdade, permite que o programador verifique se o processo termina normalmente. Se o processo retornar um valor diferente, pode-se dizer com segurança que o processo saiu de forma anormal porque ainda não foi executado.
retornar 0Esta declaração sai.
Então, como verificar o status de saída do processo, ou seja, o valor retornado?
existir
Concha, você pode verificar esta variável especial
$?, que armazena o status de saída após a execução do comando anterior.
$ test1bash: test1: comando não encontrado$ echo $?127$ cat ./test.c | grep olá$ echo $?1$ cat ./test.c | grep oi printf(oi, eu mesmo!n);$ echo $?0
Parece que retornar 0 se tornou uma regra tácita. Embora não exista um padrão que o estipule claramente, quando o programa retorna normalmente, ele sempre pode ser retornado.
$?0 é detectado em , mas quando anormal, um valor diferente de 0 é sempre detectado. Isto nos diz que no final do programa é melhor seguir o
saída 0para que qualquer um possa passar no teste
$?Determine se o programa termina normalmente. Se um dia alguém ocasionalmente usar seu programa e tentar verificar seu status de saída, mas você inexplicavelmente retornar um
-1Ou 1, então ele ficará muito angustiado e se perguntará onde está o problema no programa que ele mesmo escreveu. Ele verificará por um longo tempo, mas ficará perdido porque confia tanto em você que nunca duvida de seus hábitos de programação. do começo ao fim. Será diferente!
Para facilitar o projeto e a implementação, uma tarefa grande geralmente é dividida em módulos menores. Diferentes módulos tornam-se processos depois de iniciados. Como eles se comunicam entre si para trocar dados e trabalhar juntos? Muitos métodos são mencionados no livro "Programação Avançada em Ambiente UNIX", como pipes (pipes não nomeados e pipes nomeados), sinais (
sinal), mensagem (
Mensagem) fila (fila de mensagens), memória compartilhada (
mmap/munmap), semáforo (
semáforo, usado principalmente para sincronização, entre processos, entre diferentes threads de um processo), soquetes (
Soquete, suporte à comunicação de processos entre diferentes máquinas), etc., e no Shell, tubos e sinais geralmente são usados diretamente. A seguir, apresentamos principalmente alguns usos de pipes e mecanismos de sinal na programação Shell.
No Linux, você pode passar
|Conecte dois programas para que você possa usá-lo para conectar a entrada do último programa à saída do programa anterior, por isso é chamado de pipe. Na linguagem C, é muito simples e conveniente criar um pipe sem nome.
canofunção, passando um elemento de dois
internoUma matriz do tipo servirá. Na verdade, esse array armazena dois descritores de arquivo. Depois que o processo pai grava algo no primeiro descritor de arquivo, o processo filho pode lê-lo a partir do primeiro descritor de arquivo.
Se você usar muitas linhas de comando, este canal
|Deve ser usado com frequência. Por exemplo, há uma demonstração acima
PSA saída do comando é como
grepEntrada de comando:
$ ps -ef |
Você pode pensar que esse "tubo" é tão mágico que pode realmente vincular a entrada e a saída de dois programas. Como eles são implementados? Na verdade, quando tal conjunto de comandos é inserido, o shell atual realizará a análise apropriada, associará a saída do processo anterior ao descritor do arquivo de saída do pipe e associará a entrada do processo subsequente ao descritor do arquivo de entrada de o pipe. Este processo de associação Redireciona funções por meio de entrada e saída.
idiota(ou
FCNTL) para alcançar.
Um pipe nomeado é na verdade um arquivo (um pipe sem nome também é como um arquivo. Embora esteja relacionado a dois descritores de arquivo, ele só pode ser lido de um lado e escrito do outro. No entanto, esse arquivo é bastante especial). deve satisfazer o primeiro a entrar, primeiro a sair durante a operação e, se você tentar ler de um canal nomeado que não possui conteúdo, será bloqueado da mesma forma, se tentar gravar em um canal nomeado e nenhum programa estiver tentando no momento. para lê-lo, você será bloqueado. Veja o efeito abaixo.
$ mkfifo fifo_test #Crie um pipe famoso através do comando mkfifo $ echo Fewfefe > fifo_test #Tentando gravar conteúdo no arquivo fifo_test, mas ele está bloqueado Você precisa abrir outro terminal para continuar as seguintes operações $ cat fifo_test #Abra outro terminal. , lembre-se, abra outro. Tentando ler o conteúdo de fifo_test Fewfefe
Aqui está
ecoe
gatosão dois programas diferentes, neste caso, por
ecoe
gatoNão há relacionamento pai-filho entre os dois processos iniciados. No entanto, eles ainda podem se comunicar através de pipes nomeados.
Tal método de comunicação é muito adequado para certas situações: por exemplo, existe tal arquitetura. Essa arquitetura consiste em duas aplicações, uma das quais lê continuamente através de um loop.
fifo_testconteúdo para determinar o que deve fazer a seguir. Se este pipe não tiver conteúdo, ele será bloqueado ali sem consumir recursos devido a um loop infinito. O outro continuará fluindo como um programa de controle.
fifo_testEscreva nele algumas informações de controle para informar ao programa anterior o que fazer. Escreva um exemplo bem simples abaixo. Você pode projetar alguns códigos de controle e então o programa de controle continua a
fifo_testEscreva nele e o aplicativo executa diferentes ações com base nesses códigos de controle. Claro, você também pode ir para
fifo_testPasse outros dados, exceto o código de controle.
código do aplicativo
$ cat app.sh #!/bin/bash FIFO=fifo_test while :; do CI=`cat $FIFO` #CI --> Informações de controle case $CI in 0) echo O número de CONTROLE é ZERO, faça alguma coisa ... ;; 1) echo O número de CONTROLE é UM, faça alguma coisa... ;; echo O número de CONTROLE não foi reconhecido, faça outra coisa... ;;
Código do programa de controle
$ cat control.sh #!/bin/bash FIFO=fifo_test CI=$1 [ -z $CI ] && echo as informações de controle não devem estar vazias && exit echo $CI > $FIFO
Um programa controla o trabalho de outro programa através de pipes
$ chmod +x app.sh control.sh #Modifique as permissões executáveis desses dois programas para que os usuários possam executá-los $ ./app.sh #Inicie esta aplicação em um terminal e envie o controle através de ./control.sh Verifique a saída depois do código o número de CONTROLE ser UM, faça outra coisa... #Depois de enviar 1, o número de CONTROLE for ZERO, faça alguma coisa... #Depois de enviar 0, o número de CONTROLE não for reconhecido, faça outra coisa... #Enviar um desconhecido Após o código de controle $ ./control.sh 1 #Em outro terminal, envie informações de controle para controlar o funcionamento da aplicação $ ./control.sh 0 $ ./control.sh 4343
Essa arquitetura de aplicativo é muito adequada para design de tarefas locais de vários programas, se combinada com.
cgi da web, então também atenderá aos requisitos de controle remoto. introduzir
cgi da webA única mudança é que o programa de controle
./control.shcolocar
redede
cgidiretório e faça algumas modificações nele para que esteja em conformidade com
CGIespecificações, que incluem uma representação do formato de saída do documento (precisa ser gerado no início do arquivo
conteúdo-tpye: texto/htmle uma linha em branco) e a aquisição de parâmetros de entrada
(redeOs parâmetros de entrada são armazenados em
QUERY_STRINGvariáveis de ambiente). Então, muito simples
CGIO programa de controle pode ser escrito assim:
#!/bin/bashFIFO=./fifo_testCI=$QUERY_STRING[ -z $CI ] && echo as informações de controle não devem estar vazias && exitecho -e content-type: text/htmlnnecho $CI > $FIFO
No uso real, certifique-se de
controle.shcapaz de acessar
fifo_testpipe e possui permissões de gravação para controle por meio do navegador
aplicativo.sh:
http://ipaddress_or_dns/cgi-bin/control.sh?0
ponto de interrogação
?O seguinte conteúdo é
QUERY_STRING, semelhante ao anterior
US$ 1.
Tal aplicação é de grande importância prática para controle remoto, especialmente para controle remoto de sistemas embarcados. No curso de verão do ano passado, implementamos o controle remoto de motores desta forma. Primeiro, uma aplicação simples é implementada para controlar a rotação do motor, incluindo controle de velocidade, direção, etc. Para conseguir o controle remoto, projetamos alguns códigos de controle para controlar diferentes propriedades relacionadas à rotação do motor.
Na linguagem C, se você quiser usar um pipe nomeado, é semelhante ao Shell, exceto que ao ler e gravar dados, use
ler,
escreverLigue, crie
fifoUsado quando
mkfifochamada de função.
Sinais são interrupções de software que os usuários do Linux podem acessar via
matarO comando envia um sinal específico para um processo, ou alguns sinais podem ser enviados através do teclado, como
CTRL+Cpode desencadear
SGIINTsinal, enquanto
CTRL+pode desencadear
SGIQUITSinais, etc. Além disso, o kernel também enviará sinais ao processo sob certas circunstâncias, como ao acessar a memória fora dos limites.
SGISEGVOs sinais, é claro, e o próprio processo também podem passar
matar,
elevaçãoAguarde até que a função envie um sinal para si mesma. Para os tipos de sinal suportados no Linux, você pode passar
homem 7 sinalou
matar -lVeja listas relacionadas e instruções.
Para alguns sinais, o processo terá ações de resposta padrão, enquanto para alguns sinais, o processo pode simplesmente ignorá-las. É claro que os usuários também podem definir funções de processamento especiais para determinados sinais. Na casca você pode passar
armadilhacomando (comando interno do Shell) para definir uma ação em resposta a um sinal (um comando ou uma função definida), e na linguagem C você pode usar
sinalChame a função manipuladora registrada para um sinal. Isto é apenas uma demonstração
armadilhaUso do comando.
$ function signal_handler { echo hello, world. } #Defina a função signal_handler $ trap signal_handler SIGINT #Execute esta configuração de comando: print hello, world ao receber o sinal SIGINT $ hello, world #Pressione CTRL+C para ver a tela O hello e strings mundiais são produzidas
Da mesma forma, se você definir a ação de resposta do sinal 0, poderá usar
armadilhaPara simular o programa em linguagem C
atexitRegistro da função de encerramento do programa, ou seja, através
armadilha signal_handler SIGQUITdefinir
manipulador de sinalA função será executada quando o programa terminar. O sinal 0 é um sinal especial em
POSIX.1O sinal número 0 é definido como um sinal nulo, que é frequentemente usado para determinar se um processo específico ainda existe. Este sinal é acionado quando um programa é encerrado.
$ cat sigexit.sh#!/bin/bashfunction signal_handler { echo hello, world}trap signal_handler 0$ chmod +x sigexit.sh$ ./sigexit.sh #Atual programação Shell usará este método para fazer alguma limpeza quando o programa sair Finalizando o trabalho em arquivos temporários, olá, mundo
Quando passamos vários comandos através
|,>,<, ;, (,)Quando combinadas, essa sequência de comandos geralmente inicia vários processos que se comunicam por meio de pipes, etc. Às vezes, ao executar uma tarefa, há outras tarefas que precisam ser processadas, então você geralmente adiciona um & no final da sequência de comandos ou, após executar o comando, pressione
CTRL+ZFaz com que o comando anterior seja pausado. para realizar outras tarefas. Depois de completar algumas outras tarefas, passe
fgO comando muda a tarefa em segundo plano para primeiro plano. Esse processo de controle é geralmente chamado de controle de trabalho, e essas sequências de comandos são chamadas de trabalhos. Esse trabalho pode envolver um ou mais programas, um ou mais processos. A seguir demonstramos diversas operações de controle de trabalho comumente usadas.
$ dormir 50 e[1] 11137
Use comandos integrados do Shell
fgTraga o trabalho 1 para o primeiro plano e pressione
CTRL+ZPausar o processo
$ fg %1sleep 50^Z[1]+ Suspensão interrompida 50
$ jobs # Verifica o status atual do trabalho, um trabalho está interrompido [1] + Stopped sleep 50$ sleep 100 & # Deixa outro trabalho ser executado em segundo plano [2] 11138$ jobs # Verifica o status atual do trabalho, um está em execução e outro está parado [1]+ Suspensão interrompida 50[2]- Executando suspensão 100 &
$ bg %1[2]+ dormir 50 e
No entanto, para usar o controle de trabalho na linha de comando, o shell atual, o driver de terminal do kernel, etc., precisam oferecer suporte ao controle de trabalho.
"Programação Avançada em Ambiente UNIX"