Implementação de tarefas - Teoria de Sistemas Operacionais

COMPARTILHAR:

Whatsapp Telegram Twitter Facebook Reddit

Enquanto um processo permanecer no estado "terminado", seu PCB não será apagado pelo kernel.

Considerando o programa fork.c abaixo:

[#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main ()
{
   int retval, x ;

   x = 0 ;
   retval = fork () ;
   printf ("No processo %5d x vale %d\n", getpid(), x) ;
   if ( retval < 0 ){
      perror ("Erro") ;
      exit (1) ;
   }
   else
      if ( retval > 0 ){
         x = 0 ;
         wait (0) ;
      }
      else{
         x++ ;
         sleep (5) ;
      }

   printf ("No processo %5d x vale %d\n", getpid(), x) ;

   exit (0) ; 

}

Para exibir o identificador do processo (pid), pode-se utilizar a chamada getpid().

Ao executar o programa fork-print.c abaixo, o valor da variável x no processo filho é alterado pelo comando x++;

[#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main ()
{
   int retval, x ;

   x = 0 ;
   retval = fork () ;
   printf ("No processo %5d x vale %d\n", getpid(), x) ;
   if ( retval < 0 ){
      perror ("Erro") ;
      exit (1) ;
   }
   else
      if ( retval > 0 ){
         x = 0 ;
         wait (0) ;
      }
      else{
         x++ ;
         sleep (5) ;
      }

   printf ("No processo %5d x vale %d\n", getpid(), x) ;

   exit (0) ; 

}]

Quando um processo está no estado “terminado”, as variáveis do processo são liberadas, apenas o PCB é mantido até que o processo pai pegue o retorno do filho por meio da função wait.

Considerando o programa fork2.c abaixo:

[#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main ()
{
   int retval=0 ;
   printf ("Ola, sou o processo %5d\n", getpid()) ;
   retval = fork () ; //Cria novo processo
   printf ("[retval: %5d] sou %5d, filho de %5d\n",
           retval, getpid(), getppid()) ;
   if ( retval < 0 )
   {
      perror ("Erro") ;
      exit (1) ;
   }
   else
      if ( retval > 0 ){
			int status;
			int id = wait (&status) ; 
			printf("%d terminou com status %d\n",id,WEXITSTATUS(status));

			
		}
      else
         sleep (5) ;

   printf ("Tchau de %5d!\n", getpid()) ;

   exit (0) ; 

}]

 A variável x é única em cada processo e possui endereços físicos distintos na memória RAM.

Considere os programas simple.c e fork-execve1.c respectivamente abaixo:

[#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <sys/resource.h>


int main (int argc, char *argv[], char *envp[]){

printf ("Simple.c - sou %5d, filho de %5d\n", getpid(), getppid()) ;

    //o "for" abaixo serve apenas para produzir um tempo de processamento.

    for(int i=0;i<1999999999;i++);

struct rusage ru;

//Leitura das informacoes do processo.

getrusage(RUSAGE_SELF, &ru);

printf("\nTempo (modo usuário) %.5f (secs)\n",ru.ru_utime.tv_sec+ ru.ru_utime.tv_usec/1000000.0);

printf("\nTrocas involuntarias: %5ld \nTrocas voluntarias: %5ld\n",

ru.ru_nivcsw,ru.ru_nvcsw);

return 0;



}

]

[#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/wait.h>


/*O terceiro argumento "envp" serve para acessar as variáveis de ambiente do sistema.*/

int main (int argc, char *argv[], char *envp[])

{

   int retval ;

   //printf("\n%s\n",envp[0]);  //Acessar variaveis de ambiente

   printf ("Ola, sou o processo %5d\n", getpid()) ;

   retval = fork () ;

   printf ("[retval: %5d] sou %5d, filho de %5d\n",

           retval, getpid(), getppid()) ;

   if ( retval < 0 )

   {

      perror ("Erro: ") ;

      exit (1) ;

   }

   else

      if ( retval > 0 ){ //Se pai

int status;

int id = wait (&status) ; 

printf("%d terminou com status %d\n",id,status);

}

      else{

/*Observe que o processo "simple" possui o mesmo id do processo 

filho que acabou de ser criado.*/

         execve ("./simple", argv, envp) ;

         perror ("Erro");/*Essa mensagem ocorrera' apenas quando houver erro

ao fazer o 'load' do "./simple" */

      }

   printf ("Tchau de %5d!\n",getpid()) ;

   exit (0) ;

}

]

A informação sobre a quantidade de trocas de contexto do processo, exibida pelo simple.c, é armazenada no PCB do próprio processo. A execução do fork-execve1.c criará 1 processo. Quando o comando fork for executado, um 2o. processo será criado. Sendo assim, a execução do fork-execve-1.c criará 2 processos.

Considere o programa fork-execve2.c abaixo:

[#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

#define NUM_PROCESSOS 2

int main (int argc, char *argv[], char *envp[])
{
	int retval,i;
	printf ("Ola, sou o processo %5d\n", getpid()) ;
	//Cria NUM_PROCESSOS
	for (i=0;i<NUM_PROCESSOS;i++){
		retval = fork () ;
		if (retval == 0){ //se processo filho			
			printf ("[retval: %5d] sou %5d, filho de %5d\n",
										retval, getpid(), getppid()) ;
			break;
		}
	}
	if ( retval == 0 )
		execve ("./simple", argv, envp) ;
	else
		for (i=0;i<NUM_PROCESSOS;i++)
			printf("%d terminou\n",wait(0));
	printf ("Tchau de %5d!\n",getpid()) ;
	exit (0) ; 

}]

Ao executar o programa, 3 processos serão criados. O primeiro é o main e depois mais 2 processos (conforme o #define NUM_PROCESSOS 2).

Considere que um programa foi executado e que o pid do processo pai é 1000 e do processo filho (criado por meio do fork) é 1001. Pode-se afirmar que o "pid" do processo que contém o código do simple.c também será 1001. Execute o programa fork-execve1.c demonstrado anteriormente. Note que, para executá-lo será necessário compilar o simple.c. Você pode concluir que como a execução do execve pelo processo filho (linha 30 do programa fork-execve1.c) não gera um novo PCB, então a impressão do pid pelo simple.c (linha 9 do programa simple.c) exibe o mesmo pid.

Enquanto um processo permanecer no estado "terminado", seu PCB não será apagado pelo kernel. O PCB existirá mesmo se o processo estiver no estado "terminado". Inclusive, o SO sabe que um processo está no estado "terminado" pois essa informação está armazenada no PCB. O PCB somente será apagado após o SO liberar toda a memória alocada pelo processo e, principalmente, "entregar" o retorno do processo (return 0) ao processo pai. Enquanto o processo pai não pegar o retorno do filho, o PCB não será liberado. Se o processo pai existir e não pegar o retorno do filho, o filho irá se tornar um processo denominado zombie! Você saberia como criar e visualizar um processo zombie? Para visualizar você pode utilizar o comando ps -aux

O programa simple.c visto anteriormente possui um comando "for" na linha 11. Ao aumentar a quantidade de vezes que o "for" executa, a quantidade de trocas de contexto involuntárias poderá aumentar. Trocas de contexto involuntárias ocorrem quando o processo "gostaria" de permanecer no processador, mas seu tempo terminou. Trocas de contexto voluntárias ocorrem quando o próprio processo libera o processador antes de terminar o quantum de tempo dele. Essa liberação pode ocorrer, por exemplo, para executar uma entrada/saída ou para aguardar o término de um processo filho (como ocorre quando a função wait() é chamada) ou até mesmo quando o processo termina (com o comando return da função main).

A chamada execve não duplica o processo pai. Muito pelo contrário, ele sobrescreve as áreas de código, dados, heap e pilha do processo pai.

Ao compilar e executar o programa fork2.c, 2 processos serão criados. O primeiro processo será gerado ao executar o programa pelo terminal. O segundo processo será gerado pelo comando fork().

No programa fork2.c, a chamada do comando fork() criará um novo PCB (ou TCB) no kernel. Para armazenar as informações sobre o novo processo criado pelo comando fork(), o kernel criará um novo PCB (ou TCB).

Ao executar o programa fork-print.c, o valor da variável x no processo pai será 0. Pois a variável x no processo pai não é alterada.

A chamada execve() não cria um novo PCB que conterá as informações do novo processo. A chamada execve() utiliza o mesmo PCB do processo que a chamou.

No programa fork2.c, o processo que executar a função wait(&status) será colocado no estado de Suspenso e somente sairá deste estado quando um processo filho terminar. O processo que chama a função wait() se coloca em espera. Note que esse é um tipo de "trap", ou seja, o próprio processo interrompe sua execução. Quando um processo filho termina (pode ser qualquer filho), o processo pai receberá o retorno do filho. Lembra que em C escrevemos "int main(){.... return 0;}"? O retorno da função main será enviado ao processo pai.

Quando um processo chama da função sleep(), uma troca de contexto voluntária acontecerá. Ao executar a função sleep, o processo passa do estado de executando para suspenso. Essa mudança de estado ocorre a pedido do próprio processo. Por este motivo, ela é chamada de voluntária.

No programa fork2.c, a função wait (&status) será executada apenas pelo processo filho. A função wait (&status) será chamada apenas pelo pai pois está dentro do "if (retval > 0)". Somente o processo pai terá o valor de retval maior do que 0.

COMENTÁRIOS

Nome

#ann,25,#HK,30,#LTCode,126,Artigo - Diversos,156,Artigo - Games,200,Artigo - Tecnologia,597,autor-thomaz,7,Coluna - Alternative World,24,Coluna - Fail,12,Coluna - Tec Line,14,Criptomoeda,71,Curiosidades - Diversos,49,Curiosidades - Tecnologia,50,en,2,estudo,8,HN,12,logica,14,Pentest,23,Programar C,29,Programar POO,6,Programar Python,6,Programar Shell,21,Programar verilog,12,Raspberry Pi,15,Redes,3,root,100,Shorty Awards,1,Smartphones - Reviews,33,Teoria,10,Top Nostalgia,2,VPN,18,WhatsApp,46,
ltr
item
Limon Tec: Implementação de tarefas - Teoria de Sistemas Operacionais
Implementação de tarefas - Teoria de Sistemas Operacionais
Enquanto um processo permanecer no estado "terminado", seu PCB não será apagado pelo kernel.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmI65og5X32bSLCmBz3uJnZlmDvzOFWZWoZzyvUhh2rtp8Hr_kolKy02pOjxpkThrz8uHaTu3skUdeDJlkFEKkC2a9EabpwPzbwJ-hm-po0QIaNeNvYm5CJw3k4SbN03V-d2h1dxrW2tz4/s320/ltcode.jpg
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmI65og5X32bSLCmBz3uJnZlmDvzOFWZWoZzyvUhh2rtp8Hr_kolKy02pOjxpkThrz8uHaTu3skUdeDJlkFEKkC2a9EabpwPzbwJ-hm-po0QIaNeNvYm5CJw3k4SbN03V-d2h1dxrW2tz4/s72-c/ltcode.jpg
Limon Tec
https://www.limontec.com/2022/02/teoria-sistemas-operacionais-3.html
https://www.limontec.com/
https://www.limontec.com/
https://www.limontec.com/2022/02/teoria-sistemas-operacionais-3.html
false
2157924926610706248
UTF-8
Carregar todos posts Não encontramos nenhum post VER TUDO Ler mais Responder Cancelar resposta Deletar Por Home PÁGINAS POSTS Ver tudo RECOMENDADO PARA VOCÊ LABEL ARQUIVO SEARCH TODOS POSTS Não encontramos nenhum post relacionado a sua requisição VOLTAR PÁGINA INICIAL Domingo Segunda Terça Quarta Quinta Sexta Sábado Dom Seg Ter Qua Qui Sex Sab Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro Dezembro Jan Fev Mar Abr Maio Jun Jul Ago Set Out Nov Dez apenas agora 1 minuto atrás $$1$$ minutes ago 1 hora atrás $$1$$ hours ago Ontem $$1$$ days ago $$1$$ weeks ago mais de 5 semanas atrás Seguidores Seguir ESTE CONTEÚDO ESTÁ BLOQUEADO PASSO 1: Compartilhe com seus amigos PASSO 2: Clique no link compartilhado Copiar Todo Código Selecionar Todo Código Todos códigos foram copiados para seu clipboard Não é possível copiar códigos / textos, por favor aperte [CTRL]+[C] (ou CMD+C no Mac) para copiar Tabela de conteúdo