Comunicação entre Processos em C

De Aulas

Códigos exemplos baseados no conteúdo de Comunicação entre Processos da disciplina de Sistemas Operacionais.

Programa quebrastring.c

Exemplo de utilização das funções de sscanf para desmontar uma string e sprintf para montar uma string a partir de variáveis.

 1#include <stdio.h> 
 2#include <string.h>
 3
 4/*
 5exemplo de entrada de parametro
 6	./quebrastring "54 + 32"
 7	./quebrastring "34 - 12"
 8*/
 9                  
10int main(int argc, char *argv[])
11{
12	char operacao;
13	char strout[255];
14	int a, b, resultado;
15	if (argc == 2)
16	{
17		/* Desmonta a string em variaveis */
18		sscanf(argv[1] , "%d %c %d", &a, &operacao, &b);
19		if (operacao == '+') resultado = a + b;
20		else resultado = a - b;
21
22		/* remonta as variaveis em uma string */
23		sprintf(strout, "%d %c %d = %d", a, operacao, b, resultado);
24		printf("%s\n", strout);
25	}
26	else printf("Erro de parametros\n");
27}

Programa paifilho.c

Cria um processo pai e um processo filho deste.

 1#include <stdio.h> // printf
 2#include <unistd.h> //fork 
 3
 4int main(void)
 5{
 6	int pidFilho = fork();
 7	if (pidFilho < 0) perror("Erro no fork");
 8	else if (pidFilho == 0)
 9	{
10		printf("Processo FILHO %d do PAI %d\n", getpid(), getppid());
11		for (;;);
12	}
13	sleep(1); // da um tempinho
14	printf("Processo PAI %d do FILHO %d\n", getpid(), pidFilho);
15	for (;;);
16	return 0;
17}

Programa pipes.c

Cria dois processos, um processo pai e um processo filho deste. Faz a comunicação entre pai e filho utilizando o recurso de pipes.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
	int pipePai[2], pipeFilho[2], idFilho;
	char mensagem[50] = "";

	if (pipe(pipePai) < 0) perror("Erro no pipe do Pai\n");
	if (pipe(pipeFilho) < 0) perror("Erro no pipe do Filho\n");
	if ((idFilho = fork()) < 0) perror("Erro no fork\n");
	else if (idFilho == 0)
	{
		read(pipeFilho[0], mensagem, sizeof(mensagem));
		printf("Filho: %s\n", mensagem);
		sprintf(mensagem, "retorno");
		write(pipePai[1], mensagem, sizeof(mensagem));
		exit(0);
	}
	sprintf(mensagem, "teste");
	write(pipeFilho[1], mensagem, sizeof(mensagem));
	read(pipePai[0], mensagem, sizeof(mensagem));
	printf("Pai: %s\n", mensagem);
	return 0;
}

Programa multifilhos.c

Cria um processo pai e três processos filhos deste.

 1#include <stdio.h> // printf
 2#include <unistd.h> // fork
 3#include <stdlib.h> // exit
 4#include <wait.h> // wait
 5
 6const int PNUM = 13;
 7
 8int main(void) {
 9	// criacao dos processos filhos
10	int pid[PNUM], i;
11	for (i = 0; i < PNUM; i++) {
12		pid[i] = fork();
13		if (pid[i] < 0) perror("Nao foi possivel a criacao do FILHO");
14		else if (pid[i] == 0) {
15			printf("FILHO %d rodando...\n", getpid());
16			sleep(5);
17			exit(0);
18		}
19	}
20	// espera a morte dos filhos
21	int pidret;
22	while ((pidret = wait(0)) != -1) {
23		printf("FILHO: %d morto\n", pidret);
24	}
25	printf("PAI: %d morto\n", getpid());
26}

Exercício

Efetuar modificações no programa acima em concordância com o seguinte: O processo pai deve enviar uma mensagem para cada filho. Cada filho, quando receber a mensagem enviada pelo pai, deve imprimi-la na tela e então entrar no sleep. Após o período de sleep, o mesmo deve fechar sua execução com exit.

Programa threads.c

Compliar como: gcc threads.c -o threads -lpthread

 1#include <pthread.h>
 2#include <stdlib.h>
 3#include <stdio.h>
 4#include <unistd.h>
 5 
 6void* func (void* arg)
 7{
 8	int i;
 9	char* m = (char*) arg;
10	sleep(2);
11	printf("func: %s\n", m);
12 
13	for (i = 0; i < 5; i++)
14	{
15		printf("func: %d\n", i);
16		sleep(1);
17	}
18	sprintf(m, "Bye bye world");
19	printf("func: %s\n", m);
20	return NULL;
21}
22 
23int main (void)
24{
25	int i;
26	pthread_t tid;
27	char message[255] = "Hello World";	
28	printf("main: %s\n", message);
29 
30	if (pthread_create(&tid, NULL, func, (void*) &message))
31	{
32		perror("Error creating threads.\n");
33		abort();
34	}
35	for (i = 0; i < 10; i++)
36	{
37		printf("main: %d\n", i);
38		sleep(1);
39	}
40	if (pthread_join(tid, NULL))
41	{
42		perror("Error joining thread.");
43		abort();
44	}
45	printf("main: %s\n", message);
46}

