Comunicação entre Processos em C
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}