Programa cliente.c

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <string.h>
 4#include <netdb.h>
 5#include <unistd.h>
 6
 7void erro(char* msg)
 8{
 9	printf("Erro: %s\n", msg);
10	exit(-1);
11}
12
13int main(int argc, char* argv[])
14{
15	int sock;
16	struct sockaddr_in addr;
17	struct hostent* hostPtr;
18	char msg[255];
19
20	if (argc != 4) erro("Sintaxe: ./cliente <host> <port> <string>\n");
21	if ((hostPtr = gethostbyname(argv[1])) == 0) erro("Nao consegui obter endereco");
22
23	memset(&addr, 0, sizeof(addr));
24	addr.sin_family = AF_INET;
25	addr.sin_addr.s_addr = ((struct in_addr *) (hostPtr->h_addr))->s_addr;
26	addr.sin_port = htons((short) atoi(argv[2]));
27	
28	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) erro("socket");
29	if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) erro("Connect");
30
31	write(sock, argv[3], 1 + strlen(argv[3]));
32	read(sock, msg, sizeof(msg));
33	printf("%s\n", msg);
34
35	close(sock);
36}

Programa servidor.c

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <netdb.h>
 4#include <string.h>
 5#include <unistd.h>
 6
 7void erro(char* msg)
 8{
 9	printf("Erro: %s\n", msg);
10	exit(-1);
11}
12
13int main(int argc, char* argv[])
14{
15	int sock, client, er, client_addr_size;
16	struct sockaddr_in addr, client_addr;
17	static char mens_in[255], mens_out[512];
18	int port = 4400;
19	
20	if (argc != 2) erro("servidor <porta>\n");
21	
22	/* Configura o socket */
23	memset(&addr, 0, sizeof(addr));
24	addr.sin_family = AF_INET;					/* tipo */
25	addr.sin_addr.s_addr = htonl(INADDR_ANY);	/* interface */
26	addr.sin_port = htons((int) atoi(argv[1]));	/* fake port */
27	
28	/* Cria o socket */
29	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) erro("socket");
30	
31	/* Abre o socket na forma de bind */
32	if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) erro("bind");
33
34	/* O sistema fica ouvindo mensagens que chegam pelo socket */
35	if (listen(sock, 1) < 0) erro("listen");
36	
37	client_addr_size = sizeof(client_addr);
38	if ((client = accept(sock, (struct sockaddr*) &client_addr, &client_addr_size)) < 0) erro("accept");
39
40	/* espera uma mensagem e retorna uma confirmacao */
41	while ((er = read(client, mens_in, sizeof(mens_in))) > 0)
42	{
43		printf("Mensagem recebida: %s\n", mens_in);
44		sprintf(mens_out, "Confirmado [%s]", mens_in);
45		write(client, mens_out, sizeof(mens_out));
46		printf("Mensagem enviada: %s\n", mens_out);
47	}
48	close(client);
49	close(sock);
50	exit(0);
51	return 0;
52}

Programa multiservidor.c

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <netdb.h>
 4#include <string.h>
 5#include <unistd.h>
 6
 7void erro(char* msg)
 8{
 9	printf("Erro: %s\n", msg);
10	exit(-1);
11}
12
13void process_client(int client_sock)
14{
15	int msg_size = 0;
16	char msg_in[255], msg_out[512];
17	while ((msg_size = read(client_sock, msg_in, sizeof(msg_in))) > 0)
18	{
19		msg_in[msg_size] = '\0';
20		printf("%s\n", msg_in);
21		sprintf(msg_out, "retorno [%s]", msg_in);
22		write(client_sock, msg_out, sizeof(msg_out));
23	}
24	close(client_sock);
25}
26
27int main(int argc, char *argv[])
28{
29	int sock, client, client_addr_size;
30	struct sockaddr_in addr, client_addr;
31	
32	if (argc != 2) erro("srvx <porta>\n");
33	
34	memset(&addr, 0, sizeof(addr));
35	addr.sin_family = AF_INET;
36	addr.sin_addr.s_addr = htonl(INADDR_ANY);
37	addr.sin_port = htons((int) atoi(argv[1]));
38
39	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) erro("socket");
40	if (bind(sock,(struct sockaddr*)&addr,sizeof(addr)) < 0) erro("bind");
41	if (listen(sock, 5) < 0) erro("listen");
42	
43	while (1)
44	{
45		printf("Esperando conexao...\n");
46		client_addr_size = sizeof(client_addr);
47		client = accept(sock, (struct sockaddr *) &client_addr, &client_addr_size);
48		if (client > 0)
49		{
50			if (fork() == 0)
51			{
52				close(sock);
53				process_client(client);
54				exit(0);
55			}
56			close(client);
57		}
58	}
59	return 0;
60}